1 /*
   2  * Copyright (c) 1997, 2012, 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 
  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 
 101     public EntityResolver getEntityResolver() {
 102         return owner.getEntityResolver();
 103     }
 104 
 105     public AnnotationParserFactory getAnnotationParserFactory() {
 106         return owner.getAnnotationParserFactory();
 107     }
 108 
 109     /**
 110      * Parses a new XML Schema document.
 111      */
 112     public void parse( InputSource source ) throws SAXException {
 113         newNGCCRuntime().parseEntity(source,false,null,null);
 114     }
 115 
 116 
 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 
 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. */
 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 }