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
23  * questions.
24  */
25 
26 package com.sun.xml.internal.xsom.impl.parser;
27 
28 import com.sun.xml.internal.xsom.XSSchemaSet;
29 import com.sun.xml.internal.xsom.impl.ElementDecl;
30 import com.sun.xml.internal.xsom.impl.SchemaImpl;
31 import com.sun.xml.internal.xsom.impl.SchemaSetImpl;
32 import com.sun.xml.internal.xsom.parser.AnnotationParserFactory;
33 import com.sun.xml.internal.xsom.parser.XMLParser;
34 import com.sun.xml.internal.xsom.parser.XSOMParser;
35 import org.xml.sax.EntityResolver;
36 import org.xml.sax.ErrorHandler;
37 import org.xml.sax.InputSource;
38 import org.xml.sax.Locator;
39 import org.xml.sax.SAXException;
40 import org.xml.sax.SAXParseException;
41 
42 import java.util.HashMap;
43 import java.util.Iterator;
44 import java.util.Map;
45 import java.util.Vector;
46 
47 /**
48  * Provides context information to be used by {@link NGCCRuntimeEx}s.
49  *
50  * <p>
51  * This class does the actual processing for {@link XSOMParser},
52  * but to hide the details from the public API, this class in
53  * a different package.
54  *
55  * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
56  */
57 public class ParserContext {
58 
59     /** SchemaSet to which a newly parsed schema is put in. */
60     public final SchemaSetImpl schemaSet = new SchemaSetImpl();
61 
62     private final XSOMParser owner;
63 
64     final XMLParser parser;
65 
66 
67     private final Vector<Patch> patchers = new Vector<Patch>();
68     private final Vector<Patch> errorCheckers = new Vector<Patch>();
69 
70     /**
71      * Documents that are parsed already. Used to avoid cyclic inclusion/double
72      * inclusion of schemas. Set of {@link SchemaDocumentImpl}s.
73      *
74      * The actual data structure is map from {@link SchemaDocumentImpl} to itself,
75      * so that we can access the {@link SchemaDocumentImpl} itself.
76      */
77     public final Map<SchemaDocumentImpl, SchemaDocumentImpl> parsedDocuments = new HashMap<SchemaDocumentImpl, SchemaDocumentImpl>();
78 
79 
ParserContext( XSOMParser owner, XMLParser parser )80     public ParserContext( XSOMParser owner, XMLParser parser ) {
81         this.owner = owner;
82         this.parser = parser;
83 
84         try {
85             parse(new InputSource(ParserContext.class.getResource("datatypes.xsd").toExternalForm()));
86 
87             SchemaImpl xs = (SchemaImpl)
88                 schemaSet.getSchema("http://www.w3.org/2001/XMLSchema");
89             xs.addSimpleType(schemaSet.anySimpleType,true);
90             xs.addComplexType(schemaSet.anyType,true);
91         } catch( SAXException e ) {
92             // this must be a bug of XSOM
93             if(e.getException()!=null)
94                 e.getException().printStackTrace();
95             else
96                 e.printStackTrace();
97             throw new InternalError();
98         }
99     }
100 
getEntityResolver()101     public EntityResolver getEntityResolver() {
102         return owner.getEntityResolver();
103     }
104 
getAnnotationParserFactory()105     public AnnotationParserFactory getAnnotationParserFactory() {
106         return owner.getAnnotationParserFactory();
107     }
108 
109     /**
110      * Parses a new XML Schema document.
111      */
parse( InputSource source )112     public void parse( InputSource source ) throws SAXException {
113         newNGCCRuntime().parseEntity(source,false,null,null);
114     }
115 
116 
getResult()117     public XSSchemaSet getResult() throws SAXException {
118         // run all the patchers
119         for (Patch patcher : patchers)
120             patcher.run();
121         patchers.clear();
122 
123         // build the element substitutability map
124         Iterator itr = schemaSet.iterateElementDecls();
125         while(itr.hasNext())
126             ((ElementDecl)itr.next()).updateSubstitutabilityMap();
127 
128         // run all the error checkers
129         for (Patch patcher : errorCheckers)
130             patcher.run();
131         errorCheckers.clear();
132 
133 
134         if(hadError)    return null;
135         else            return schemaSet;
136     }
137 
newNGCCRuntime()138     public NGCCRuntimeEx newNGCCRuntime() {
139         return new NGCCRuntimeEx(this);
140     }
141 
142 
143 
144     /** Once an error is detected, this flag is set to true. */
145     private boolean hadError = false;
146 
147     /** Turns on the error flag. */
setErrorFlag()148     void setErrorFlag() { hadError=true; }
149 
150     /**
151      * PatchManager implementation, which is accessible only from
152      * NGCCRuntimEx.
153      */
154     final PatcherManager patcherManager = new PatcherManager() {
155         public void addPatcher( Patch patch ) {
156             patchers.add(patch);
157         }
158         public void addErrorChecker( Patch patch ) {
159             errorCheckers.add(patch);
160         }
161         public void reportError( String msg, Locator src ) throws SAXException {
162             // set a flag to true to avoid returning a corrupted object.
163             setErrorFlag();
164 
165             SAXParseException e = new SAXParseException(msg,src);
166             if(errorHandler==null)
167                 throw e;
168             else
169                 errorHandler.error(e);
170         }
171     };
172 
173     /**
174      * ErrorHandler proxy to turn on the hadError flag when an error
175      * is found.
176      */
177     final ErrorHandler errorHandler = new ErrorHandler() {
178         private ErrorHandler getErrorHandler() {
179             if( owner.getErrorHandler()==null )
180                 return noopHandler;
181             else
182                 return owner.getErrorHandler();
183         }
184 
185         public void warning(SAXParseException e) throws SAXException {
186             getErrorHandler().warning(e);
187         }
188 
189         public void error(SAXParseException e) throws SAXException {
190             setErrorFlag();
191             getErrorHandler().error(e);
192         }
193 
194         public void fatalError(SAXParseException e) throws SAXException {
195             setErrorFlag();
196             getErrorHandler().fatalError(e);
197         }
198     };
199 
200     /**
201      * {@link ErrorHandler} that does nothing.
202      */
203     final ErrorHandler noopHandler = new ErrorHandler() {
204         public void warning(SAXParseException e) {
205         }
206         public void error(SAXParseException e) {
207         }
208         public void fatalError(SAXParseException e) {
209             setErrorFlag();
210         }
211     };
212 }
213