diff -r 88b85470e72c -r f50545b5e2f1 src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMForest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMForest.java Tue Mar 06 16:09:35 2012 -0800 @@ -0,0 +1,571 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.internal.xjc.reader.internalizer; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.SchemaFactory; + +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.XMLStreamReaderToContentHandler; +import com.sun.tools.internal.xjc.ErrorReceiver; +import com.sun.tools.internal.xjc.Options; +import com.sun.tools.internal.xjc.reader.Const; +import com.sun.tools.internal.xjc.reader.xmlschema.parser.SchemaConstraintChecker; +import com.sun.tools.internal.xjc.util.ErrorReceiverFilter; +import com.sun.xml.internal.bind.marshaller.DataWriter; +import com.sun.xml.internal.xsom.parser.JAXPParser; +import com.sun.xml.internal.xsom.parser.XMLParser; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.ContentHandler; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLFilterImpl; + + +/** + * Builds a DOM forest and maintains association from + * system IDs to DOM trees. + * + *
+ * A forest is a transitive reflexive closure of referenced documents. + * IOW, if a document is in a forest, all the documents referenced from + * it is in a forest, too. To support this semantics, {@link DOMForest} + * uses {@link InternalizationLogic} to find referenced documents. + * + *
+ * Some documents are marked as "root"s, meaning those documents were
+ * put into a forest explicitly, not because it is referenced from another
+ * document. (However, a root document can be referenced from other
+ * documents, too.)
+ *
+ * @author
+ * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
+ */
+public final class DOMForest {
+ /** actual data storage map<SystemId,Document>. */
+ private final Map
+ * Set of system ids as strings.
+ */
+ private final Set
+ * This method performs a weaker version of the tests where error messages
+ * are provided without line number information. So whenever possible
+ * use {@link SchemaConstraintChecker}.
+ *
+ * @see SchemaConstraintChecker
+ */
+ public boolean checkSchemaCorrectness(ErrorReceiver errorHandler) {
+ try {
+ SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+ ErrorReceiverFilter filter = new ErrorReceiverFilter(errorHandler);
+ sf.setErrorHandler(filter);
+ Set
+ * Poor-man's base URI.
+ */
+ public String getSystemId( Document dom ) {
+ for (Map.Entry
+ * The client of this class can feed SAX events into the handler
+ * to parse a document into this DOM forest.
+ *
+ * This version requires that the DOM object to be created and registered
+ * to the map beforehand.
+ */
+ private ContentHandler getParserHandler( Document dom ) {
+ ContentHandler handler = new DOMBuilder(dom,locatorTable,outerMostBindings);
+ handler = new WhitespaceStripper(handler,errorReceiver,entityResolver);
+ handler = new VersionChecker(handler,errorReceiver,entityResolver);
+
+ // insert the reference finder so that
+ // included/imported schemas will be also parsed
+ XMLFilterImpl f = logic.createExternalReferenceFinder(this);
+ f.setContentHandler(handler);
+
+ if(errorReceiver!=null)
+ f.setErrorHandler(errorReceiver);
+ if(entityResolver!=null)
+ f.setEntityResolver(entityResolver);
+
+ return f;
+ }
+
+ public interface Handler extends ContentHandler {
+ /**
+ * Gets the DOM that was built.
+ */
+ public Document getDocument();
+ }
+
+ private static abstract class HandlerImpl extends XMLFilterImpl implements Handler {
+ }
+
+ /**
+ * Returns a {@link ContentHandler} to feed SAX events into.
+ *
+ *
+ * The client of this class can feed SAX events into the handler
+ * to parse a document into this DOM forest.
+ */
+ public Handler getParserHandler( String systemId, boolean root ) {
+ final Document dom = documentBuilder.newDocument();
+ core.put( systemId, dom );
+ if(root)
+ rootDocuments.add(systemId);
+
+ ContentHandler handler = getParserHandler(dom);
+
+ // we will register the DOM to the map once the system ID becomes available.
+ // but the SAX allows the event source to not to provide that information,
+ // so be prepared for such case.
+ HandlerImpl x = new HandlerImpl() {
+ public Document getDocument() {
+ return dom;
+ }
+ };
+ x.setContentHandler(handler);
+
+ return x;
+ }
+
+ /**
+ * Parses the given document and add it to the DOM forest.
+ *
+ * @return
+ * null if there was a parse error. otherwise non-null.
+ */
+ public Document parse( String systemId, InputSource inputSource, boolean root ) throws SAXException {
+ Document dom = documentBuilder.newDocument();
+
+ systemId = Options.normalizeSystemId(systemId);
+
+ // put into the map before growing a tree, to
+ // prevent recursive reference from causing infinite loop.
+ core.put( systemId, dom );
+ if(root)
+ rootDocuments.add(systemId);
+
+ try {
+ XMLReader reader = parserFactory.newSAXParser().getXMLReader();
+ reader.setContentHandler(getParserHandler(dom));
+ if(errorReceiver!=null)
+ reader.setErrorHandler(errorReceiver);
+ if(entityResolver!=null)
+ reader.setEntityResolver(entityResolver);
+ reader.parse(inputSource);
+ } catch( ParserConfigurationException e ) {
+ // in practice, this exception won't happen.
+ errorReceiver.error(e.getMessage(),e);
+ core.remove(systemId);
+ rootDocuments.remove(systemId);
+ return null;
+ } catch( IOException e ) {
+ errorReceiver.error(Messages.format(Messages.DOMFOREST_INPUTSOURCE_IOEXCEPTION, systemId, e.toString()),e);
+ core.remove(systemId);
+ rootDocuments.remove(systemId);
+ return null;
+ }
+
+ return dom;
+ }
+
+ public Document parse( String systemId, XMLStreamReader parser, boolean root ) throws XMLStreamException {
+ Document dom = documentBuilder.newDocument();
+
+ systemId = Options.normalizeSystemId(systemId);
+
+ if(root)
+ rootDocuments.add(systemId);
+
+ if(systemId==null)
+ throw new IllegalArgumentException("system id cannot be null");
+ core.put( systemId, dom );
+
+ new XMLStreamReaderToContentHandler(parser,getParserHandler(dom),false,false).bridge();
+
+ return dom;
+ }
+
+ /**
+ * Performs internalization.
+ *
+ * This method should be called only once, only after all the
+ * schemas are parsed.
+ *
+ * @return
+ * the returned bindings need to be applied after schema
+ * components are built.
+ */
+ public SCDBasedBindingSet transform(boolean enableSCD) {
+ return Internalizer.transform(this,enableSCD);
+ }
+
+ /**
+ * Performs the schema correctness check by using JAXP 1.3.
+ *
+ *
+ * This is "weak", because {@link SchemaFactory#newSchema(Source[])}
+ * doesn't handle inclusions very correctly (it ends up parsing it
+ * from its original source, not in this tree), and because
+ * it doesn't handle two documents for the same namespace very
+ * well.
+ *
+ *
+ * We should eventually fix JAXP (and Xerces), but meanwhile
+ * this weaker and potentially wrong correctness check is still
+ * better than nothing when used inside JAX-WS (JAXB CLI and Ant
+ * does a better job of checking this.)
+ *
+ *
+ * To receive errors, use {@link SchemaFactory#setErrorHandler(ErrorHandler)}.
+ */
+ public void weakSchemaCorrectnessCheck(SchemaFactory sf) {
+ List