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