1 /*
2 * Copyright (c) 1997, 2011, 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
40 import javax.xml.parsers.DocumentBuilder;
41 import javax.xml.parsers.DocumentBuilderFactory;
42 import javax.xml.parsers.ParserConfigurationException;
43 import javax.xml.parsers.SAXParserFactory;
44 import javax.xml.stream.XMLStreamException;
45 import javax.xml.stream.XMLStreamReader;
46 import javax.xml.transform.Source;
47 import javax.xml.transform.Transformer;
48 import javax.xml.transform.TransformerException;
49 import javax.xml.transform.TransformerFactory;
50 import javax.xml.transform.dom.DOMSource;
51 import javax.xml.transform.sax.SAXResult;
52 import javax.xml.transform.sax.SAXSource;
53 import javax.xml.validation.SchemaFactory;
54
55 import com.sun.istack.internal.NotNull;
56 import com.sun.istack.internal.XMLStreamReaderToContentHandler;
57 import com.sun.tools.internal.xjc.ErrorReceiver;
58 import com.sun.tools.internal.xjc.Options;
59 import com.sun.tools.internal.xjc.reader.Const;
60 import com.sun.tools.internal.xjc.reader.xmlschema.parser.SchemaConstraintChecker;
61 import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
62 import com.sun.xml.internal.bind.marshaller.DataWriter;
63 import com.sun.xml.internal.xsom.parser.JAXPParser;
64 import com.sun.xml.internal.xsom.parser.XMLParser;
65
66 import org.w3c.dom.Document;
67 import org.w3c.dom.Element;
68 import org.xml.sax.ContentHandler;
69 import org.xml.sax.EntityResolver;
70 import org.xml.sax.InputSource;
71 import org.xml.sax.SAXException;
72 import org.xml.sax.SAXParseException;
73 import org.xml.sax.XMLReader;
74 import org.xml.sax.helpers.XMLFilterImpl;
75
76
77 /**
78 * Builds a DOM forest and maintains association from
79 * system IDs to DOM trees.
80 *
81 * <p>
82 * A forest is a transitive reflexive closure of referenced documents.
109 private final Set<String> rootDocuments = new HashSet<String>();
110
111 /** Stores location information for all the trees in this forest. */
112 public final LocatorTable locatorTable = new LocatorTable();
113
114 /** Stores all the outer-most <jaxb:bindings> customizations. */
115 public final Set<Element> outerMostBindings = new HashSet<Element>();
116
117 /** Used to resolve references to other schema documents. */
118 private EntityResolver entityResolver = null;
119
120 /** Errors encountered during the parsing will be sent to this object. */
121 private ErrorReceiver errorReceiver = null;
122
123 /** Schema language dependent part of the processing. */
124 protected final InternalizationLogic logic;
125
126 private final SAXParserFactory parserFactory;
127 private final DocumentBuilder documentBuilder;
128
129
130 public DOMForest(
131 SAXParserFactory parserFactory, DocumentBuilder documentBuilder,
132 InternalizationLogic logic ) {
133
134 this.parserFactory = parserFactory;
135 this.documentBuilder = documentBuilder;
136 this.logic = logic;
137 }
138
139 public DOMForest( InternalizationLogic logic ) {
140 try {
141 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
142 dbf.setNamespaceAware(true);
143 this.documentBuilder = dbf.newDocumentBuilder();
144
145 this.parserFactory = SAXParserFactory.newInstance();
146 this.parserFactory.setNamespaceAware(true);
147 } catch( ParserConfigurationException e ) {
148 throw new AssertionError(e);
149 }
150
151 this.logic = logic;
152 }
153
154 /**
155 * Gets the DOM tree associated with the specified system ID,
156 * or null if none is found.
157 */
158 public Document get( String systemId ) {
159 Document doc = core.get(systemId);
160
161 if( doc==null && systemId.startsWith("file:/") && !systemId.startsWith("file://") ) {
162 // As of JDK1.4, java.net.URL.toExternal method returns URLs like
163 // "file:/abc/def/ghi" which is an incorrect file protocol URL according to RFC1738.
164 // Some other correctly functioning parts return the correct URLs ("file:///abc/def/ghi"),
165 // and this descripancy breaks DOM look up by system ID.
166
171 if( doc==null && systemId.startsWith("file:") ) {
172 // on Windows, filenames are case insensitive.
173 // perform case-insensitive search for improved user experience
174 String systemPath = getPath(systemId);
175 for (String key : core.keySet()) {
176 if(key.startsWith("file:") && getPath(key).equalsIgnoreCase(systemPath)) {
177 doc = core.get(key);
178 break;
179 }
180 }
181 }
182
183 return doc;
184 }
185
186 /**
187 * Strips off the leading 'file:///' portion from an URL.
188 */
189 private String getPath(String key) {
190 key = key.substring(5); // skip 'file:'
191 while(key.length()>0 && key.charAt(0)=='/')
192 key = key.substring(1);
193 return key;
194 }
195
196 /**
197 * Returns a read-only set of root document system IDs.
198 */
199 public Set<String> getRootDocuments() {
200 return Collections.unmodifiableSet(rootDocuments);
201 }
202
203 /**
204 * Picks one document at random and returns it.
205 */
206 public Document getOneDocument() {
207 for (Document dom : core.values()) {
208 if (!dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI))
209 return dom;
210 }
211 // we should have caught this error very early on
212 throw new AssertionError();
213 }
214
215 /**
216 * Checks the correctness of the XML Schema documents and return true
217 * if it's OK.
218 *
219 * <p>
220 * This method performs a weaker version of the tests where error messages
221 * are provided without line number information. So whenever possible
222 * use {@link SchemaConstraintChecker}.
223 *
224 * @see SchemaConstraintChecker
225 */
226 public boolean checkSchemaCorrectness(ErrorReceiver errorHandler) {
227 try {
228 SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
229 ErrorReceiverFilter filter = new ErrorReceiverFilter(errorHandler);
230 sf.setErrorHandler(filter);
231 Set<String> roots = getRootDocuments();
232 Source[] sources = new Source[roots.size()];
233 int i=0;
234 for (String root : roots) {
235 sources[i++] = new DOMSource(get(root),root);
236 }
237 sf.newSchema(sources);
238 return !filter.hadError();
239 } catch (SAXException e) {
240 // the errors should have been reported
241 return false;
242 }
243 }
244
245 /**
246 * Gets the system ID from which the given DOM is parsed.
247 * <p>
248 * Poor-man's base URI.
407 if(systemId==null)
408 throw new IllegalArgumentException("system id cannot be null");
409 core.put( systemId, dom );
410
411 new XMLStreamReaderToContentHandler(parser,getParserHandler(dom),false,false).bridge();
412
413 return dom;
414 }
415
416 /**
417 * Performs internalization.
418 *
419 * This method should be called only once, only after all the
420 * schemas are parsed.
421 *
422 * @return
423 * the returned bindings need to be applied after schema
424 * components are built.
425 */
426 public SCDBasedBindingSet transform(boolean enableSCD) {
427 return Internalizer.transform(this,enableSCD);
428 }
429
430 /**
431 * Performs the schema correctness check by using JAXP 1.3.
432 *
433 * <p>
434 * This is "weak", because {@link SchemaFactory#newSchema(Source[])}
435 * doesn't handle inclusions very correctly (it ends up parsing it
436 * from its original source, not in this tree), and because
437 * it doesn't handle two documents for the same namespace very
438 * well.
439 *
440 * <p>
441 * We should eventually fix JAXP (and Xerces), but meanwhile
442 * this weaker and potentially wrong correctness check is still
443 * better than nothing when used inside JAX-WS (JAXB CLI and Ant
444 * does a better job of checking this.)
445 *
446 * <p>
447 * To receive errors, use {@link SchemaFactory#setErrorHandler(ErrorHandler)}.
449 public void weakSchemaCorrectnessCheck(SchemaFactory sf) {
450 List<SAXSource> sources = new ArrayList<SAXSource>();
451 for( String systemId : getRootDocuments() ) {
452 Document dom = get(systemId);
453 if (dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI))
454 continue; // this isn't a schema. we have to do a negative check because if we see completely unrelated ns, we want to report that as an error
455
456 SAXSource ss = createSAXSource(systemId);
457 try {
458 ss.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes",true);
459 } catch (SAXException e) {
460 throw new AssertionError(e); // Xerces wants this. See 6395322.
461 }
462 sources.add(ss);
463 }
464
465 try {
466 sf.newSchema(sources.toArray(new SAXSource[0]));
467 } catch (SAXException e) {
468 // error should have been reported.
469 } catch (RuntimeException e) {
470 // JAXP RI isn't very trustworthy when it comes to schema error check,
471 // and we know some cases where it just dies with NPE. So handle it gracefully.
472 // this masks a bug in the JAXP RI, but we need a release that we have to make.
473 try {
474 sf.getErrorHandler().warning(
475 new SAXParseException(Messages.format(
476 Messages.ERR_GENERAL_SCHEMA_CORRECTNESS_ERROR,e.getMessage()),
477 null,null,-1,-1,e));
478 } catch (SAXException _) {
479 // ignore
480 }
481 }
482 }
483
484 /**
485 * Creates a {@link SAXSource} that, when parsed, reads from this {@link DOMForest}
486 * (instead of parsing the original source identified by the system ID.)
487 */
488 public @NotNull SAXSource createSAXSource(String systemId) {
489 ContentHandlerNamespacePrefixAdapter reader = new ContentHandlerNamespacePrefixAdapter(new XMLFilterImpl() {
490 // XMLReader that uses XMLParser to parse. We need to use XMLFilter to indrect
491 // handlers, since SAX allows handlers to be changed while parsing.
492 public void parse(InputSource input) throws SAXException, IOException {
493 createParser().parse(input, this, this, this);
494 }
495
496 public void parse(String systemId) throws SAXException, IOException {
497 parse(new InputSource(systemId));
498 }
499 });
500
501 return new SAXSource(reader,new InputSource(systemId));
502 }
503
504 /**
505 * Creates {@link XMLParser} for XSOM which reads documents from
506 * this DOMForest rather than doing a fresh parse.
507 *
508 * The net effect is that XSOM will read transformed XML Schemas
509 * instead of the original documents.
510 */
511 public XMLParser createParser() {
512 return new DOMForestParser(this,new JAXPParser());
513 }
514
515
516
517 public EntityResolver getEntityResolver() {
518 return entityResolver;
519 }
520
521 public void setEntityResolver(EntityResolver entityResolver) {
522 this.entityResolver = entityResolver;
523 }
524
525 public ErrorReceiver getErrorHandler() {
526 return errorReceiver;
527 }
528
529 public void setErrorHandler(ErrorReceiver errorHandler) {
530 this.errorReceiver = errorHandler;
531 }
532
533 /**
534 * Gets all the parsed documents.
535 */
536 public Document[] listDocuments() {
537 return core.values().toArray(new Document[core.size()]);
538 }
539
540 /**
541 * Gets all the system IDs of the documents.
542 */
543 public String[] listSystemIDs() {
544 return core.keySet().toArray(new String[core.keySet().size()]);
545 }
546
547 /**
548 * Dumps the contents of the forest to the specified stream.
549 *
550 * This is a debug method. As such, error handling is sloppy.
551 */
552 public void dump( OutputStream out ) throws IOException {
553 try {
554 // create identity transformer
555 Transformer it = TransformerFactory.newInstance().newTransformer();
556
557 for (Map.Entry<String, Document> e : core.entrySet()) {
558 out.write( ("---<< "+e.getKey()+'\n').getBytes() );
559
560 DataWriter dw = new DataWriter(new OutputStreamWriter(out),null);
561 dw.setIndentStep(" ");
562 it.transform( new DOMSource(e.getValue()),
563 new SAXResult(dw));
564
565 out.write( "\n\n\n".getBytes() );
566 }
567 } catch( TransformerException e ) {
568 e.printStackTrace();
569 }
570 }
571 }
|
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
40 import javax.xml.parsers.DocumentBuilder;
41 import javax.xml.parsers.DocumentBuilderFactory;
42 import javax.xml.parsers.ParserConfigurationException;
43 import javax.xml.parsers.SAXParserFactory;
44 import javax.xml.stream.XMLStreamException;
45 import javax.xml.stream.XMLStreamReader;
46 import javax.xml.transform.Source;
47 import javax.xml.transform.Transformer;
48 import javax.xml.transform.TransformerException;
49 import javax.xml.transform.TransformerFactory;
50 import javax.xml.transform.dom.DOMSource;
51 import javax.xml.transform.sax.SAXResult;
52 import javax.xml.transform.sax.SAXSource;
53 import javax.xml.validation.SchemaFactory;
54
55 import com.sun.istack.internal.NotNull;
56 import com.sun.istack.internal.XMLStreamReaderToContentHandler;
57 import com.sun.tools.internal.xjc.ErrorReceiver;
58 import com.sun.tools.internal.xjc.Options;
59 import com.sun.tools.internal.xjc.reader.Const;
60 import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
61 import com.sun.xml.internal.bind.marshaller.DataWriter;
62 import com.sun.xml.internal.bind.v2.util.XmlFactory;
63 import com.sun.xml.internal.xsom.parser.JAXPParser;
64 import com.sun.xml.internal.xsom.parser.XMLParser;
65
66 import org.w3c.dom.Document;
67 import org.w3c.dom.Element;
68 import org.xml.sax.ContentHandler;
69 import org.xml.sax.EntityResolver;
70 import org.xml.sax.InputSource;
71 import org.xml.sax.SAXException;
72 import org.xml.sax.SAXParseException;
73 import org.xml.sax.XMLReader;
74 import org.xml.sax.helpers.XMLFilterImpl;
75
76
77 /**
78 * Builds a DOM forest and maintains association from
79 * system IDs to DOM trees.
80 *
81 * <p>
82 * A forest is a transitive reflexive closure of referenced documents.
109 private final Set<String> rootDocuments = new HashSet<String>();
110
111 /** Stores location information for all the trees in this forest. */
112 public final LocatorTable locatorTable = new LocatorTable();
113
114 /** Stores all the outer-most <jaxb:bindings> customizations. */
115 public final Set<Element> outerMostBindings = new HashSet<Element>();
116
117 /** Used to resolve references to other schema documents. */
118 private EntityResolver entityResolver = null;
119
120 /** Errors encountered during the parsing will be sent to this object. */
121 private ErrorReceiver errorReceiver = null;
122
123 /** Schema language dependent part of the processing. */
124 protected final InternalizationLogic logic;
125
126 private final SAXParserFactory parserFactory;
127 private final DocumentBuilder documentBuilder;
128
129 private final Options options;
130
131 public DOMForest(
132 SAXParserFactory parserFactory, DocumentBuilder documentBuilder,
133 InternalizationLogic logic ) {
134
135 this.parserFactory = parserFactory;
136 this.documentBuilder = documentBuilder;
137 this.logic = logic;
138 this.options = null;
139 }
140
141 public DOMForest( InternalizationLogic logic, Options opt ) {
142
143 if (opt == null) throw new AssertionError("Options object null");
144 this.options = opt;
145
146 try {
147 DocumentBuilderFactory dbf = XmlFactory.createDocumentBuilderFactory(opt.disableXmlSecurity);
148 this.documentBuilder = dbf.newDocumentBuilder();
149 this.parserFactory = XmlFactory.createParserFactory(opt.disableXmlSecurity);
150 } catch( ParserConfigurationException e ) {
151 throw new AssertionError(e);
152 }
153
154 this.logic = logic;
155 }
156
157 /**
158 * Gets the DOM tree associated with the specified system ID,
159 * or null if none is found.
160 */
161 public Document get( String systemId ) {
162 Document doc = core.get(systemId);
163
164 if( doc==null && systemId.startsWith("file:/") && !systemId.startsWith("file://") ) {
165 // As of JDK1.4, java.net.URL.toExternal method returns URLs like
166 // "file:/abc/def/ghi" which is an incorrect file protocol URL according to RFC1738.
167 // Some other correctly functioning parts return the correct URLs ("file:///abc/def/ghi"),
168 // and this descripancy breaks DOM look up by system ID.
169
174 if( doc==null && systemId.startsWith("file:") ) {
175 // on Windows, filenames are case insensitive.
176 // perform case-insensitive search for improved user experience
177 String systemPath = getPath(systemId);
178 for (String key : core.keySet()) {
179 if(key.startsWith("file:") && getPath(key).equalsIgnoreCase(systemPath)) {
180 doc = core.get(key);
181 break;
182 }
183 }
184 }
185
186 return doc;
187 }
188
189 /**
190 * Strips off the leading 'file:///' portion from an URL.
191 */
192 private String getPath(String key) {
193 key = key.substring(5); // skip 'file:'
194 while(key.length()>0 && key.charAt(0)=='/') {
195 key = key.substring(1);
196 }
197 return key;
198 }
199
200 /**
201 * Returns a read-only set of root document system IDs.
202 */
203 public Set<String> getRootDocuments() {
204 return Collections.unmodifiableSet(rootDocuments);
205 }
206
207 /**
208 * Picks one document at random and returns it.
209 */
210 public Document getOneDocument() {
211 for (Document dom : core.values()) {
212 if (!dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI))
213 return dom;
214 }
215 // we should have caught this error very early on
216 throw new AssertionError();
217 }
218
219 /**
220 * Checks the correctness of the XML Schema documents and return true
221 * if it's OK.
222 *
223 * <p>
224 * This method performs a weaker version of the tests where error messages
225 * are provided without line number information. So whenever possible
226 * use {@link SchemaConstraintChecker}.
227 *
228 * @see SchemaConstraintChecker
229 */
230 public boolean checkSchemaCorrectness(ErrorReceiver errorHandler) {
231 try {
232 boolean disableXmlSecurity = false;
233 if (options != null) {
234 disableXmlSecurity = options.disableXmlSecurity;
235 }
236 SchemaFactory sf = XmlFactory.createSchemaFactory(W3C_XML_SCHEMA_NS_URI, disableXmlSecurity);
237 ErrorReceiverFilter filter = new ErrorReceiverFilter(errorHandler);
238 sf.setErrorHandler(filter);
239 Set<String> roots = getRootDocuments();
240 Source[] sources = new Source[roots.size()];
241 int i=0;
242 for (String root : roots) {
243 sources[i++] = new DOMSource(get(root),root);
244 }
245 sf.newSchema(sources);
246 return !filter.hadError();
247 } catch (SAXException e) {
248 // the errors should have been reported
249 return false;
250 }
251 }
252
253 /**
254 * Gets the system ID from which the given DOM is parsed.
255 * <p>
256 * Poor-man's base URI.
415 if(systemId==null)
416 throw new IllegalArgumentException("system id cannot be null");
417 core.put( systemId, dom );
418
419 new XMLStreamReaderToContentHandler(parser,getParserHandler(dom),false,false).bridge();
420
421 return dom;
422 }
423
424 /**
425 * Performs internalization.
426 *
427 * This method should be called only once, only after all the
428 * schemas are parsed.
429 *
430 * @return
431 * the returned bindings need to be applied after schema
432 * components are built.
433 */
434 public SCDBasedBindingSet transform(boolean enableSCD) {
435 return Internalizer.transform(this, enableSCD, options.disableXmlSecurity);
436 }
437
438 /**
439 * Performs the schema correctness check by using JAXP 1.3.
440 *
441 * <p>
442 * This is "weak", because {@link SchemaFactory#newSchema(Source[])}
443 * doesn't handle inclusions very correctly (it ends up parsing it
444 * from its original source, not in this tree), and because
445 * it doesn't handle two documents for the same namespace very
446 * well.
447 *
448 * <p>
449 * We should eventually fix JAXP (and Xerces), but meanwhile
450 * this weaker and potentially wrong correctness check is still
451 * better than nothing when used inside JAX-WS (JAXB CLI and Ant
452 * does a better job of checking this.)
453 *
454 * <p>
455 * To receive errors, use {@link SchemaFactory#setErrorHandler(ErrorHandler)}.
457 public void weakSchemaCorrectnessCheck(SchemaFactory sf) {
458 List<SAXSource> sources = new ArrayList<SAXSource>();
459 for( String systemId : getRootDocuments() ) {
460 Document dom = get(systemId);
461 if (dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI))
462 continue; // this isn't a schema. we have to do a negative check because if we see completely unrelated ns, we want to report that as an error
463
464 SAXSource ss = createSAXSource(systemId);
465 try {
466 ss.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes",true);
467 } catch (SAXException e) {
468 throw new AssertionError(e); // Xerces wants this. See 6395322.
469 }
470 sources.add(ss);
471 }
472
473 try {
474 sf.newSchema(sources.toArray(new SAXSource[0]));
475 } catch (SAXException e) {
476 // error should have been reported.
477 } catch (RuntimeException re) {
478 // JAXP RI isn't very trustworthy when it comes to schema error check,
479 // and we know some cases where it just dies with NPE. So handle it gracefully.
480 // this masks a bug in the JAXP RI, but we need a release that we have to make.
481 try {
482 sf.getErrorHandler().warning(
483 new SAXParseException(Messages.format(
484 Messages.ERR_GENERAL_SCHEMA_CORRECTNESS_ERROR,re.getMessage()),
485 null,null,-1,-1,re));
486 } catch (SAXException e) {
487 // ignore
488 }
489 }
490 }
491
492 /**
493 * Creates a {@link SAXSource} that, when parsed, reads from this {@link DOMForest}
494 * (instead of parsing the original source identified by the system ID.)
495 */
496 public @NotNull SAXSource createSAXSource(String systemId) {
497 ContentHandlerNamespacePrefixAdapter reader = new ContentHandlerNamespacePrefixAdapter(new XMLFilterImpl() {
498 // XMLReader that uses XMLParser to parse. We need to use XMLFilter to indrect
499 // handlers, since SAX allows handlers to be changed while parsing.
500 @Override
501 public void parse(InputSource input) throws SAXException, IOException {
502 createParser().parse(input, this, this, this);
503 }
504
505 @Override
506 public void parse(String systemId) throws SAXException, IOException {
507 parse(new InputSource(systemId));
508 }
509 });
510
511 return new SAXSource(reader,new InputSource(systemId));
512 }
513
514 /**
515 * Creates {@link XMLParser} for XSOM which reads documents from
516 * this DOMForest rather than doing a fresh parse.
517 *
518 * The net effect is that XSOM will read transformed XML Schemas
519 * instead of the original documents.
520 */
521 public XMLParser createParser() {
522 return new DOMForestParser(this, new JAXPParser(XmlFactory.createParserFactory(options.disableXmlSecurity)));
523 }
524
525 public EntityResolver getEntityResolver() {
526 return entityResolver;
527 }
528
529 public void setEntityResolver(EntityResolver entityResolver) {
530 this.entityResolver = entityResolver;
531 }
532
533 public ErrorReceiver getErrorHandler() {
534 return errorReceiver;
535 }
536
537 public void setErrorHandler(ErrorReceiver errorHandler) {
538 this.errorReceiver = errorHandler;
539 }
540
541 /**
542 * Gets all the parsed documents.
543 */
544 public Document[] listDocuments() {
545 return core.values().toArray(new Document[core.size()]);
546 }
547
548 /**
549 * Gets all the system IDs of the documents.
550 */
551 public String[] listSystemIDs() {
552 return core.keySet().toArray(new String[core.keySet().size()]);
553 }
554
555 /**
556 * Dumps the contents of the forest to the specified stream.
557 *
558 * This is a debug method. As such, error handling is sloppy.
559 */
560 @SuppressWarnings("CallToThreadDumpStack")
561 public void dump( OutputStream out ) throws IOException {
562 try {
563 // create identity transformer
564 boolean disableXmlSecurity = false;
565 if (options != null) {
566 disableXmlSecurity = options.disableXmlSecurity;
567 }
568 TransformerFactory tf = XmlFactory.createTransformerFactory(disableXmlSecurity);
569 Transformer it = tf.newTransformer();
570
571 for (Map.Entry<String, Document> e : core.entrySet()) {
572 out.write( ("---<< "+e.getKey()+'\n').getBytes() );
573
574 DataWriter dw = new DataWriter(new OutputStreamWriter(out),null);
575 dw.setIndentStep(" ");
576 it.transform( new DOMSource(e.getValue()),
577 new SAXResult(dw));
578
579 out.write( "\n\n\n".getBytes() );
580 }
581 } catch( TransformerException e ) {
582 e.printStackTrace();
583 }
584 }
585 }
|