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

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

mercurial