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

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

mercurial