1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/tools/internal/xjc/api/impl/s2j/SchemaCompilerImpl.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,324 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.internal.xjc.api.impl.s2j; 1.30 + 1.31 +import java.io.IOException; 1.32 +import java.net.MalformedURLException; 1.33 +import java.net.URI; 1.34 +import java.net.URISyntaxException; 1.35 +import java.net.URL; 1.36 + 1.37 +import javax.xml.XMLConstants; 1.38 +import javax.xml.stream.XMLStreamException; 1.39 +import javax.xml.stream.XMLStreamReader; 1.40 +import javax.xml.validation.SchemaFactory; 1.41 + 1.42 +import com.sun.codemodel.internal.JCodeModel; 1.43 +import com.sun.istack.internal.NotNull; 1.44 +import com.sun.istack.internal.SAXParseException2; 1.45 +import com.sun.tools.internal.xjc.ErrorReceiver; 1.46 +import com.sun.tools.internal.xjc.ModelLoader; 1.47 +import com.sun.tools.internal.xjc.Options; 1.48 +import com.sun.tools.internal.xjc.api.ClassNameAllocator; 1.49 +import com.sun.tools.internal.xjc.api.ErrorListener; 1.50 +import com.sun.tools.internal.xjc.api.SchemaCompiler; 1.51 +import com.sun.tools.internal.xjc.api.SpecVersion; 1.52 +import com.sun.tools.internal.xjc.model.Model; 1.53 +import com.sun.tools.internal.xjc.outline.Outline; 1.54 +import com.sun.tools.internal.xjc.reader.internalizer.DOMForest; 1.55 +import com.sun.tools.internal.xjc.reader.internalizer.SCDBasedBindingSet; 1.56 +import com.sun.tools.internal.xjc.reader.xmlschema.parser.LSInputSAXWrapper; 1.57 +import com.sun.tools.internal.xjc.reader.xmlschema.parser.XMLSchemaInternalizationLogic; 1.58 +import com.sun.xml.internal.bind.unmarshaller.DOMScanner; 1.59 +import com.sun.xml.internal.bind.v2.util.XmlFactory; 1.60 +import com.sun.xml.internal.xsom.XSSchemaSet; 1.61 + 1.62 +import org.w3c.dom.Element; 1.63 +import org.w3c.dom.ls.LSInput; 1.64 +import org.w3c.dom.ls.LSResourceResolver; 1.65 +import org.xml.sax.ContentHandler; 1.66 +import org.xml.sax.EntityResolver; 1.67 +import org.xml.sax.InputSource; 1.68 +import org.xml.sax.SAXException; 1.69 +import org.xml.sax.SAXParseException; 1.70 +import org.xml.sax.helpers.LocatorImpl; 1.71 + 1.72 +/** 1.73 + * {@link SchemaCompiler} implementation. 1.74 + * 1.75 + * This class builds a {@link DOMForest} until the {@link #bind()} method, 1.76 + * then this method does the rest of the hard work. 1.77 + * 1.78 + * @see ModelLoader 1.79 + * 1.80 + * @author 1.81 + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 1.82 + */ 1.83 +public final class SchemaCompilerImpl extends ErrorReceiver implements SchemaCompiler { 1.84 + 1.85 + /** 1.86 + * User-specified error receiver. 1.87 + * This field can be null, in which case errors need to be discarded. 1.88 + */ 1.89 + private ErrorListener errorListener; 1.90 + 1.91 + protected final Options opts = new Options(); 1.92 + 1.93 + protected @NotNull DOMForest forest; 1.94 + 1.95 + /** 1.96 + * Set to true once an error is found. 1.97 + */ 1.98 + private boolean hadError; 1.99 + 1.100 + public SchemaCompilerImpl() { 1.101 + opts.compatibilityMode = Options.EXTENSION; 1.102 + resetSchema(); 1.103 + 1.104 + if(System.getProperty("xjc-api.test")!=null) { 1.105 + opts.debugMode = true; 1.106 + opts.verbose = true; 1.107 + } 1.108 + } 1.109 + 1.110 + @NotNull 1.111 + public Options getOptions() { 1.112 + return opts; 1.113 + } 1.114 + 1.115 + public ContentHandler getParserHandler( String systemId ) { 1.116 + return forest.getParserHandler(systemId,true); 1.117 + } 1.118 + 1.119 + public void parseSchema( String systemId, Element element ) { 1.120 + checkAbsoluteness(systemId); 1.121 + try { 1.122 + DOMScanner scanner = new DOMScanner(); 1.123 + 1.124 + // use a locator that sets the system ID correctly 1.125 + // so that we can resolve relative URLs in most of the case. 1.126 + // it still doesn't handle xml:base and XInclude and all those things 1.127 + // correctly. There's just no way to make all those things work with DOM! 1.128 + LocatorImpl loc = new LocatorImpl(); 1.129 + loc.setSystemId(systemId); 1.130 + scanner.setLocator(loc); 1.131 + 1.132 + scanner.setContentHandler(getParserHandler(systemId)); 1.133 + scanner.scan(element); 1.134 + } catch (SAXException e) { 1.135 + // since parsing DOM shouldn't cause a SAX exception 1.136 + // and our handler will never throw it, it's not clear 1.137 + // if this will ever happen. 1.138 + fatalError(new SAXParseException2( 1.139 + e.getMessage(), null, systemId,-1,-1, e)); 1.140 + } 1.141 + } 1.142 + 1.143 + public void parseSchema(InputSource source) { 1.144 + checkAbsoluteness(source.getSystemId()); 1.145 + try { 1.146 + forest.parse(source,true); 1.147 + } catch (SAXException e) { 1.148 + // parsers are required to report an error to ErrorHandler, 1.149 + // so we should never see this error. 1.150 + e.printStackTrace(); 1.151 + } 1.152 + } 1.153 + 1.154 + public void setTargetVersion(SpecVersion version) { 1.155 + if(version==null) 1.156 + version = SpecVersion.LATEST; 1.157 + opts.target = version; 1.158 + } 1.159 + 1.160 + public void parseSchema(String systemId, XMLStreamReader reader) throws XMLStreamException { 1.161 + checkAbsoluteness(systemId); 1.162 + forest.parse(systemId,reader,true); 1.163 + } 1.164 + 1.165 + /** 1.166 + * Checks if the system ID is absolute. 1.167 + */ 1.168 + @SuppressWarnings("ResultOfObjectAllocationIgnored") 1.169 + private void checkAbsoluteness(String systemId) { 1.170 + // we need to be able to handle system IDs like "urn:foo", which java.net.URL can't process, 1.171 + // but OTOH we also need to be able to process system IDs like "file://a b c/def.xsd", 1.172 + // which java.net.URI can't process. So for now, let's fail only if both of them fail. 1.173 + // eventually we need a proper URI class that works for us. 1.174 + try { 1.175 + new URL(systemId); 1.176 + } catch( MalformedURLException mue) { 1.177 + try { 1.178 + new URI(systemId); 1.179 + } catch (URISyntaxException e ) { 1.180 + throw new IllegalArgumentException("system ID '"+systemId+"' isn't absolute",e); 1.181 + } 1.182 + } 1.183 + } 1.184 + 1.185 + public void setEntityResolver(EntityResolver entityResolver) { 1.186 + forest.setEntityResolver(entityResolver); 1.187 + opts.entityResolver = entityResolver; 1.188 + } 1.189 + 1.190 + public void setDefaultPackageName(String packageName) { 1.191 + opts.defaultPackage2 = packageName; 1.192 + } 1.193 + 1.194 + public void forcePackageName(String packageName) { 1.195 + opts.defaultPackage = packageName; 1.196 + } 1.197 + 1.198 + public void setClassNameAllocator(ClassNameAllocator allocator) { 1.199 + opts.classNameAllocator = allocator; 1.200 + } 1.201 + 1.202 + public void resetSchema() { 1.203 + forest = new DOMForest(new XMLSchemaInternalizationLogic(), opts); 1.204 + forest.setErrorHandler(this); 1.205 + forest.setEntityResolver(opts.entityResolver); 1.206 + } 1.207 + 1.208 + public JAXBModelImpl bind() { 1.209 + // this has been problematic. turn it off. 1.210 +// if(!forest.checkSchemaCorrectness(this)) 1.211 +// return null; 1.212 + 1.213 + // parse all the binding files given via XJC -b options. 1.214 + // this also takes care of the binding files given in the -episode option. 1.215 + for (InputSource is : opts.getBindFiles()) 1.216 + parseSchema(is); 1.217 + 1.218 + // internalization 1.219 + SCDBasedBindingSet scdBasedBindingSet = forest.transform(opts.isExtensionMode()); 1.220 + 1.221 + if (!NO_CORRECTNESS_CHECK) { 1.222 + // correctness check 1.223 + SchemaFactory sf = XmlFactory.createSchemaFactory(XMLConstants.W3C_XML_SCHEMA_NS_URI, opts.disableXmlSecurity); 1.224 + 1.225 + // fix for https://jaxb.dev.java.net/issues/show_bug.cgi?id=795 1.226 + // taken from SchemaConstraintChecker, TODO XXX FIXME UGLY 1.227 + if (opts.entityResolver != null) { 1.228 + sf.setResourceResolver(new LSResourceResolver() { 1.229 + public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { 1.230 + try { 1.231 + // XSOM passes the namespace URI to the publicID parameter. 1.232 + // we do the same here . 1.233 + InputSource is = opts.entityResolver.resolveEntity(namespaceURI, systemId); 1.234 + if (is == null) return null; 1.235 + return new LSInputSAXWrapper(is); 1.236 + } catch (SAXException e) { 1.237 + // TODO: is this sufficient? 1.238 + return null; 1.239 + } catch (IOException e) { 1.240 + // TODO: is this sufficient? 1.241 + return null; 1.242 + } 1.243 + } 1.244 + }); 1.245 + } 1.246 + 1.247 + sf.setErrorHandler(new DowngradingErrorHandler(this)); 1.248 + forest.weakSchemaCorrectnessCheck(sf); 1.249 + if (hadError) 1.250 + return null; // error in the correctness check. abort now 1.251 + } 1.252 + 1.253 + JCodeModel codeModel = new JCodeModel(); 1.254 + 1.255 + ModelLoader gl = new ModelLoader(opts,codeModel,this); 1.256 + try { 1.257 + XSSchemaSet result = gl.createXSOM(forest, scdBasedBindingSet); 1.258 + if(result==null) 1.259 + return null; 1.260 + 1.261 + // we need info about each field, so we go ahead and generate the 1.262 + // skeleton at this point. 1.263 + // REVISIT: we should separate FieldRenderer and FieldAccessor 1.264 + // so that accessors can be used before we build the code. 1.265 + Model model = gl.annotateXMLSchema(result); 1.266 + if(model==null) return null; 1.267 + 1.268 + if(hadError) return null; // if we have any error by now, abort 1.269 + 1.270 + model.setPackageLevelAnnotations(opts.packageLevelAnnotations); 1.271 + 1.272 + Outline context = model.generateCode(opts,this); 1.273 + if(context==null) return null; 1.274 + 1.275 + if(hadError) return null; 1.276 + 1.277 + return new JAXBModelImpl(context); 1.278 + } catch( SAXException e ) { 1.279 + // since XSOM uses our parser that scans DOM, 1.280 + // no parser error is possible. 1.281 + // all the other errors will be directed to ErrorReceiver 1.282 + // before it's thrown, so when the exception is thrown 1.283 + // the error should have already been reported. 1.284 + 1.285 + // thus ignore. 1.286 + return null; 1.287 + } 1.288 + } 1.289 + 1.290 + public void setErrorListener(ErrorListener errorListener) { 1.291 + this.errorListener = errorListener; 1.292 + } 1.293 + 1.294 + public void info(SAXParseException exception) { 1.295 + if(errorListener!=null) 1.296 + errorListener.info(exception); 1.297 + } 1.298 + public void warning(SAXParseException exception) { 1.299 + if(errorListener!=null) 1.300 + errorListener.warning(exception); 1.301 + } 1.302 + public void error(SAXParseException exception) { 1.303 + hadError = true; 1.304 + if(errorListener!=null) 1.305 + errorListener.error(exception); 1.306 + } 1.307 + public void fatalError(SAXParseException exception) { 1.308 + hadError = true; 1.309 + if(errorListener!=null) 1.310 + errorListener.fatalError(exception); 1.311 + } 1.312 + 1.313 + /** 1.314 + * We use JAXP 1.3 to do a schema correctness check, but we know 1.315 + * it doesn't always work. So in case some people hit the problem, 1.316 + * this switch is here so that they can turn it off as a workaround. 1.317 + */ 1.318 + private static boolean NO_CORRECTNESS_CHECK = false; 1.319 + 1.320 + static { 1.321 + try { 1.322 + NO_CORRECTNESS_CHECK = Boolean.getBoolean(SchemaCompilerImpl.class.getName()+".noCorrectnessCheck"); 1.323 + } catch( Throwable t) { 1.324 + // ignore 1.325 + } 1.326 + } 1.327 +}