src/share/jaxws_classes/com/sun/tools/internal/xjc/ModelLoader.java

Tue, 09 Apr 2013 14:51:13 +0100

author
alanb
date
Tue, 09 Apr 2013 14:51:13 +0100
changeset 368
0989ad8c0860
parent 286
f50545b5e2f1
child 637
9c07ef4934dd
permissions
-rw-r--r--

8010393: Update JAX-WS RI to 2.2.9-b12941
Reviewed-by: alanb, erikj
Contributed-by: miroslav.kos@oracle.com, martin.grebac@oracle.com

ohair@286 1 /*
alanb@368 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
ohair@286 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286 4 *
ohair@286 5 * This code is free software; you can redistribute it and/or modify it
ohair@286 6 * under the terms of the GNU General Public License version 2 only, as
ohair@286 7 * published by the Free Software Foundation. Oracle designates this
ohair@286 8 * particular file as subject to the "Classpath" exception as provided
ohair@286 9 * by Oracle in the LICENSE file that accompanied this code.
ohair@286 10 *
ohair@286 11 * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286 14 * version 2 for more details (a copy is included in the LICENSE file that
ohair@286 15 * accompanied this code).
ohair@286 16 *
ohair@286 17 * You should have received a copy of the GNU General Public License version
ohair@286 18 * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286 20 *
ohair@286 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286 22 * or visit www.oracle.com if you need additional information or have any
ohair@286 23 * questions.
ohair@286 24 */
ohair@286 25
ohair@286 26 package com.sun.tools.internal.xjc;
ohair@286 27
ohair@286 28 import java.io.IOException;
ohair@286 29 import java.io.StringReader;
ohair@286 30
ohair@286 31 import com.sun.codemodel.internal.JCodeModel;
ohair@286 32 import com.sun.tools.internal.xjc.model.Model;
ohair@286 33 import com.sun.tools.internal.xjc.reader.Const;
ohair@286 34 import com.sun.tools.internal.xjc.reader.ExtensionBindingChecker;
ohair@286 35 import com.sun.tools.internal.xjc.reader.dtd.TDTDReader;
ohair@286 36 import com.sun.tools.internal.xjc.reader.internalizer.DOMForest;
ohair@286 37 import com.sun.tools.internal.xjc.reader.internalizer.DOMForestScanner;
ohair@286 38 import com.sun.tools.internal.xjc.reader.internalizer.InternalizationLogic;
ohair@286 39 import com.sun.tools.internal.xjc.reader.internalizer.SCDBasedBindingSet;
ohair@286 40 import com.sun.tools.internal.xjc.reader.internalizer.VersionChecker;
ohair@286 41 import com.sun.tools.internal.xjc.reader.relaxng.RELAXNGCompiler;
ohair@286 42 import com.sun.tools.internal.xjc.reader.relaxng.RELAXNGInternalizationLogic;
ohair@286 43 import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder;
ohair@286 44 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.AnnotationParserFactoryImpl;
ohair@286 45 import com.sun.tools.internal.xjc.reader.xmlschema.parser.CustomizationContextChecker;
ohair@286 46 import com.sun.tools.internal.xjc.reader.xmlschema.parser.IncorrectNamespaceURIChecker;
ohair@286 47 import com.sun.tools.internal.xjc.reader.xmlschema.parser.SchemaConstraintChecker;
ohair@286 48 import com.sun.tools.internal.xjc.reader.xmlschema.parser.XMLSchemaInternalizationLogic;
ohair@286 49 import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
alanb@368 50 import com.sun.xml.internal.bind.v2.util.XmlFactory;
ohair@286 51 import com.sun.xml.internal.xsom.XSSchemaSet;
ohair@286 52 import com.sun.xml.internal.xsom.parser.JAXPParser;
ohair@286 53 import com.sun.xml.internal.xsom.parser.XMLParser;
ohair@286 54 import com.sun.xml.internal.xsom.parser.XSOMParser;
ohair@286 55 import javax.xml.XMLConstants;
ohair@286 56
ohair@286 57 import com.sun.xml.internal.rngom.ast.builder.SchemaBuilder;
ohair@286 58 import com.sun.xml.internal.rngom.ast.util.CheckingSchemaBuilder;
ohair@286 59 import com.sun.xml.internal.rngom.digested.DPattern;
ohair@286 60 import com.sun.xml.internal.rngom.digested.DSchemaBuilderImpl;
ohair@286 61 import com.sun.xml.internal.rngom.parse.IllegalSchemaException;
ohair@286 62 import com.sun.xml.internal.rngom.parse.Parseable;
ohair@286 63 import com.sun.xml.internal.rngom.parse.compact.CompactParseable;
ohair@286 64 import com.sun.xml.internal.rngom.parse.xml.SAXParseable;
ohair@286 65 import com.sun.xml.internal.rngom.xml.sax.XMLReaderCreator;
ohair@286 66 import org.w3c.dom.Document;
ohair@286 67 import org.w3c.dom.Element;
ohair@286 68 import org.w3c.dom.NodeList;
ohair@286 69 import org.xml.sax.Attributes;
ohair@286 70 import org.xml.sax.ContentHandler;
ohair@286 71 import org.xml.sax.EntityResolver;
ohair@286 72 import org.xml.sax.ErrorHandler;
ohair@286 73 import org.xml.sax.InputSource;
ohair@286 74 import org.xml.sax.SAXException;
ohair@286 75 import org.xml.sax.SAXParseException;
ohair@286 76 import org.xml.sax.XMLFilter;
ohair@286 77 import org.xml.sax.XMLReader;
ohair@286 78 import org.xml.sax.helpers.XMLFilterImpl;
ohair@286 79
ohair@286 80 /**
ohair@286 81 * Builds a {@link Model} object.
ohair@286 82 *
ohair@286 83 * This is an utility class that makes it easy to load a grammar object
ohair@286 84 * from various sources.
ohair@286 85 *
ohair@286 86 * @author
ohair@286 87 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
ohair@286 88 */
ohair@286 89 public final class ModelLoader {
ohair@286 90
ohair@286 91 private final Options opt;
ohair@286 92 private final ErrorReceiverFilter errorReceiver;
ohair@286 93 private final JCodeModel codeModel;
ohair@286 94 /**
ohair@286 95 * {@link DOMForest#transform(boolean)} creates this on the side.
ohair@286 96 */
ohair@286 97 private SCDBasedBindingSet scdBasedBindingSet;
ohair@286 98
ohair@286 99
ohair@286 100 /**
ohair@286 101 * A convenience method to load schemas into a {@link Model}.
ohair@286 102 */
ohair@286 103 public static Model load( Options opt, JCodeModel codeModel, ErrorReceiver er ) {
ohair@286 104 return new ModelLoader(opt,codeModel,er).load();
ohair@286 105 }
ohair@286 106
ohair@286 107
ohair@286 108 public ModelLoader(Options _opt, JCodeModel _codeModel, ErrorReceiver er) {
ohair@286 109 this.opt = _opt;
ohair@286 110 this.codeModel = _codeModel;
ohair@286 111 this.errorReceiver = new ErrorReceiverFilter(er);
ohair@286 112 }
ohair@286 113
ohair@286 114 @SuppressWarnings("CallToThreadDumpStack")
ohair@286 115 private Model load() {
ohair@286 116 Model grammar;
ohair@286 117
ohair@286 118 if(!sanityCheck())
ohair@286 119 return null;
ohair@286 120
ohair@286 121
ohair@286 122 try {
ohair@286 123 switch (opt.getSchemaLanguage()) {
ohair@286 124 case DTD :
ohair@286 125 // TODO: make sure that bindFiles,size()<=1
ohair@286 126 InputSource bindFile = null;
ohair@286 127 if (opt.getBindFiles().length > 0)
ohair@286 128 bindFile = opt.getBindFiles()[0];
ohair@286 129 // if there is no binding file, make a dummy one.
ohair@286 130 if (bindFile == null) {
ohair@286 131 // if no binding information is specified, provide a default
ohair@286 132 bindFile =
ohair@286 133 new InputSource(
ohair@286 134 new StringReader(
ohair@286 135 "<?xml version='1.0'?><xml-java-binding-schema><options package='"
ohair@286 136 + (opt.defaultPackage==null?"generated":opt.defaultPackage)
ohair@286 137 + "'/></xml-java-binding-schema>"));
ohair@286 138 }
ohair@286 139
ohair@286 140 checkTooManySchemaErrors();
ohair@286 141 grammar = loadDTD(opt.getGrammars()[0], bindFile );
ohair@286 142 break;
ohair@286 143
ohair@286 144 case RELAXNG :
ohair@286 145 checkTooManySchemaErrors();
ohair@286 146 grammar = loadRELAXNG();
ohair@286 147 break;
ohair@286 148
ohair@286 149 case RELAXNG_COMPACT :
ohair@286 150 checkTooManySchemaErrors();
ohair@286 151 grammar = loadRELAXNGCompact();
ohair@286 152 break;
ohair@286 153
ohair@286 154 case WSDL:
ohair@286 155 grammar = annotateXMLSchema( loadWSDL() );
ohair@286 156 break;
ohair@286 157
ohair@286 158 case XMLSCHEMA:
ohair@286 159 grammar = annotateXMLSchema( loadXMLSchema() );
ohair@286 160 break;
ohair@286 161
ohair@286 162 default :
ohair@286 163 throw new AssertionError(); // assertion failed
ohair@286 164 }
ohair@286 165
ohair@286 166 if (errorReceiver.hadError()) {
ohair@286 167 grammar = null;
ohair@286 168 } else {
ohair@286 169 grammar.setPackageLevelAnnotations(opt.packageLevelAnnotations);
ohair@286 170 }
ohair@286 171
ohair@286 172 return grammar;
ohair@286 173
ohair@286 174 } catch (SAXException e) {
ohair@286 175 // parsing error in the input document.
ohair@286 176 // this error must have been reported to the user vis error handler
ohair@286 177 // so don't print it again.
ohair@286 178 if (opt.verbose) {
ohair@286 179 // however, a bug in XJC might throw unexpected SAXException.
ohair@286 180 // thus when one is debugging, it is useful to print what went
ohair@286 181 // wrong.
ohair@286 182 if (e.getException() != null)
ohair@286 183 e.getException().printStackTrace();
ohair@286 184 else
ohair@286 185 e.printStackTrace();
ohair@286 186 }
ohair@286 187 return null;
ohair@286 188 } catch (AbortException e) {
ohair@286 189 // error should have been reported already, since this is requested by the error receiver
ohair@286 190 return null;
ohair@286 191 }
ohair@286 192 }
ohair@286 193
ohair@286 194
ohair@286 195
ohair@286 196 /**
ohair@286 197 * Do some extra checking and return false if the compilation
ohair@286 198 * should abort.
ohair@286 199 */
ohair@286 200 private boolean sanityCheck() {
ohair@286 201 if( opt.getSchemaLanguage()==Language.XMLSCHEMA ) {
ohair@286 202 Language guess = opt.guessSchemaLanguage();
ohair@286 203
ohair@286 204 String[] msg = null;
ohair@286 205 switch(guess) {
ohair@286 206 case DTD:
ohair@286 207 msg = new String[]{"DTD","-dtd"};
ohair@286 208 break;
ohair@286 209 case RELAXNG:
ohair@286 210 msg = new String[]{"RELAX NG","-relaxng"};
ohair@286 211 break;
ohair@286 212 case RELAXNG_COMPACT:
ohair@286 213 msg = new String[]{"RELAX NG compact syntax","-relaxng-compact"};
ohair@286 214 break;
ohair@286 215 case WSDL:
ohair@286 216 msg = new String[]{"WSDL","-wsdl"};
ohair@286 217 break;
ohair@286 218 }
ohair@286 219 if( msg!=null )
ohair@286 220 errorReceiver.warning( null,
ohair@286 221 Messages.format(
ohair@286 222 Messages.EXPERIMENTAL_LANGUAGE_WARNING,
ohair@286 223 msg[0], msg[1] ));
ohair@286 224 }
ohair@286 225 return true;
ohair@286 226 }
ohair@286 227
ohair@286 228
ohair@286 229 /**
ohair@286 230 * {@link XMLParser} implementation that adds additional processors into the chain.
ohair@286 231 *
ohair@286 232 * <p>
ohair@286 233 * This parser will parse a DOM forest as:
ohair@286 234 * DOMForestParser -->
ohair@286 235 * ExtensionBindingChecker -->
ohair@286 236 * ProhibitedFeatureFilter -->
ohair@286 237 * XSOMParser
ohair@286 238 */
ohair@286 239 private class XMLSchemaParser implements XMLParser {
ohair@286 240 private final XMLParser baseParser;
ohair@286 241
ohair@286 242 private XMLSchemaParser(XMLParser baseParser) {
ohair@286 243 this.baseParser = baseParser;
ohair@286 244 }
ohair@286 245
ohair@286 246 public void parse(InputSource source, ContentHandler handler,
ohair@286 247 ErrorHandler errorHandler, EntityResolver entityResolver ) throws SAXException, IOException {
ohair@286 248 // set up the chain of handlers.
ohair@286 249 handler = wrapBy( new ExtensionBindingChecker(XMLConstants.W3C_XML_SCHEMA_NS_URI,opt,errorReceiver), handler );
ohair@286 250 handler = wrapBy( new IncorrectNamespaceURIChecker(errorReceiver), handler );
ohair@286 251 handler = wrapBy( new CustomizationContextChecker(errorReceiver), handler );
ohair@286 252 // handler = wrapBy( new VersionChecker(controller), handler );
ohair@286 253
ohair@286 254 baseParser.parse( source, handler, errorHandler, entityResolver );
ohair@286 255 }
ohair@286 256 /**
ohair@286 257 * Wraps the specified content handler by a filter.
ohair@286 258 * It is little awkward to use a helper implementation class like XMLFilterImpl
ohair@286 259 * as the method parameter, but this simplifies the code.
ohair@286 260 */
ohair@286 261 private ContentHandler wrapBy( XMLFilterImpl filter, ContentHandler handler ) {
ohair@286 262 filter.setContentHandler(handler);
ohair@286 263 return filter;
ohair@286 264 }
ohair@286 265 }
ohair@286 266
ohair@286 267 private void checkTooManySchemaErrors() {
ohair@286 268 if( opt.getGrammars().length!=1 )
ohair@286 269 errorReceiver.error(null,Messages.format(Messages.ERR_TOO_MANY_SCHEMA));
ohair@286 270 }
ohair@286 271
ohair@286 272 /**
ohair@286 273 * Parses a DTD file into an annotated grammar.
ohair@286 274 *
ohair@286 275 * @param source
ohair@286 276 * DTD file
ohair@286 277 * @param bindFile
ohair@286 278 * External binding file.
ohair@286 279 */
ohair@286 280 private Model loadDTD( InputSource source, InputSource bindFile) {
ohair@286 281
ohair@286 282 // parse the schema as a DTD.
ohair@286 283 return TDTDReader.parse(
ohair@286 284 source,
ohair@286 285 bindFile,
ohair@286 286 errorReceiver,
ohair@286 287 opt);
ohair@286 288 }
ohair@286 289
ohair@286 290 /**
ohair@286 291 * Builds DOMForest and performs the internalization.
ohair@286 292 *
ohair@286 293 * @throws SAXException
ohair@286 294 * when a fatal error happens
ohair@286 295 */
ohair@286 296 public DOMForest buildDOMForest( InternalizationLogic logic )
ohair@286 297 throws SAXException {
ohair@286 298
ohair@286 299 // parse into DOM forest
alanb@368 300 DOMForest forest = new DOMForest(logic, opt);
ohair@286 301
ohair@286 302 forest.setErrorHandler(errorReceiver);
ohair@286 303 if(opt.entityResolver!=null)
ohair@286 304 forest.setEntityResolver(opt.entityResolver);
ohair@286 305
ohair@286 306 // parse source grammars
ohair@286 307 for (InputSource value : opt.getGrammars()) {
ohair@286 308 errorReceiver.pollAbort();
ohair@286 309 forest.parse(value, true);
ohair@286 310 }
ohair@286 311
ohair@286 312 // parse external binding files
ohair@286 313 for (InputSource value : opt.getBindFiles()) {
ohair@286 314 errorReceiver.pollAbort();
ohair@286 315 Document dom = forest.parse(value, true);
ohair@286 316 if(dom==null) continue; // error must have been reported
ohair@286 317 Element root = dom.getDocumentElement();
ohair@286 318 // TODO: it somehow doesn't feel right to do a validation in the Driver class.
ohair@286 319 // think about moving it to somewhere else.
ohair@286 320 if (!fixNull(root.getNamespaceURI()).equals(Const.JAXB_NSURI)
ohair@286 321 || !root.getLocalName().equals("bindings"))
ohair@286 322 errorReceiver.error(new SAXParseException(Messages.format(Messages.ERR_NOT_A_BINDING_FILE,
ohair@286 323 root.getNamespaceURI(),
ohair@286 324 root.getLocalName()),
ohair@286 325 null,
ohair@286 326 value.getSystemId(),
ohair@286 327 -1, -1));
ohair@286 328 }
ohair@286 329
ohair@286 330 scdBasedBindingSet = forest.transform(opt.isExtensionMode());
ohair@286 331
ohair@286 332 return forest;
ohair@286 333 }
ohair@286 334
ohair@286 335 private String fixNull(String s) {
ohair@286 336 if(s==null) return "";
ohair@286 337 else return s;
ohair@286 338 }
ohair@286 339
ohair@286 340 /**
ohair@286 341 * Parses a set of XML Schema files into an annotated grammar.
ohair@286 342 */
ohair@286 343 public XSSchemaSet loadXMLSchema() throws SAXException {
ohair@286 344
alanb@368 345 if( opt.strictCheck && !SchemaConstraintChecker.check(opt.getGrammars(),errorReceiver,opt.entityResolver, opt.disableXmlSecurity)) {
ohair@286 346 // schema error. error should have been reported
ohair@286 347 return null;
ohair@286 348 }
ohair@286 349
ohair@286 350 if(opt.getBindFiles().length==0) {
ohair@286 351 // no external binding. try the speculative no DOMForest execution,
ohair@286 352 // which is faster if the speculation succeeds.
ohair@286 353 try {
ohair@286 354 return createXSOMSpeculative();
alanb@368 355 } catch( SpeculationFailure e) {
ohair@286 356 // failed. go the slow way
ohair@286 357 }
ohair@286 358 }
ohair@286 359
ohair@286 360 // the default slower way is to parse everything into DOM first.
ohair@286 361 // so that we can take external annotations into account.
ohair@286 362 DOMForest forest = buildDOMForest( new XMLSchemaInternalizationLogic() );
ohair@286 363 return createXSOM(forest, scdBasedBindingSet);
ohair@286 364 }
ohair@286 365
ohair@286 366 /**
ohair@286 367 * Parses a set of schemas inside a WSDL file.
ohair@286 368 *
ohair@286 369 * A WSDL file may contain multiple &lt;xsd:schema> elements.
ohair@286 370 */
ohair@286 371 private XSSchemaSet loadWSDL()
ohair@286 372 throws SAXException {
ohair@286 373
ohair@286 374
ohair@286 375 // build DOMForest just like we handle XML Schema
ohair@286 376 DOMForest forest = buildDOMForest( new XMLSchemaInternalizationLogic() );
ohair@286 377
ohair@286 378 DOMForestScanner scanner = new DOMForestScanner(forest);
ohair@286 379
ohair@286 380 XSOMParser xsomParser = createXSOMParser( forest );
ohair@286 381
ohair@286 382 // find <xsd:schema>s and parse them individually
ohair@286 383 for( InputSource grammar : opt.getGrammars() ) {
ohair@286 384 Document wsdlDom = forest.get( grammar.getSystemId() );
ohair@286 385 if (wsdlDom == null) {
ohair@286 386 String systemId = Options.normalizeSystemId(grammar.getSystemId());
ohair@286 387 if (forest.get(systemId) != null) {
ohair@286 388 grammar.setSystemId(systemId);
ohair@286 389 wsdlDom = forest.get( grammar.getSystemId() );
ohair@286 390 }
ohair@286 391 }
ohair@286 392
ohair@286 393 NodeList schemas = wsdlDom.getElementsByTagNameNS(XMLConstants.W3C_XML_SCHEMA_NS_URI,"schema");
ohair@286 394 for( int i=0; i<schemas.getLength(); i++ )
ohair@286 395 scanner.scan( (Element)schemas.item(i), xsomParser.getParserHandler() );
ohair@286 396 }
ohair@286 397 return xsomParser.getResult();
ohair@286 398 }
ohair@286 399
ohair@286 400 /**
ohair@286 401 * Annotates the obtained schema set.
ohair@286 402 *
ohair@286 403 * @return
ohair@286 404 * null if an error happens. In that case, the error messages
ohair@286 405 * will be properly reported to the controller by this method.
ohair@286 406 */
ohair@286 407 public Model annotateXMLSchema(XSSchemaSet xs) {
ohair@286 408 if (xs == null)
ohair@286 409 return null;
ohair@286 410 return BGMBuilder.build(xs, codeModel, errorReceiver, opt);
ohair@286 411 }
ohair@286 412
alanb@368 413 /**
alanb@368 414 * Potentially problematic - make sure the parser instance passed is initialized
alanb@368 415 * with proper security feature.
alanb@368 416 *
alanb@368 417 * @param parser
alanb@368 418 * @return
alanb@368 419 */
ohair@286 420 public XSOMParser createXSOMParser(XMLParser parser) {
ohair@286 421 // set up other parameters to XSOMParser
ohair@286 422 XSOMParser reader = new XSOMParser(new XMLSchemaParser(parser));
ohair@286 423 reader.setAnnotationParser(new AnnotationParserFactoryImpl(opt));
ohair@286 424 reader.setErrorHandler(errorReceiver);
ohair@286 425 reader.setEntityResolver(opt.entityResolver);
ohair@286 426 return reader;
ohair@286 427 }
ohair@286 428
ohair@286 429 public XSOMParser createXSOMParser(final DOMForest forest) {
ohair@286 430 XSOMParser p = createXSOMParser(forest.createParser());
ohair@286 431 p.setEntityResolver(new EntityResolver() {
ohair@286 432 public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
ohair@286 433 // DOMForest only parses documents that are reachable through systemIds,
ohair@286 434 // and it won't pick up references like <xs:import namespace="..." /> without
ohair@286 435 // @schemaLocation. So we still need to use an entity resolver here to resolve
ohair@286 436 // these references, yet we don't want to just run them blindly, since if we do that
ohair@286 437 // DOMForestParser always get the translated system ID when catalog is used
ohair@286 438 // (where DOMForest records trees with their original system IDs.)
ohair@286 439 if(systemId!=null && forest.get(systemId)!=null)
ohair@286 440 return new InputSource(systemId);
ohair@286 441 if(opt.entityResolver!=null)
ohair@286 442 return opt.entityResolver.resolveEntity(publicId,systemId);
ohair@286 443
ohair@286 444 return null;
ohair@286 445 }
ohair@286 446 });
ohair@286 447 return p;
ohair@286 448 }
ohair@286 449
ohair@286 450
ohair@286 451 private static final class SpeculationFailure extends Error {}
ohair@286 452
ohair@286 453 private static final class SpeculationChecker extends XMLFilterImpl {
ohair@286 454 @Override
ohair@286 455 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
ohair@286 456 if(localName.equals("bindings") && uri.equals(Const.JAXB_NSURI))
ohair@286 457 throw new SpeculationFailure();
ohair@286 458 super.startElement(uri,localName,qName,attributes);
ohair@286 459 }
ohair@286 460 }
ohair@286 461
ohair@286 462 /**
ohair@286 463 * Parses schemas directly into XSOM by assuming that there's
ohair@286 464 * no external annotations.
ohair@286 465 * <p>
ohair@286 466 * When an external annotation is found, a {@link SpeculationFailure} is thrown,
ohair@286 467 * and we will do it all over again by using the slow way.
ohair@286 468 */
ohair@286 469 private XSSchemaSet createXSOMSpeculative() throws SAXException, SpeculationFailure {
ohair@286 470
ohair@286 471 // check if the schema contains external binding files. If so, speculation is a failure.
ohair@286 472
ohair@286 473 XMLParser parser = new XMLParser() {
alanb@368 474 private final JAXPParser base = new JAXPParser(XmlFactory.createParserFactory(opt.disableXmlSecurity));
ohair@286 475
ohair@286 476 public void parse(InputSource source, ContentHandler handler,
ohair@286 477 ErrorHandler errorHandler, EntityResolver entityResolver ) throws SAXException, IOException {
ohair@286 478 // set up the chain of handlers.
ohair@286 479 handler = wrapBy( new SpeculationChecker(), handler );
ohair@286 480 handler = wrapBy( new VersionChecker(null,errorReceiver,entityResolver), handler );
ohair@286 481
ohair@286 482 base.parse( source, handler, errorHandler, entityResolver );
ohair@286 483 }
ohair@286 484 /**
ohair@286 485 * Wraps the specified content handler by a filter.
ohair@286 486 * It is little awkward to use a helper implementation class like XMLFilterImpl
ohair@286 487 * as the method parameter, but this simplifies the code.
ohair@286 488 */
ohair@286 489 private ContentHandler wrapBy( XMLFilterImpl filter, ContentHandler handler ) {
ohair@286 490 filter.setContentHandler(handler);
ohair@286 491 return filter;
ohair@286 492 }
ohair@286 493 };
ohair@286 494
ohair@286 495 XSOMParser reader = createXSOMParser(parser);
ohair@286 496
ohair@286 497 // parse source grammars
ohair@286 498 for (InputSource value : opt.getGrammars())
ohair@286 499 reader.parse(value);
ohair@286 500
ohair@286 501 return reader.getResult();
ohair@286 502 }
ohair@286 503
ohair@286 504 /**
ohair@286 505 * Parses a {@link DOMForest} into a {@link XSSchemaSet}.
ohair@286 506 *
ohair@286 507 * @return
ohair@286 508 * null if the parsing failed.
ohair@286 509 */
ohair@286 510 public XSSchemaSet createXSOM(DOMForest forest, SCDBasedBindingSet scdBasedBindingSet) throws SAXException {
ohair@286 511 // set up other parameters to XSOMParser
ohair@286 512 XSOMParser reader = createXSOMParser(forest);
ohair@286 513
ohair@286 514 // re-parse the transformed schemas
ohair@286 515 for (String systemId : forest.getRootDocuments()) {
ohair@286 516 errorReceiver.pollAbort();
ohair@286 517 Document dom = forest.get(systemId);
ohair@286 518 if (!dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI)) {
ohair@286 519 reader.parse(systemId);
ohair@286 520 }
ohair@286 521 }
ohair@286 522
ohair@286 523 XSSchemaSet result = reader.getResult();
ohair@286 524
ohair@286 525 if(result!=null)
ohair@286 526 scdBasedBindingSet.apply(result,errorReceiver);
ohair@286 527
ohair@286 528 return result;
ohair@286 529 }
ohair@286 530
ohair@286 531 /**
ohair@286 532 * Parses a RELAX NG grammar into an annotated grammar.
ohair@286 533 */
ohair@286 534 private Model loadRELAXNG() throws SAXException {
ohair@286 535
ohair@286 536 // build DOM forest
ohair@286 537 final DOMForest forest = buildDOMForest( new RELAXNGInternalizationLogic() );
ohair@286 538
ohair@286 539 // use JAXP masquerading to validate the input document.
ohair@286 540 // DOMForest -> ExtensionBindingChecker -> RNGOM
ohair@286 541
ohair@286 542 XMLReaderCreator xrc = new XMLReaderCreator() {
ohair@286 543 public XMLReader createXMLReader() {
ohair@286 544
ohair@286 545 // foreset parser cannot change the receivers while it's working,
ohair@286 546 // so we need to have one XMLFilter that works as a buffer
ohair@286 547 XMLFilter buffer = new XMLFilterImpl() {
ohair@286 548 @Override
ohair@286 549 public void parse(InputSource source) throws IOException, SAXException {
ohair@286 550 forest.createParser().parse( source, this, this, this );
ohair@286 551 }
ohair@286 552 };
ohair@286 553
ohair@286 554 XMLFilter f = new ExtensionBindingChecker(Const.RELAXNG_URI,opt,errorReceiver);
ohair@286 555 f.setParent(buffer);
ohair@286 556
ohair@286 557 f.setEntityResolver(opt.entityResolver);
ohair@286 558
ohair@286 559 return f;
ohair@286 560 }
ohair@286 561 };
ohair@286 562
ohair@286 563 Parseable p = new SAXParseable( opt.getGrammars()[0], errorReceiver, xrc );
ohair@286 564
ohair@286 565 return loadRELAXNG(p);
ohair@286 566
ohair@286 567 }
ohair@286 568
ohair@286 569 /**
ohair@286 570 * Loads RELAX NG compact syntax
ohair@286 571 */
ohair@286 572 private Model loadRELAXNGCompact() {
ohair@286 573 if(opt.getBindFiles().length>0)
ohair@286 574 errorReceiver.error(new SAXParseException(
ohair@286 575 Messages.format(Messages.ERR_BINDING_FILE_NOT_SUPPORTED_FOR_RNC),null));
ohair@286 576
ohair@286 577 // TODO: entity resolver?
ohair@286 578 Parseable p = new CompactParseable( opt.getGrammars()[0], errorReceiver );
ohair@286 579
ohair@286 580 return loadRELAXNG(p);
ohair@286 581
ohair@286 582 }
ohair@286 583
ohair@286 584 /**
ohair@286 585 * Common part between the XML syntax and the compact syntax.
ohair@286 586 */
ohair@286 587 private Model loadRELAXNG(Parseable p) {
ohair@286 588 SchemaBuilder sb = new CheckingSchemaBuilder(new DSchemaBuilderImpl(),errorReceiver);
ohair@286 589
ohair@286 590 try {
ohair@286 591 DPattern out = (DPattern)p.parse(sb);
ohair@286 592 return RELAXNGCompiler.build(out,codeModel,opt);
ohair@286 593 } catch (IllegalSchemaException e) {
ohair@286 594 errorReceiver.error(e.getMessage(),e);
ohair@286 595 return null;
ohair@286 596 }
ohair@286 597 }
ohair@286 598 }

mercurial