< prev index next >

jaxws/src/jdk.xml.bind/share/classes/com/sun/xml/internal/xsom/impl/parser/NGCCRuntimeEx.java

Print this page


   1 /*
   2  * Copyright (c) 1997, 2016, 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.XSDeclaration;
  29 import com.sun.xml.internal.xsom.XmlString;
  30 import com.sun.xml.internal.xsom.XSSimpleType;
  31 import com.sun.xml.internal.xsom.impl.ForeignAttributesImpl;
  32 import com.sun.xml.internal.xsom.impl.SchemaImpl;
  33 import com.sun.xml.internal.xsom.impl.UName;
  34 import com.sun.xml.internal.xsom.impl.Const;
  35 import com.sun.xml.internal.xsom.impl.parser.state.NGCCRuntime;
  36 import com.sun.xml.internal.xsom.impl.parser.state.Schema;
  37 import com.sun.xml.internal.xsom.impl.util.Uri;
  38 import com.sun.xml.internal.xsom.parser.AnnotationParser;
  39 import com.sun.xml.internal.org.relaxng.datatype.ValidationContext;
  40 import org.xml.sax.Attributes;
  41 import org.xml.sax.EntityResolver;
  42 import org.xml.sax.ErrorHandler;
  43 import org.xml.sax.InputSource;
  44 import org.xml.sax.Locator;
  45 import org.xml.sax.SAXException;
  46 import org.xml.sax.SAXParseException;
  47 import org.xml.sax.helpers.LocatorImpl;
  48 
  49 import java.io.IOException;
  50 import java.net.URI;

  51 import java.text.MessageFormat;
  52 import java.util.Stack;

  53 
  54 /**
  55  * NGCCRuntime extended with various utility methods for
  56  * parsing XML Schema.
  57  *
  58  * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
  59  */
  60 public class NGCCRuntimeEx extends NGCCRuntime implements PatcherManager {
  61 
  62     /** coordinator. */
  63     public final ParserContext parser;
  64 
  65     /** The schema currently being parsed. */
  66     public SchemaImpl currentSchema;
  67 
  68     /** The @finalDefault value of the current schema. */
  69     public int finalDefault = 0;
  70     /** The @blockDefault value of the current schema. */
  71     public int blockDefault = 0;
  72 


 133         if(c==null || ignorableDuplicateComponent(c)) return;
 134 
 135         reportError( Messages.format(Messages.ERR_DOUBLE_DEFINITION,c.getName()) );
 136         reportError( Messages.format(Messages.ERR_DOUBLE_DEFINITION_ORIGINAL), c.getLocator() );
 137     }
 138 
 139     public static boolean ignorableDuplicateComponent(XSDeclaration c) {
 140         if(c.getTargetNamespace().equals(Const.schemaNamespace)) {
 141             if(c instanceof XSSimpleType)
 142                 // hide artificial "double definitions" on simple types
 143                 return true;
 144             if(c.isGlobal() && c.getName().equals("anyType"))
 145                 return true; // ditto for anyType
 146         }
 147         return false;
 148     }
 149 
 150 
 151 
 152     /* registers a patcher that will run after all the parsing has finished. */

 153     public void addPatcher( Patch patcher ) {
 154         parser.patcherManager.addPatcher(patcher);
 155     }

 156     public void addErrorChecker( Patch patcher ) {
 157         parser.patcherManager.addErrorChecker(patcher);
 158     }

 159     public void reportError( String msg, Locator loc ) throws SAXException {
 160         parser.patcherManager.reportError(msg,loc);
 161     }
 162     public void reportError( String msg ) throws SAXException {
 163         reportError(msg,getLocator());
 164     }
 165 
 166 
 167     /**
 168      * Resolves relative URI found in the document.
 169      *
 170      * @param namespaceURI
 171      *      passed to the entity resolver.
 172      * @param relativeUri
 173      *      value of the schemaLocation attribute. Can be null.
 174      *
 175      * @return
 176      *      non-null if {@link EntityResolver} returned an {@link InputSource},
 177      *      or if the relativeUri parameter seems to be pointing to something.
 178      *      Otherwise it returns null, in which case import/include should be abandoned.
 179      */
 180     private InputSource resolveRelativeURL( String namespaceURI, String relativeUri ) throws SAXException {
 181         try {
 182             String baseUri = getLocator().getSystemId();
 183             if(baseUri==null)
 184                 // if the base URI is not available, the document system ID is
 185                 // better than nothing.
 186                 baseUri=documentSystemId;
 187 
 188             EntityResolver er = parser.getEntityResolver();
 189             String systemId = null;
 190 
 191             if (relativeUri!=null)
 192                 systemId = Uri.resolve(baseUri,relativeUri);







 193 
 194             if (er!=null) {
 195                 InputSource is = er.resolveEntity(namespaceURI,systemId);
 196                 if (is == null) {
 197                     try {
 198                         String normalizedSystemId = URI.create(systemId).normalize().toASCIIString();
 199                         is = er.resolveEntity(namespaceURI,normalizedSystemId);
 200                     } catch (Exception e) {
 201                         // just ignore, this is a second try, return the fallback if this breaks
 202                     }
 203                 }
 204                 if (is != null) {
 205                     return is;
 206                 }
 207             }
 208 
 209             if (systemId!=null)
 210                 return new InputSource(systemId);
 211             else
 212                 return null;
 213         } catch (IOException e) {
 214             SAXParseException se = new SAXParseException(e.getMessage(),getLocator(),e);
 215             parser.errorHandler.error(se);
 216             return null;
 217         }
 218     }
 219 
 220     /** Includes the specified schema. */













 221     public void includeSchema( String schemaLocation ) throws SAXException {
 222         NGCCRuntimeEx runtime = new NGCCRuntimeEx(parser,chameleonMode,this);
 223         runtime.currentSchema = this.currentSchema;
 224         runtime.blockDefault = this.blockDefault;
 225         runtime.finalDefault = this.finalDefault;
 226 
 227         if( schemaLocation==null ) {
 228             SAXParseException e = new SAXParseException(
 229                 Messages.format( Messages.ERR_MISSING_SCHEMALOCATION ), getLocator() );
 230             parser.errorHandler.fatalError(e);
 231             throw e;
 232         }
 233 
 234         runtime.parseEntity( resolveRelativeURL(null,schemaLocation),
 235             true, currentSchema.getTargetNamespace(), getLocator() );
 236     }
 237 
 238     /** Imports the specified schema. */




 239     public void importSchema( String ns, String schemaLocation ) throws SAXException {
 240         NGCCRuntimeEx newRuntime = new NGCCRuntimeEx(parser,false,this);
 241         InputSource source = resolveRelativeURL(ns,schemaLocation);
 242         if(source!=null)
 243             newRuntime.parseEntity( source, false, ns, getLocator() );
 244         // if source == null,
 245         // we can't locate this document. Let's just hope that
 246         // we already have the schema components for this schema
 247         // or we will receive them in the future.
 248     }
 249 
 250     /**
 251      * Called when a new document is being parsed and checks
 252      * if the document has already been parsed before.
 253      *
 254      * <p>
 255      * Used to avoid recursive inclusion. Note that the same
 256      * document will be parsed multiple times if they are for different
 257      * target namespaces.
 258      *


 300         if(existing==null) {
 301             parser.parsedDocuments.put(document,document);
 302         } else {
 303             document = existing;
 304         }
 305 
 306         assert document !=null;
 307 
 308         if(referer!=null) {
 309             assert referer.document !=null : "referer "+referer.documentSystemId+" has docIdentity==null";
 310             referer.document.references.add(this.document);
 311             this.document.referers.add(referer.document);
 312         }
 313 
 314         return existing!=null;
 315     }
 316 
 317     /**
 318      * Parses the specified entity.
 319      *

 320      * @param importLocation
 321      *      The source location of the import/include statement.
 322      *      Used for reporting errors.



 323      */
 324     public void parseEntity( InputSource source, boolean includeMode, String expectedNamespace, Locator importLocation )
 325             throws SAXException {
 326 
 327         documentSystemId = source.getSystemId();
 328         try {
 329             Schema s = new Schema(this,includeMode,expectedNamespace);
 330             setRootHandler(s);
 331             try {
 332                 parser.parser.parse(source,this, getErrorHandler(), parser.getEntityResolver());
 333             } catch( IOException fnfe ) {
 334                 SAXParseException se = new SAXParseException(fnfe.toString(), importLocation, fnfe);
 335                 parser.errorHandler.warning(se);
 336             }
 337         } catch( SAXException e ) {
 338             parser.setErrorFlag();
 339             throw e;
 340         }
 341     }
 342 
 343     /**
 344      * Creates a new instance of annotation parser.

 345      */
 346     public AnnotationParser createAnnotationParser() {
 347         if(parser.getAnnotationParserFactory()==null)
 348             return DefaultAnnotationParser.theInstance;
 349         else
 350             return parser.getAnnotationParserFactory().create();
 351     }
 352 
 353     /**
 354      * Gets the element name that contains the annotation element.
 355      * This method works correctly only when called by the annotation handler.
 356      */
 357     public String getAnnotationContextElementName() {
 358         return elementNames.get( elementNames.size()-2 );
 359     }
 360 
 361     /** Creates a copy of the current locator object. */

 362     public Locator copyLocator() {
 363         return new LocatorImpl(getLocator());
 364     }
 365 
 366     public ErrorHandler getErrorHandler() {
 367         return parser.errorHandler;
 368     }
 369 
 370     @Override
 371     public void onEnterElementConsumed(String uri, String localName, String qname, Attributes atts)
 372         throws SAXException {
 373         super.onEnterElementConsumed(uri, localName, qname, atts);
 374         elementNames.push(localName);
 375     }
 376 
 377     @Override
 378     public void onLeaveElementConsumed(String uri, String localName, String qname) throws SAXException {
 379         super.onLeaveElementConsumed(uri, localName, qname);
 380         elementNames.pop();
 381     }
 382 
 383 
 384 
 385 //
 386 //
 387 // ValidationContext implementation
 388 //
 389 //
 390     // this object lives longer than the parser itself,
 391     // so it's important for this object not to have any reference
 392     // to the parser.
 393     private static class Context implements ValidationContext {
 394         Context( String _prefix, String _uri, Context _context ) {
 395             this.previous = _context;
 396             this.prefix = _prefix;
 397             this.uri = _uri;
 398         }
 399 

 400         public String resolveNamespacePrefix(String p) {
 401             if(p.equals(prefix))    return uri;
 402             if(previous==null)      return null;
 403             else                    return previous.resolveNamespacePrefix(p);
 404         }
 405 
 406         private final String prefix;
 407         private final String uri;
 408         private final Context previous;
 409 
 410         // XSDLib don't use those methods, so we cut a corner here.

 411         public String getBaseUri() { return null; }

 412         public boolean isNotation(String arg0) { return false; }

 413         public boolean isUnparsedEntity(String arg0) { return false; }
 414     }
 415 
 416     private Context currentContext=null;
 417 
 418     /** Returns an immutable snapshot of the current context. */

 419     public ValidationContext createValidationContext() {
 420         return currentContext;
 421     }
 422 
 423     public XmlString createXmlString(String value) {
 424         if(value==null)     return null;
 425         else    return new XmlString(value,createValidationContext());
 426     }
 427 
 428     @Override
 429     public void startPrefixMapping( String prefix, String uri ) throws SAXException {
 430         super.startPrefixMapping(prefix,uri);
 431         currentContext = new Context(prefix,uri,currentContext);
 432     }
 433     @Override
 434     public void endPrefixMapping( String prefix ) throws SAXException {
 435         super.endPrefixMapping(prefix);
 436         currentContext = currentContext.previous;
 437     }
 438 
 439 //
 440 //
 441 // Utility functions
 442 //
 443 //
 444 
 445     /**
 446      * Parses UName under the given context.
 447      * @param qname Attribute name.
 448      * @return New {@link UName} instance based on attribute name.

 449      */
 450     public UName parseUName(final String qname ) throws SAXException {
 451         int idx = qname.indexOf(':');
 452         if(idx<0) {
 453             String uri = resolveNamespacePrefix("");
 454 
 455             // chamelon behavior. ugly...
 456             if( uri.equals("") && chameleonMode )
 457                 uri = currentSchema.getTargetNamespace();
 458 
 459             // this is guaranteed to resolve
 460             return new UName(uri,qname,qname);
 461         } else {
 462             String prefix = qname.substring(0,idx);
 463             String uri = currentContext.resolveNamespacePrefix(prefix);
 464             if(uri==null) {
 465                 // prefix failed to resolve.
 466                 reportError(Messages.format(
 467                     Messages.ERR_UNDEFINED_PREFIX,prefix));
 468                 uri="undefined"; // replace with a dummy


   1 /*
   2  * Copyright (c) 1997, 2017, 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.XSDeclaration;
  29 import com.sun.xml.internal.xsom.XmlString;
  30 import com.sun.xml.internal.xsom.XSSimpleType;
  31 import com.sun.xml.internal.xsom.impl.ForeignAttributesImpl;
  32 import com.sun.xml.internal.xsom.impl.SchemaImpl;
  33 import com.sun.xml.internal.xsom.impl.UName;
  34 import com.sun.xml.internal.xsom.impl.Const;
  35 import com.sun.xml.internal.xsom.impl.parser.state.NGCCRuntime;
  36 import com.sun.xml.internal.xsom.impl.parser.state.Schema;

  37 import com.sun.xml.internal.xsom.parser.AnnotationParser;
  38 import com.sun.xml.internal.org.relaxng.datatype.ValidationContext;
  39 import org.xml.sax.Attributes;
  40 import org.xml.sax.EntityResolver;
  41 import org.xml.sax.ErrorHandler;
  42 import org.xml.sax.InputSource;
  43 import org.xml.sax.Locator;
  44 import org.xml.sax.SAXException;
  45 import org.xml.sax.SAXParseException;
  46 import org.xml.sax.helpers.LocatorImpl;
  47 
  48 import java.io.IOException;
  49 import java.net.URI;
  50 import java.net.URL;
  51 import java.text.MessageFormat;
  52 import java.util.Stack;
  53 import java.util.regex.Pattern;
  54 
  55 /**
  56  * NGCCRuntime extended with various utility methods for
  57  * parsing XML Schema.
  58  *
  59  * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
  60  */
  61 public class NGCCRuntimeEx extends NGCCRuntime implements PatcherManager {
  62 
  63     /** coordinator. */
  64     public final ParserContext parser;
  65 
  66     /** The schema currently being parsed. */
  67     public SchemaImpl currentSchema;
  68 
  69     /** The @finalDefault value of the current schema. */
  70     public int finalDefault = 0;
  71     /** The @blockDefault value of the current schema. */
  72     public int blockDefault = 0;
  73 


 134         if(c==null || ignorableDuplicateComponent(c)) return;
 135 
 136         reportError( Messages.format(Messages.ERR_DOUBLE_DEFINITION,c.getName()) );
 137         reportError( Messages.format(Messages.ERR_DOUBLE_DEFINITION_ORIGINAL), c.getLocator() );
 138     }
 139 
 140     public static boolean ignorableDuplicateComponent(XSDeclaration c) {
 141         if(c.getTargetNamespace().equals(Const.schemaNamespace)) {
 142             if(c instanceof XSSimpleType)
 143                 // hide artificial "double definitions" on simple types
 144                 return true;
 145             if(c.isGlobal() && c.getName().equals("anyType"))
 146                 return true; // ditto for anyType
 147         }
 148         return false;
 149     }
 150 
 151 
 152 
 153     /* registers a patcher that will run after all the parsing has finished. */
 154     @Override
 155     public void addPatcher( Patch patcher ) {
 156         parser.patcherManager.addPatcher(patcher);
 157     }
 158     @Override
 159     public void addErrorChecker( Patch patcher ) {
 160         parser.patcherManager.addErrorChecker(patcher);
 161     }
 162     @Override
 163     public void reportError( String msg, Locator loc ) throws SAXException {
 164         parser.patcherManager.reportError(msg,loc);
 165     }
 166     public void reportError( String msg ) throws SAXException {
 167         reportError(msg,getLocator());
 168     }
 169 
 170 
 171     /**
 172      * Resolves relative URI found in the document.
 173      *
 174      * @param namespaceURI
 175      *      passed to the entity resolver.
 176      * @param relativeUri
 177      *      value of the schemaLocation attribute. Can be null.
 178      *
 179      * @return
 180      *      non-null if {@link EntityResolver} returned an {@link InputSource},
 181      *      or if the relativeUri parameter seems to be pointing to something.
 182      *      Otherwise it returns null, in which case import/include should be abandoned.
 183      */
 184     private InputSource resolveRelativeURL( String namespaceURI, String relativeUri ) throws SAXException {
 185         try {
 186             String baseUri = getLocator().getSystemId();
 187             if(baseUri==null)
 188                 // if the base URI is not available, the document system ID is
 189                 // better than nothing.
 190                 baseUri=documentSystemId;
 191 
 192             EntityResolver er = parser.getEntityResolver();
 193             String systemId = null;
 194 
 195             if (relativeUri!=null) {
 196                 if (isAbsolute(relativeUri)) {
 197                     systemId = relativeUri;
 198                 }
 199                 if (baseUri == null || !isAbsolute(baseUri)) {
 200                     throw new IOException("Unable to resolve relative URI " + relativeUri + " because base URI is not absolute: " + baseUri);
 201                 }
 202                 systemId = new URL(new URL(baseUri), relativeUri).toString();
 203             }
 204 
 205             if (er!=null) {
 206                 InputSource is = er.resolveEntity(namespaceURI,systemId);
 207                 if (is == null) {
 208                     try {
 209                         String normalizedSystemId = URI.create(systemId).normalize().toASCIIString();
 210                         is = er.resolveEntity(namespaceURI,normalizedSystemId);
 211                     } catch (Exception e) {
 212                         // just ignore, this is a second try, return the fallback if this breaks
 213                     }
 214                 }
 215                 if (is != null) {
 216                     return is;
 217                 }
 218             }
 219 
 220             if (systemId!=null)
 221                 return new InputSource(systemId);
 222             else
 223                 return null;
 224         } catch (IOException e) {
 225             SAXParseException se = new SAXParseException(e.getMessage(),getLocator(),e);
 226             parser.errorHandler.error(se);
 227             return null;
 228         }
 229     }
 230 
 231     private static final Pattern P = Pattern.compile(".*[/#?].*");
 232 
 233     private static boolean isAbsolute(String uri) {
 234         int i = uri.indexOf(':');
 235         if (i < 0) {
 236             return false;
 237         }
 238         return !P.matcher(uri.substring(0, i)).matches();
 239     }
 240 
 241     /**
 242      * Includes the specified schema.
 243      * @param schemaLocation
 244      * @throws org.xml.sax.SAXException */
 245     public void includeSchema( String schemaLocation ) throws SAXException {
 246         NGCCRuntimeEx runtime = new NGCCRuntimeEx(parser,chameleonMode,this);
 247         runtime.currentSchema = this.currentSchema;
 248         runtime.blockDefault = this.blockDefault;
 249         runtime.finalDefault = this.finalDefault;
 250 
 251         if( schemaLocation==null ) {
 252             SAXParseException e = new SAXParseException(
 253                 Messages.format( Messages.ERR_MISSING_SCHEMALOCATION ), getLocator() );
 254             parser.errorHandler.fatalError(e);
 255             throw e;
 256         }
 257 
 258         runtime.parseEntity( resolveRelativeURL(null,schemaLocation),
 259             true, currentSchema.getTargetNamespace(), getLocator() );
 260     }
 261 
 262     /**
 263      * Imports the specified schema.
 264      * @param ns
 265      * @param schemaLocation
 266      * @throws org.xml.sax.SAXException */
 267     public void importSchema( String ns, String schemaLocation ) throws SAXException {
 268         NGCCRuntimeEx newRuntime = new NGCCRuntimeEx(parser,false,this);
 269         InputSource source = resolveRelativeURL(ns,schemaLocation);
 270         if(source!=null)
 271             newRuntime.parseEntity( source, false, ns, getLocator() );
 272         // if source == null,
 273         // we can't locate this document. Let's just hope that
 274         // we already have the schema components for this schema
 275         // or we will receive them in the future.
 276     }
 277 
 278     /**
 279      * Called when a new document is being parsed and checks
 280      * if the document has already been parsed before.
 281      *
 282      * <p>
 283      * Used to avoid recursive inclusion. Note that the same
 284      * document will be parsed multiple times if they are for different
 285      * target namespaces.
 286      *


 328         if(existing==null) {
 329             parser.parsedDocuments.put(document,document);
 330         } else {
 331             document = existing;
 332         }
 333 
 334         assert document !=null;
 335 
 336         if(referer!=null) {
 337             assert referer.document !=null : "referer "+referer.documentSystemId+" has docIdentity==null";
 338             referer.document.references.add(this.document);
 339             this.document.referers.add(referer.document);
 340         }
 341 
 342         return existing!=null;
 343     }
 344 
 345     /**
 346      * Parses the specified entity.
 347      *
 348      * @param source
 349      * @param importLocation
 350      *      The source location of the import/include statement.
 351      *      Used for reporting errors.
 352      * @param includeMode
 353      * @param expectedNamespace
 354      * @throws org.xml.sax.SAXException
 355      */
 356     public void parseEntity( InputSource source, boolean includeMode, String expectedNamespace, Locator importLocation )
 357             throws SAXException {
 358 
 359         documentSystemId = source.getSystemId();
 360         try {
 361             Schema s = new Schema(this,includeMode,expectedNamespace);
 362             setRootHandler(s);
 363             try {
 364                 parser.parser.parse(source,this, getErrorHandler(), parser.getEntityResolver());
 365             } catch( IOException fnfe ) {
 366                 SAXParseException se = new SAXParseException(fnfe.toString(), importLocation, fnfe);
 367                 parser.errorHandler.warning(se);
 368             }
 369         } catch( SAXException e ) {
 370             parser.setErrorFlag();
 371             throw e;
 372         }
 373     }
 374 
 375     /**
 376      * Creates a new instance of annotation parser.
 377      * @return
 378      */
 379     public AnnotationParser createAnnotationParser() {
 380         if(parser.getAnnotationParserFactory()==null)
 381             return DefaultAnnotationParser.theInstance;
 382         else
 383             return parser.getAnnotationParserFactory().create();
 384     }
 385 
 386     /**
 387      * Gets the element name that contains the annotation element.This method works correctly only when called by the annotation handler.
 388      * @return
 389      */
 390     public String getAnnotationContextElementName() {
 391         return elementNames.get( elementNames.size()-2 );
 392     }
 393 
 394     /** Creates a copy of the current locator object.
 395      * @return  */
 396     public Locator copyLocator() {
 397         return new LocatorImpl(getLocator());
 398     }
 399 
 400     public ErrorHandler getErrorHandler() {
 401         return parser.errorHandler;
 402     }
 403 
 404     @Override
 405     public void onEnterElementConsumed(String uri, String localName, String qname, Attributes atts)
 406         throws SAXException {
 407         super.onEnterElementConsumed(uri, localName, qname, atts);
 408         elementNames.push(localName);
 409     }
 410 
 411     @Override
 412     public void onLeaveElementConsumed(String uri, String localName, String qname) throws SAXException {
 413         super.onLeaveElementConsumed(uri, localName, qname);
 414         elementNames.pop();
 415     }
 416 
 417 
 418 
 419 //
 420 //
 421 // ValidationContext implementation
 422 //
 423 //
 424     // this object lives longer than the parser itself,
 425     // so it's important for this object not to have any reference
 426     // to the parser.
 427     private static class Context implements ValidationContext {
 428         Context( String _prefix, String _uri, Context _context ) {
 429             this.previous = _context;
 430             this.prefix = _prefix;
 431             this.uri = _uri;
 432         }
 433 
 434         @Override
 435         public String resolveNamespacePrefix(String p) {
 436             if(p.equals(prefix))    return uri;
 437             if(previous==null)      return null;
 438             else                    return previous.resolveNamespacePrefix(p);
 439         }
 440 
 441         private final String prefix;
 442         private final String uri;
 443         private final Context previous;
 444 
 445         // XSDLib don't use those methods, so we cut a corner here.
 446         @Override
 447         public String getBaseUri() { return null; }
 448         @Override
 449         public boolean isNotation(String arg0) { return false; }
 450         @Override
 451         public boolean isUnparsedEntity(String arg0) { return false; }
 452     }
 453 
 454     private Context currentContext=null;
 455 
 456     /** Returns an immutable snapshot of the current context.
 457      * @return  */
 458     public ValidationContext createValidationContext() {
 459         return currentContext;
 460     }
 461 
 462     public XmlString createXmlString(String value) {
 463         if(value==null)     return null;
 464         else    return new XmlString(value,createValidationContext());
 465     }
 466 
 467     @Override
 468     public void startPrefixMapping( String prefix, String uri ) throws SAXException {
 469         super.startPrefixMapping(prefix,uri);
 470         currentContext = new Context(prefix,uri,currentContext);
 471     }
 472     @Override
 473     public void endPrefixMapping( String prefix ) throws SAXException {
 474         super.endPrefixMapping(prefix);
 475         currentContext = currentContext.previous;
 476     }
 477 
 478 //
 479 //
 480 // Utility functions
 481 //
 482 //
 483 
 484     /**
 485      * Parses UName under the given context.
 486      * @param qname Attribute name.
 487      * @return New {@link UName} instance based on attribute name.
 488      * @throws org.xml.sax.SAXException
 489      */
 490     public UName parseUName(final String qname ) throws SAXException {
 491         int idx = qname.indexOf(':');
 492         if(idx<0) {
 493             String uri = resolveNamespacePrefix("");
 494 
 495             // chamelon behavior. ugly...
 496             if( uri.equals("") && chameleonMode )
 497                 uri = currentSchema.getTargetNamespace();
 498 
 499             // this is guaranteed to resolve
 500             return new UName(uri,qname,qname);
 501         } else {
 502             String prefix = qname.substring(0,idx);
 503             String uri = currentContext.resolveNamespacePrefix(prefix);
 504             if(uri==null) {
 505                 // prefix failed to resolve.
 506                 reportError(Messages.format(
 507                     Messages.ERR_UNDEFINED_PREFIX,prefix));
 508                 uri="undefined"; // replace with a dummy


< prev index next >