001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020: package com.sun.xml.xsom.parser;
021:
022: import java.io.File;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.io.Reader;
026: import java.net.URL;
027: import java.util.Set;
028: import java.util.HashSet;
029:
030: import javax.xml.parsers.SAXParserFactory;
031:
032: import org.xml.sax.ContentHandler;
033: import org.xml.sax.EntityResolver;
034: import org.xml.sax.ErrorHandler;
035: import org.xml.sax.InputSource;
036: import org.xml.sax.SAXException;
037:
038: import com.sun.xml.xsom.XSSchemaSet;
039: import com.sun.xml.xsom.impl.parser.NGCCRuntimeEx;
040: import com.sun.xml.xsom.impl.parser.ParserContext;
041: import com.sun.xml.xsom.impl.parser.state.Schema;
042:
043: /**
044: * Parses possibly multiple W3C XML Schema files and compose
045: * them into one grammar.
046: *
047: * @author
048: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
049: */
050: public final class XSOMParser {
051:
052: private EntityResolver entityResolver;
053: private ErrorHandler userErrorHandler;
054:
055: private AnnotationParserFactory apFactory;
056:
057: private final ParserContext context;
058:
059: /**
060: * Creates a new XSOMParser by using a SAX parser from JAXP.
061: */
062: public XSOMParser() {
063: this (new JAXPParser());
064: }
065:
066: /**
067: * Creates a new XSOMParser that uses the given SAXParserFactory
068: * for creating new SAX parsers.
069: *
070: * The caller needs to configure
071: * it properly. Don't forget to call <code>setNamespaceAware(true)</code>
072: * or you'll see some strange errors.
073: */
074: public XSOMParser(SAXParserFactory factory) {
075: this (new JAXPParser(factory));
076: }
077:
078: /**
079: * Creates a new XSOMParser that reads XML Schema from non-standard
080: * inputs.
081: *
082: * By implementing the {@link XMLParser} interface, XML Schema
083: * can be read from something other than XML.
084: *
085: * @param parser
086: * This parser will be called to parse XML Schema documents.
087: */
088: public XSOMParser(XMLParser parser) {
089: context = new ParserContext(this , parser);
090: }
091:
092: /**
093: * Parses a new XML Schema document.
094: *
095: * <p>
096: * When using this method, XSOM does not know the system ID of
097: * this document, therefore, when this stream contains relative
098: * references to other schemas, XSOM will fail to resolve them.
099: * To specify an system ID with a stream, use {@link InputSource}
100: */
101: public void parse(InputStream is) throws SAXException {
102: parse(new InputSource(is));
103: }
104:
105: /**
106: * Parses a new XML Schema document.
107: *
108: * <p>
109: * When using this method, XSOM does not know the system ID of
110: * this document, therefore, when this reader contains relative
111: * references to other schemas, XSOM will fail to resolve them.
112: * To specify an system ID with a reader, use {@link InputSource}
113: */
114: public void parse(Reader reader) throws SAXException {
115: parse(new InputSource(reader));
116: }
117:
118: /**
119: * Parses a new XML Schema document.
120: */
121: public void parse(File schema) throws SAXException, IOException {
122: parse(schema.toURL());
123: }
124:
125: /**
126: * Parses a new XML Schema document.
127: */
128: public void parse(URL url) throws SAXException {
129: parse(url.toExternalForm());
130: }
131:
132: /**
133: * Parses a new XML Schema document.
134: */
135: public void parse(String systemId) throws SAXException {
136: parse(new InputSource(systemId));
137: }
138:
139: /**
140: * Parses a new XML Schema document.
141: *
142: * <p>
143: * Note that if the {@link InputSource} does not have a system ID,
144: * XSOM will fail to resolve them.
145: */
146: public void parse(InputSource source) throws SAXException {
147: context.parse(source);
148: }
149:
150: /**
151: * Gets the parser implemented as a ContentHandler.
152: *
153: * One can feed XML Schema as SAX events to this interface to
154: * parse a schema. To parse multiple schema files, feed multiple
155: * sets of events.
156: *
157: * <p>
158: * If you don't send a complete event sequence from a startDocument
159: * event to an endDocument event, the state of XSOMParser can become
160: * unstable. This sometimes happen when you encounter an error while
161: * generating SAX events. Don't call the getResult method in that case.
162: *
163: * <p>
164: * This way of reading XML Schema can be useful when XML Schema is
165: * not available as a stand-alone XML document.
166: * For example, one can feed XML Schema inside a WSDL document.
167: */
168: public ContentHandler getParserHandler() {
169: NGCCRuntimeEx runtime = context.newNGCCRuntime();
170: Schema s = new Schema(runtime, false, null);
171: runtime.setRootHandler(s);
172: return runtime;
173: }
174:
175: /**
176: * Gets the parsed result. Don't call this method until
177: * you parse all the schemas.
178: *
179: * @return
180: * If there was any parse error, this method returns null.
181: * To receive error information, specify your error handler
182: * through the setErrorHandler method.
183: * @exception SAXException
184: * This exception will never be thrown unless it is thrown
185: * by an error handler.
186: */
187: public XSSchemaSet getResult() throws SAXException {
188: return context.getResult();
189: }
190:
191: /**
192: * Gets the set of {@link SchemaDocument} that represents
193: * parsed documents so far.
194: *
195: * @return
196: * can be empty but never null.
197: */
198: public Set<SchemaDocument> getDocuments() {
199: return new HashSet<SchemaDocument>(context.parsedDocuments
200: .keySet());
201: }
202:
203: public EntityResolver getEntityResolver() {
204: return entityResolver;
205: }
206:
207: /**
208: * Set an entity resolver that is used to resolve things
209: * like <xsd:import> and <xsd:include>.
210: */
211: public void setEntityResolver(EntityResolver resolver) {
212: this .entityResolver = resolver;
213: }
214:
215: public ErrorHandler getErrorHandler() {
216: return userErrorHandler;
217: }
218:
219: /**
220: * Set an error handler that receives all the errors encountered
221: * during the parsing.
222: */
223: public void setErrorHandler(ErrorHandler errorHandler) {
224: this .userErrorHandler = errorHandler;
225: }
226:
227: /**
228: * Sets the annotation parser.
229: *
230: * Annotation parser can be used to parse application-specific
231: * annotations inside a schema.
232: *
233: * <p>
234: * For each annotation, new instance of this class will be
235: * created and used to parse <xs:annotation>.
236: */
237: public void setAnnotationParser(final Class annParser) {
238: setAnnotationParser(new AnnotationParserFactory() {
239: public AnnotationParser create() {
240: try {
241: return (AnnotationParser) annParser.newInstance();
242: } catch (InstantiationException e) {
243: throw new InstantiationError(e.getMessage());
244: } catch (IllegalAccessException e) {
245: throw new IllegalAccessError(e.getMessage());
246: }
247: }
248: });
249: }
250:
251: /**
252: * Sets the annotation parser factory.
253: *
254: * <p>
255: * The specified factory will be used to create AnnotationParsers.
256: */
257: public void setAnnotationParser(AnnotationParserFactory factory) {
258: this .apFactory = factory;
259: }
260:
261: public AnnotationParserFactory getAnnotationParserFactory() {
262: return apFactory;
263: }
264: }
|