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 23 * questions. 24 */ 25 26 package com.sun.xml.internal.xsom.parser; 27 28 import java.io.File; 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.io.Reader; 32 import java.net.URL; 33 import java.util.Set; 34 import java.util.HashSet; 35 36 import javax.xml.parsers.SAXParserFactory; 37 38 import org.xml.sax.ContentHandler; 39 import org.xml.sax.EntityResolver; 40 import org.xml.sax.ErrorHandler; 41 import org.xml.sax.InputSource; 42 import org.xml.sax.SAXException; 43 44 import com.sun.xml.internal.xsom.XSSchemaSet; 45 import com.sun.xml.internal.xsom.impl.parser.NGCCRuntimeEx; 46 import com.sun.xml.internal.xsom.impl.parser.ParserContext; 47 import com.sun.xml.internal.xsom.impl.parser.state.Schema; 48 49 /** 50 * Parses possibly multiple W3C XML Schema files and compose 51 * them into one grammar. 52 * 53 * @author 54 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 55 */ 56 public final class XSOMParser { 57 58 private EntityResolver entityResolver; 59 private ErrorHandler userErrorHandler; 60 61 private AnnotationParserFactory apFactory; 62 63 private final ParserContext context; 64 65 /** 66 * Creates a new XSOMParser by using a SAX parser from JAXP. 67 * @deprecated Unsafe, use XSOMParser(factory) instead with 68 * security features initialized by setting 69 * XMLConstants.FEATURE_SECURE_PROCESSING feature. 70 */ 71 public XSOMParser() { 72 this(new JAXPParser()); 73 } 74 75 /** 76 * Creates a new XSOMParser that uses the given SAXParserFactory 77 * for creating new SAX parsers. 78 * 79 * The caller needs to configure 80 * it properly. Don't forget to call <code>setNamespaceAware(true)</code> 81 * or you'll see some strange errors. 82 */ 83 public XSOMParser( SAXParserFactory factory ) { 84 this( new JAXPParser(factory) ); 85 } 86 87 /** 88 * Creates a new XSOMParser that reads XML Schema from non-standard 89 * inputs. 90 * 91 * By implementing the {@link XMLParser} interface, XML Schema 92 * can be read from something other than XML. 93 * 94 * @param parser 95 * This parser will be called to parse XML Schema documents. 96 */ 97 public XSOMParser(XMLParser parser) { 98 context = new ParserContext(this,parser); 99 } 100 101 /** 102 * Parses a new XML Schema document. 103 * 104 * <p> 105 * When using this method, XSOM does not know the system ID of 106 * this document, therefore, when this stream contains relative 107 * references to other schemas, XSOM will fail to resolve them. 108 * To specify an system ID with a stream, use {@link InputSource} 109 */ 110 public void parse( InputStream is ) throws SAXException { 111 parse(new InputSource(is)); 112 } 113 114 /** 115 * Parses a new XML Schema document. 116 * 117 * <p> 118 * When using this method, XSOM does not know the system ID of 119 * this document, therefore, when this reader contains relative 120 * references to other schemas, XSOM will fail to resolve them. 121 * To specify an system ID with a reader, use {@link InputSource} 122 */ 123 public void parse( Reader reader ) throws SAXException { 124 parse(new InputSource(reader)); 125 } 126 127 /** 128 * Parses a new XML Schema document. 129 */ 130 public void parse( File schema ) throws SAXException, IOException { 131 parse(schema.toURL()); 132 } 133 134 /** 135 * Parses a new XML Schema document. 136 */ 137 public void parse( URL url ) throws SAXException { 138 parse( url.toExternalForm() ); 139 } 140 141 /** 142 * Parses a new XML Schema document. 143 */ 144 public void parse( String systemId ) throws SAXException { 145 parse(new InputSource(systemId)); 146 } 147 148 /** 149 * Parses a new XML Schema document. 150 * 151 * <p> 152 * Note that if the {@link InputSource} does not have a system ID, 153 * XSOM will fail to resolve them. 154 */ 155 public void parse( InputSource source ) throws SAXException { 156 context.parse(source); 157 } 158 159 160 161 /** 162 * Gets the parser implemented as a ContentHandler. 163 * 164 * One can feed XML Schema as SAX events to this interface to 165 * parse a schema. To parse multiple schema files, feed multiple 166 * sets of events. 167 * 168 * <p> 169 * If you don't send a complete event sequence from a startDocument 170 * event to an endDocument event, the state of XSOMParser can become 171 * unstable. This sometimes happen when you encounter an error while 172 * generating SAX events. Don't call the getResult method in that case. 173 * 174 * <p> 175 * This way of reading XML Schema can be useful when XML Schema is 176 * not available as a stand-alone XML document. 177 * For example, one can feed XML Schema inside a WSDL document. 178 */ 179 public ContentHandler getParserHandler() { 180 NGCCRuntimeEx runtime = context.newNGCCRuntime(); 181 Schema s = new Schema(runtime,false,null); 182 runtime.setRootHandler(s); 183 return runtime; 184 } 185 186 /** 187 * Gets the parsed result. Don't call this method until 188 * you parse all the schemas. 189 * 190 * @return 191 * If there was any parse error, this method returns null. 192 * To receive error information, specify your error handler 193 * through the setErrorHandler method. 194 * @exception SAXException 195 * This exception will never be thrown unless it is thrown 196 * by an error handler. 197 */ 198 public XSSchemaSet getResult() throws SAXException { 199 return context.getResult(); 200 } 201 202 /** 203 * Gets the set of {@link SchemaDocument} that represents 204 * parsed documents so far. 205 * 206 * @return 207 * can be empty but never null. 208 */ 209 public Set<SchemaDocument> getDocuments() { 210 return new HashSet<SchemaDocument>(context.parsedDocuments.keySet()); 211 } 212 213 public EntityResolver getEntityResolver() { 214 return entityResolver; 215 } 216 /** 217 * Set an entity resolver that is used to resolve things 218 * like <xsd:import> and <xsd:include>. 219 */ 220 public void setEntityResolver( EntityResolver resolver ) { 221 this.entityResolver = resolver; 222 } 223 public ErrorHandler getErrorHandler() { 224 return userErrorHandler; 225 } 226 /** 227 * Set an error handler that receives all the errors encountered 228 * during the parsing. 229 */ 230 public void setErrorHandler(ErrorHandler errorHandler) { 231 this.userErrorHandler = errorHandler; 232 } 233 234 /** 235 * Sets the annotation parser. 236 * 237 * Annotation parser can be used to parse application-specific 238 * annotations inside a schema. 239 * 240 * <p> 241 * For each annotation, new instance of this class will be 242 * created and used to parse <xs:annotation>. 243 */ 244 public void setAnnotationParser( final Class annParser ) { 245 setAnnotationParser( new AnnotationParserFactory() { 246 public AnnotationParser create() { 247 try { 248 return (AnnotationParser)annParser.newInstance(); 249 } catch( InstantiationException e ) { 250 throw new InstantiationError(e.getMessage()); 251 } catch( IllegalAccessException e ) { 252 throw new IllegalAccessError(e.getMessage()); 253 } 254 } 255 }); 256 } 257 258 /** 259 * Sets the annotation parser factory. 260 * 261 * <p> 262 * The specified factory will be used to create AnnotationParsers. 263 */ 264 public void setAnnotationParser( AnnotationParserFactory factory ) { 265 this.apFactory = factory; 266 } 267 268 public AnnotationParserFactory getAnnotationParserFactory() { 269 return apFactory; 270 } 271 }