src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/SchemaCompilerImpl.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, 2013, 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.api.impl.s2j;
    28 import java.io.IOException;
    29 import java.net.MalformedURLException;
    30 import java.net.URI;
    31 import java.net.URISyntaxException;
    32 import java.net.URL;
    34 import javax.xml.XMLConstants;
    35 import javax.xml.stream.XMLStreamException;
    36 import javax.xml.stream.XMLStreamReader;
    37 import javax.xml.validation.SchemaFactory;
    39 import com.sun.codemodel.internal.JCodeModel;
    40 import com.sun.istack.internal.NotNull;
    41 import com.sun.istack.internal.SAXParseException2;
    42 import com.sun.tools.internal.xjc.ErrorReceiver;
    43 import com.sun.tools.internal.xjc.ModelLoader;
    44 import com.sun.tools.internal.xjc.Options;
    45 import com.sun.tools.internal.xjc.api.ClassNameAllocator;
    46 import com.sun.tools.internal.xjc.api.ErrorListener;
    47 import com.sun.tools.internal.xjc.api.SchemaCompiler;
    48 import com.sun.tools.internal.xjc.api.SpecVersion;
    49 import com.sun.tools.internal.xjc.model.Model;
    50 import com.sun.tools.internal.xjc.outline.Outline;
    51 import com.sun.tools.internal.xjc.reader.internalizer.DOMForest;
    52 import com.sun.tools.internal.xjc.reader.internalizer.SCDBasedBindingSet;
    53 import com.sun.tools.internal.xjc.reader.xmlschema.parser.LSInputSAXWrapper;
    54 import com.sun.tools.internal.xjc.reader.xmlschema.parser.XMLSchemaInternalizationLogic;
    55 import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
    56 import com.sun.xml.internal.bind.v2.util.XmlFactory;
    57 import com.sun.xml.internal.xsom.XSSchemaSet;
    59 import org.w3c.dom.Element;
    60 import org.w3c.dom.ls.LSInput;
    61 import org.w3c.dom.ls.LSResourceResolver;
    62 import org.xml.sax.ContentHandler;
    63 import org.xml.sax.EntityResolver;
    64 import org.xml.sax.InputSource;
    65 import org.xml.sax.SAXException;
    66 import org.xml.sax.SAXParseException;
    67 import org.xml.sax.helpers.LocatorImpl;
    69 /**
    70  * {@link SchemaCompiler} implementation.
    71  *
    72  * This class builds a {@link DOMForest} until the {@link #bind()} method,
    73  * then this method does the rest of the hard work.
    74  *
    75  * @see ModelLoader
    76  *
    77  * @author
    78  *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
    79  */
    80 public final class SchemaCompilerImpl extends ErrorReceiver implements SchemaCompiler {
    82     /**
    83      * User-specified error receiver.
    84      * This field can be null, in which case errors need to be discarded.
    85      */
    86     private ErrorListener errorListener;
    88     protected final Options opts = new Options();
    90     protected @NotNull DOMForest forest;
    92     /**
    93      * Set to true once an error is found.
    94      */
    95     private boolean hadError;
    97     public SchemaCompilerImpl() {
    98         opts.compatibilityMode = Options.EXTENSION;
    99         resetSchema();
   101         if(System.getProperty("xjc-api.test")!=null) {
   102             opts.debugMode = true;
   103             opts.verbose = true;
   104         }
   105     }
   107     @NotNull
   108     public Options getOptions() {
   109         return opts;
   110     }
   112     public ContentHandler getParserHandler( String systemId ) {
   113         return forest.getParserHandler(systemId,true);
   114     }
   116     public void parseSchema( String systemId, Element element ) {
   117         checkAbsoluteness(systemId);
   118         try {
   119             DOMScanner scanner = new DOMScanner();
   121             // use a locator that sets the system ID correctly
   122             // so that we can resolve relative URLs in most of the case.
   123             // it still doesn't handle xml:base and XInclude and all those things
   124             // correctly. There's just no way to make all those things work with DOM!
   125             LocatorImpl loc = new LocatorImpl();
   126             loc.setSystemId(systemId);
   127             scanner.setLocator(loc);
   129             scanner.setContentHandler(getParserHandler(systemId));
   130             scanner.scan(element);
   131         } catch (SAXException e) {
   132             // since parsing DOM shouldn't cause a SAX exception
   133             // and our handler will never throw it, it's not clear
   134             // if this will ever happen.
   135             fatalError(new SAXParseException2(
   136                 e.getMessage(), null, systemId,-1,-1, e));
   137         }
   138     }
   140     public void parseSchema(InputSource source) {
   141         checkAbsoluteness(source.getSystemId());
   142         try {
   143             forest.parse(source,true);
   144         } catch (SAXException e) {
   145             // parsers are required to report an error to ErrorHandler,
   146             // so we should never see this error.
   147             e.printStackTrace();
   148         }
   149     }
   151     public void setTargetVersion(SpecVersion version) {
   152         if(version==null)
   153             version = SpecVersion.LATEST;
   154         opts.target = version;
   155     }
   157     public void parseSchema(String systemId, XMLStreamReader reader) throws XMLStreamException {
   158         checkAbsoluteness(systemId);
   159         forest.parse(systemId,reader,true);
   160     }
   162     /**
   163      * Checks if the system ID is absolute.
   164      */
   165     @SuppressWarnings("ResultOfObjectAllocationIgnored")
   166     private void checkAbsoluteness(String systemId) {
   167         // we need to be able to handle system IDs like "urn:foo", which java.net.URL can't process,
   168         // but OTOH we also need to be able to process system IDs like "file://a b c/def.xsd",
   169         // which java.net.URI can't process. So for now, let's fail only if both of them fail.
   170         // eventually we need a proper URI class that works for us.
   171         try {
   172             new URL(systemId);
   173         } catch( MalformedURLException mue) {
   174             try {
   175                 new URI(systemId);
   176             } catch (URISyntaxException e ) {
   177                 throw new IllegalArgumentException("system ID '"+systemId+"' isn't absolute",e);
   178             }
   179         }
   180     }
   182     public void setEntityResolver(EntityResolver entityResolver) {
   183         forest.setEntityResolver(entityResolver);
   184         opts.entityResolver = entityResolver;
   185     }
   187     public void setDefaultPackageName(String packageName) {
   188         opts.defaultPackage2 = packageName;
   189     }
   191     public void forcePackageName(String packageName) {
   192         opts.defaultPackage = packageName;
   193     }
   195     public void setClassNameAllocator(ClassNameAllocator allocator) {
   196         opts.classNameAllocator = allocator;
   197     }
   199     public void resetSchema() {
   200         forest = new DOMForest(new XMLSchemaInternalizationLogic(), opts);
   201         forest.setErrorHandler(this);
   202         forest.setEntityResolver(opts.entityResolver);
   203     }
   205     public JAXBModelImpl bind() {
   206         // this has been problematic. turn it off.
   207 //        if(!forest.checkSchemaCorrectness(this))
   208 //            return null;
   210         // parse all the binding files given via XJC -b options.
   211         // this also takes care of the binding files given in the -episode option.
   212         for (InputSource is : opts.getBindFiles())
   213             parseSchema(is);
   215         // internalization
   216         SCDBasedBindingSet scdBasedBindingSet = forest.transform(opts.isExtensionMode());
   218         if (!NO_CORRECTNESS_CHECK) {
   219             // correctness check
   220             SchemaFactory sf = XmlFactory.createSchemaFactory(XMLConstants.W3C_XML_SCHEMA_NS_URI, opts.disableXmlSecurity);
   222             // fix for https://jaxb.dev.java.net/issues/show_bug.cgi?id=795
   223             // taken from SchemaConstraintChecker, TODO XXX FIXME UGLY
   224             if (opts.entityResolver != null) {
   225                 sf.setResourceResolver(new LSResourceResolver() {
   226                     public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
   227                         try {
   228                             // XSOM passes the namespace URI to the publicID parameter.
   229                             // we do the same here .
   230                             InputSource is = opts.entityResolver.resolveEntity(namespaceURI, systemId);
   231                             if (is == null) return null;
   232                             return new LSInputSAXWrapper(is);
   233                         } catch (SAXException e) {
   234                             // TODO: is this sufficient?
   235                             return null;
   236                         } catch (IOException e) {
   237                             // TODO: is this sufficient?
   238                             return null;
   239                         }
   240                     }
   241                 });
   242             }
   244             sf.setErrorHandler(new DowngradingErrorHandler(this));
   245             forest.weakSchemaCorrectnessCheck(sf);
   246             if (hadError)
   247                 return null;    // error in the correctness check. abort now
   248         }
   250         JCodeModel codeModel = new JCodeModel();
   252         ModelLoader gl = new ModelLoader(opts,codeModel,this);
   253         try {
   254             XSSchemaSet result = gl.createXSOM(forest, scdBasedBindingSet);
   255             if(result==null)
   256                 return null;
   258             // we need info about each field, so we go ahead and generate the
   259             // skeleton at this point.
   260             // REVISIT: we should separate FieldRenderer and FieldAccessor
   261             // so that accessors can be used before we build the code.
   262             Model model = gl.annotateXMLSchema(result);
   263             if(model==null)   return null;
   265             if(hadError)        return null;    // if we have any error by now, abort
   267             model.setPackageLevelAnnotations(opts.packageLevelAnnotations);
   269             Outline context = model.generateCode(opts,this);
   270             if(context==null)   return null;
   272             if(hadError)        return null;
   274             return new JAXBModelImpl(context);
   275         } catch( SAXException e ) {
   276             // since XSOM uses our parser that scans DOM,
   277             // no parser error is possible.
   278             // all the other errors will be directed to ErrorReceiver
   279             // before it's thrown, so when the exception is thrown
   280             // the error should have already been reported.
   282             // thus ignore.
   283             return null;
   284         }
   285     }
   287     public void setErrorListener(ErrorListener errorListener) {
   288         this.errorListener = errorListener;
   289     }
   291     public void info(SAXParseException exception) {
   292         if(errorListener!=null)
   293             errorListener.info(exception);
   294     }
   295     public void warning(SAXParseException exception) {
   296         if(errorListener!=null)
   297             errorListener.warning(exception);
   298     }
   299     public void error(SAXParseException exception) {
   300         hadError = true;
   301         if(errorListener!=null)
   302             errorListener.error(exception);
   303     }
   304     public void fatalError(SAXParseException exception) {
   305         hadError = true;
   306         if(errorListener!=null)
   307             errorListener.fatalError(exception);
   308     }
   310     /**
   311      * We use JAXP 1.3 to do a schema correctness check, but we know
   312      * it doesn't always work. So in case some people hit the problem,
   313      * this switch is here so that they can turn it off as a workaround.
   314      */
   315     private static boolean NO_CORRECTNESS_CHECK = false;
   317     static {
   318         try {
   319             NO_CORRECTNESS_CHECK = Boolean.getBoolean(SchemaCompilerImpl.class.getName()+".noCorrectnessCheck");
   320         } catch( Throwable t) {
   321             // ignore
   322         }
   323     }
   324 }

mercurial