src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/SCDBasedBindingSet.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.tools.internal.xjc.reader.internalizer;
aoqi@0 27
aoqi@0 28 import java.util.ArrayList;
aoqi@0 29 import java.util.Collection;
aoqi@0 30 import java.util.Iterator;
aoqi@0 31 import java.util.List;
aoqi@0 32
aoqi@0 33 import javax.xml.bind.JAXBException;
aoqi@0 34 import javax.xml.bind.Unmarshaller;
aoqi@0 35 import javax.xml.bind.UnmarshallerHandler;
aoqi@0 36 import javax.xml.validation.ValidatorHandler;
aoqi@0 37
aoqi@0 38 import com.sun.istack.internal.NotNull;
aoqi@0 39 import com.sun.istack.internal.SAXParseException2;
aoqi@0 40 import com.sun.tools.internal.xjc.ErrorReceiver;
aoqi@0 41 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
aoqi@0 42 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
aoqi@0 43 import com.sun.tools.internal.xjc.util.ForkContentHandler;
aoqi@0 44 import com.sun.tools.internal.xjc.util.DOMUtils;
aoqi@0 45 import com.sun.xml.internal.xsom.SCD;
aoqi@0 46 import com.sun.xml.internal.xsom.XSAnnotation;
aoqi@0 47 import com.sun.xml.internal.xsom.XSComponent;
aoqi@0 48 import com.sun.xml.internal.xsom.XSSchemaSet;
aoqi@0 49
aoqi@0 50 import org.w3c.dom.Element;
aoqi@0 51 import org.xml.sax.SAXException;
aoqi@0 52 import org.xml.sax.SAXParseException;
aoqi@0 53
aoqi@0 54 /**
aoqi@0 55 * Set of binding nodes that have target nodes specified via SCD.
aoqi@0 56 *
aoqi@0 57 * This is parsed during {@link Internalizer} works on the tree,
aoqi@0 58 * but applying this has to wait for {@link XSSchemaSet} to be parsed.
aoqi@0 59 *
aoqi@0 60 * @author Kohsuke Kawaguchi
aoqi@0 61 * @see SCD
aoqi@0 62 */
aoqi@0 63 public final class SCDBasedBindingSet {
aoqi@0 64
aoqi@0 65 /**
aoqi@0 66 * Represents the target schema component of the
aoqi@0 67 * customization identified by SCD.
aoqi@0 68 *
aoqi@0 69 * @author Kohsuke Kawaguchi
aoqi@0 70 */
aoqi@0 71 final class Target {
aoqi@0 72 /**
aoqi@0 73 * SCDs can be specified via multiple steps, like:
aoqi@0 74 *
aoqi@0 75 * <xmp>
aoqi@0 76 * <bindings scd="foo/bar">
aoqi@0 77 * <bindings scd="zot/xyz">
aoqi@0 78 * </xmp>
aoqi@0 79 *
aoqi@0 80 * This field and {@link #nextSibling} form a single-linked list that
aoqi@0 81 * represent the children that shall be evaluated within this target.
aoqi@0 82 * Think of it as {@code List<Target>}.
aoqi@0 83 */
aoqi@0 84 private Target firstChild;
aoqi@0 85 private final Target nextSibling;
aoqi@0 86
aoqi@0 87 /**
aoqi@0 88 * Compiled SCD.
aoqi@0 89 */
aoqi@0 90 private final @NotNull SCD scd;
aoqi@0 91
aoqi@0 92 /**
aoqi@0 93 * The element on which SCD was found.
aoqi@0 94 */
aoqi@0 95 private final @NotNull Element src;
aoqi@0 96
aoqi@0 97 /**
aoqi@0 98 * Bindings that apply to this SCD.
aoqi@0 99 */
aoqi@0 100 private final List<Element> bindings = new ArrayList<Element>();
aoqi@0 101
aoqi@0 102 private Target(Target parent, Element src, SCD scd) {
aoqi@0 103 if(parent==null) {
aoqi@0 104 this.nextSibling = topLevel;
aoqi@0 105 topLevel = this;
aoqi@0 106 } else {
aoqi@0 107 this.nextSibling = parent.firstChild;
aoqi@0 108 parent.firstChild = this;
aoqi@0 109 }
aoqi@0 110 this.src = src;
aoqi@0 111 this.scd = scd;
aoqi@0 112 }
aoqi@0 113
aoqi@0 114 /**
aoqi@0 115 * Adds a new binding declaration to be associated to the schema component
aoqi@0 116 * identified by {@link #scd}.
aoqi@0 117 */
aoqi@0 118 void addBinidng(Element binding) {
aoqi@0 119 bindings.add(binding);
aoqi@0 120 }
aoqi@0 121
aoqi@0 122 /**
aoqi@0 123 * Applies bindings to the schema component for this and its siblings.
aoqi@0 124 */
aoqi@0 125 private void applyAll(Collection<? extends XSComponent> contextNode) {
aoqi@0 126 for( Target self=this; self!=null; self=self.nextSibling )
aoqi@0 127 self.apply(contextNode);
aoqi@0 128 }
aoqi@0 129
aoqi@0 130 /**
aoqi@0 131 * Applies bindings to the schema component for just this node.
aoqi@0 132 */
aoqi@0 133 private void apply(Collection<? extends XSComponent> contextNode) {
aoqi@0 134 // apply the SCD...
aoqi@0 135 Collection<XSComponent> childNodes = scd.select(contextNode);
aoqi@0 136 if(childNodes.isEmpty()) {
aoqi@0 137 // no node matched
aoqi@0 138 if(src.getAttributeNode("if-exists")!=null) {
aoqi@0 139 // if this attribute exists, it's not an error if SCD didn't match.
aoqi@0 140 return;
aoqi@0 141 }
aoqi@0 142
aoqi@0 143 reportError( src, Messages.format(Messages.ERR_SCD_EVALUATED_EMPTY,scd) );
aoqi@0 144 return;
aoqi@0 145 }
aoqi@0 146
aoqi@0 147 if(firstChild!=null)
aoqi@0 148 firstChild.applyAll(childNodes);
aoqi@0 149
aoqi@0 150 if(!bindings.isEmpty()) {
aoqi@0 151 // error to match more than one components
aoqi@0 152 Iterator<XSComponent> itr = childNodes.iterator();
aoqi@0 153 XSComponent target = itr.next();
aoqi@0 154 if(itr.hasNext()) {
aoqi@0 155 reportError( src, Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES,scd,childNodes.size()) );
aoqi@0 156 errorReceiver.error( target.getLocator(), Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES_FIRST) );
aoqi@0 157 errorReceiver.error( itr.next().getLocator(), Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES_SECOND) );
aoqi@0 158 }
aoqi@0 159
aoqi@0 160 // apply bindings to the target
aoqi@0 161 for (Element binding : bindings) {
aoqi@0 162 for (Element item : DOMUtils.getChildElements(binding)) {
aoqi@0 163 String localName = item.getLocalName();
aoqi@0 164
aoqi@0 165 if ("bindings".equals(localName))
aoqi@0 166 continue; // this should be already in Target.bindings of some SpecVersion.
aoqi@0 167
aoqi@0 168 try {
aoqi@0 169 new DOMForestScanner(forest).scan(item,loader);
aoqi@0 170 BIDeclaration decl = (BIDeclaration)unmarshaller.getResult();
aoqi@0 171
aoqi@0 172 // add this binding to the target
aoqi@0 173 XSAnnotation ann = target.getAnnotation(true);
aoqi@0 174 BindInfo bi = (BindInfo)ann.getAnnotation();
aoqi@0 175 if(bi==null) {
aoqi@0 176 bi = new BindInfo();
aoqi@0 177 ann.setAnnotation(bi);
aoqi@0 178 }
aoqi@0 179 bi.addDecl(decl);
aoqi@0 180 } catch (SAXException e) {
aoqi@0 181 // the error should have already been reported.
aoqi@0 182 } catch (JAXBException e) {
aoqi@0 183 // if validation didn't fail, then unmarshalling can't go wrong
aoqi@0 184 throw new AssertionError(e);
aoqi@0 185 }
aoqi@0 186 }
aoqi@0 187 }
aoqi@0 188 }
aoqi@0 189 }
aoqi@0 190 }
aoqi@0 191
aoqi@0 192 private Target topLevel;
aoqi@0 193
aoqi@0 194 /**
aoqi@0 195 * The forest where binding elements came from. Needed to report line numbers for errors.
aoqi@0 196 */
aoqi@0 197 private final DOMForest forest;
aoqi@0 198
aoqi@0 199
aoqi@0 200 // variables used only during the apply method
aoqi@0 201 //
aoqi@0 202 private ErrorReceiver errorReceiver;
aoqi@0 203 private UnmarshallerHandler unmarshaller;
aoqi@0 204 private ForkContentHandler loader; // unmarshaller+validator
aoqi@0 205
aoqi@0 206 SCDBasedBindingSet(DOMForest forest) {
aoqi@0 207 this.forest = forest;
aoqi@0 208 }
aoqi@0 209
aoqi@0 210 Target createNewTarget(Target parent, Element src, SCD scd) {
aoqi@0 211 return new Target(parent,src,scd);
aoqi@0 212 }
aoqi@0 213
aoqi@0 214 /**
aoqi@0 215 * Applies the additional binding customizations.
aoqi@0 216 */
aoqi@0 217 public void apply(XSSchemaSet schema, ErrorReceiver errorReceiver) {
aoqi@0 218 if(topLevel!=null) {
aoqi@0 219 this.errorReceiver = errorReceiver;
aoqi@0 220 Unmarshaller u = BindInfo.getCustomizationUnmarshaller();
aoqi@0 221 this.unmarshaller = u.getUnmarshallerHandler();
aoqi@0 222 ValidatorHandler v = BindInfo.bindingFileSchema.newValidator();
aoqi@0 223 v.setErrorHandler(errorReceiver);
aoqi@0 224 loader = new ForkContentHandler(v,unmarshaller);
aoqi@0 225
aoqi@0 226 topLevel.applyAll(schema.getSchemas());
aoqi@0 227
aoqi@0 228 this.loader = null;
aoqi@0 229 this.unmarshaller = null;
aoqi@0 230 this.errorReceiver = null;
aoqi@0 231 }
aoqi@0 232 }
aoqi@0 233
aoqi@0 234 private void reportError( Element errorSource, String formattedMsg ) {
aoqi@0 235 reportError( errorSource, formattedMsg, null );
aoqi@0 236 }
aoqi@0 237
aoqi@0 238 private void reportError( Element errorSource,
aoqi@0 239 String formattedMsg, Exception nestedException ) {
aoqi@0 240
aoqi@0 241 SAXParseException e = new SAXParseException2( formattedMsg,
aoqi@0 242 forest.locatorTable.getStartLocation(errorSource),
aoqi@0 243 nestedException );
aoqi@0 244 errorReceiver.error(e);
aoqi@0 245 }
aoqi@0 246 }

mercurial