KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > jaxp > validation > ValidatorHandlerImpl


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57 package com.sun.org.apache.xerces.internal.jaxp.validation;
58
59 import javax.xml.validation.TypeInfoProvider JavaDoc;
60 import javax.xml.validation.ValidatorHandler JavaDoc;
61
62 import com.sun.org.apache.xerces.internal.impl.Constants;
63 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
64 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
65 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
66 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
67 import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter;
68 import com.sun.org.apache.xerces.internal.util.DraconianErrorHandler;
69 import com.sun.org.apache.xerces.internal.util.LocatorWrapper;
70 import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
71 import com.sun.org.apache.xerces.internal.util.SymbolTable;
72 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
73 import com.sun.org.apache.xerces.internal.xni.Augmentations;
74 import com.sun.org.apache.xerces.internal.xni.QName;
75 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
76 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
77 import com.sun.org.apache.xerces.internal.xni.XMLString;
78 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
79 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
80 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
81 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
82 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
83 import com.sun.org.apache.xerces.internal.xs.ItemPSVI;
84 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
85 import org.w3c.dom.TypeInfo JavaDoc;
86 import org.w3c.dom.ls.LSResourceResolver JavaDoc;
87 import org.xml.sax.Attributes JavaDoc;
88 import org.xml.sax.ContentHandler JavaDoc;
89 import org.xml.sax.ErrorHandler JavaDoc;
90 import org.xml.sax.Locator JavaDoc;
91 import org.xml.sax.SAXException JavaDoc;
92 import org.xml.sax.SAXNotRecognizedException JavaDoc;
93 import org.xml.sax.SAXNotSupportedException JavaDoc;
94
95 /**
96  * {@link ValidatorHandler} implementation that wraps
97  * {@link InsulatedValidatorComponent}.
98  *
99  * <p>
100  * This class implements all the SAX {@link org.xml.sax.ContentHandler}
101  * methods and turn SAX events into XNI events.
102  *
103  * <p>
104  * This class also implements {@link XMLComponentManager}
105  * to host a validator.
106  *
107  * @author
108  * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
109  */

110 final class ValidatorHandlerImpl extends ValidatorHandler JavaDoc {
111     // TODO: reuse SAX2XNI
112

113     /**
114      * The actual validator.
115      */

116     private final InsulatedValidatorComponent validator;
117     
118     /**
119      * <code>validator.getValidator()</code>.
120      */

121     private final XMLDocumentFilter validatorFilter;
122     
123     /**
124      * Used to adopt the output from a validtor to the input of
125      * the user specified {@link ContentHandler}.
126      */

127     private final XNI2SAXEx xni2sax = new XNI2SAXEx();
128     
129     
130     // XMLSchemaValidator needs various helper components to work.
131
private final SymbolTable symbolTable = new SymbolTable();
132     private final NamespaceSupport nsContext = new NamespaceSupport();
133     private final ValidationManager validationManager = new ValidationManager();
134     private final XMLEntityManager entityManager = new XMLEntityManager();
135     
136     /** error reporter is used to format error messages. */
137     private final XMLErrorReporter errorReporter = new XMLErrorReporter();
138     
139     /** User-specified error handler. Maybe null. */
140     private ErrorHandler errorHandler;
141     
142     /** This flag is set to true while we are processing the startElement event. */
143     private boolean inStartElement;
144     
145     /** The value of the <tt>http://xml.org/sax/features/namespace-prefixes</tt> feature. */
146     private boolean namespacePrefixesFeature = false;
147     
148     //private Hashtable fProperties;
149
/**
150      * Used by {@link XMLDTDValidator} to report errors.
151      */

152     private final ErrorHandlerAdaptor xercesErrorHandler = new ErrorHandlerAdaptor() {
153         protected ErrorHandler getErrorHandler() {
154             if(errorHandler==null )
155                 return DraconianErrorHandler.theInstance;
156             else
157                 return errorHandler;
158         }
159     };
160     
161     /** User-specified entity resolver. Maybe null. */
162     private LSResourceResolver JavaDoc resourceResolver;
163     
164     
165     
166     
167     ValidatorHandlerImpl( InsulatedValidatorComponent validator ) {
168         this.validator = validator;
169         this.validatorFilter = validator.getValidator();
170
171         // format error message with Schema aware formatter
172
errorReporter.putMessageFormatter(
173                 XSMessageFormatter.SCHEMA_DOMAIN,
174                 new XSMessageFormatter());
175     }
176     
177     /**
178      * Obtains the current augmentation.
179      * <p>
180      * used for {@link javax.xml.validation.TypeInfoProvider}.
181      *
182      * @return
183      * may return null.
184      */

185     private final Augmentations getCurrentAugmentation() {
186         return xni2sax.getCurrentAugmentation();
187     }
188     
189     /**
190      * Obtains the current attributes.
191      *
192      * @throws IllegalStateException
193      */

194     private final XMLAttributes getCurrentAttributes() {
195         return xni2sax.getCurrentAttributes();
196     }
197     
198     
199     public boolean getFeature(String JavaDoc name) throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
200         if( name.equals("http://xml.org/sax/features/namespace-prefixes") )
201             return namespacePrefixesFeature;
202         return super.getFeature(name);
203     }
204     
205     public void setFeature(String JavaDoc name, boolean value) throws SAXNotRecognizedException JavaDoc, SAXNotSupportedException JavaDoc {
206         if( name.equals("http://xml.org/sax/features/namespace-prefixes") ) {
207             namespacePrefixesFeature = value;
208             return;
209         }
210         super.setFeature(name, value);
211     }
212     
213     
214     
215     //
216
//
217
// ValidaorHandler implementation
218
//
219
//
220

221     public boolean isValidSoFar() {
222         return !xercesErrorHandler.hadError();
223     }
224     
225     public void setErrorHandler(ErrorHandler errorHandler) {
226         this.errorHandler = errorHandler;
227     }
228     
229     public ErrorHandler getErrorHandler() {
230         return errorHandler;
231     }
232     
233     public void setResourceResolver(LSResourceResolver JavaDoc entityResolver) {
234         this.resourceResolver = entityResolver;
235     }
236     
237     public LSResourceResolver JavaDoc getResourceResolver() {
238         return resourceResolver;
239     }
240     
241     public final void setContentHandler(ContentHandler JavaDoc result) {
242         xni2sax.setContentHandler(result);
243         if(result==null) validatorFilter.setDocumentHandler(null);
244         else validatorFilter.setDocumentHandler(xni2sax);
245     }
246     
247     public final ContentHandler JavaDoc getContentHandler() {
248         return xni2sax.getContentHandler();
249     }
250     
251     
252     
253     
254     //
255
//
256
// XMLComponentManager implementation
257
//
258
//
259
private final XMLComponentManager manager = new XMLComponentManager() {
260         public Object JavaDoc getProperty( String JavaDoc propName ) {
261             if( propName.equals(XercesConstants.SYMBOL_TABLE) )
262                 return symbolTable;
263             if( propName.equals(XercesConstants.VALIDATION_MANAGER) )
264                 return validationManager;
265             if( propName.equals(XercesConstants.ERROR_REPORTER) )
266                 return errorReporter;
267             if( propName.equals(XercesConstants.ERROR_HANDLER) )
268                 return xercesErrorHandler;
269             if( propName.equals(XercesConstants.ENTITY_MANAGER) )
270                 return entityManager;
271             if( propName.equals(XercesConstants.ENTITY_RESOLVER) )
272                 return entityManager;
273             
274             throw new XMLConfigurationException(
275             XMLConfigurationException.NOT_RECOGNIZED, propName );
276         }
277         public boolean getFeature( String JavaDoc propName ) {
278             // if( propName.equals(XercesConstants.SCHEMA_VALIDATION) )
279
// // this flag will turn on the validation
280
// return true;
281
if( propName.equals(XercesConstants.VALIDATION) )
282                 return true;//TODO:: Configure
283

284             throw new XMLConfigurationException(
285             XMLConfigurationException.NOT_RECOGNIZED, propName );
286         }
287     };
288     
289     //
290
//
291
// ContentHandler implementation
292
//
293
//
294
public void startDocument() throws SAXException JavaDoc {
295         try {
296             resetComponents();
297             
298             XMLLocator xmlLocator = (locator==null)?null:new LocatorWrapper(locator);
299             
300             // set the locator to the error reporter
301
errorReporter.setDocumentLocator(xmlLocator);
302             
303             validatorFilter.startDocument(
304             xmlLocator,
305             null,
306             nsContext,
307             null);
308         } catch( WrappedSAXException e ) {
309             throw e.exception;
310         }
311     }
312     
313     /**
314      * Resets the components we use internally.
315      */

316     private void resetComponents() {
317         // reset the error flag when we start a new validation.
318
xercesErrorHandler.reset();
319         nsContext.reset();
320         errorReporter.reset(manager);
321         validator.reset(manager);
322     }
323     
324     public void endDocument() throws SAXException JavaDoc {
325         try {
326             validatorFilter.endDocument(null);
327         } catch( WrappedSAXException e ) {
328             throw e.exception;
329         }
330     }
331     
332     public void startElement( String JavaDoc uri, String JavaDoc local, String JavaDoc qname, Attributes att ) throws SAXException JavaDoc {
333         try {
334             inStartElement = true;
335             validatorFilter.startElement(createQName(uri,local,qname),createAttributes(att),null);
336         } catch( WrappedSAXException e ) {
337             throw e.exception;
338         } finally {
339             inStartElement = false;
340         }
341     }
342     
343     public void endElement( String JavaDoc uri, String JavaDoc local, String JavaDoc qname ) throws SAXException JavaDoc {
344         try {
345             validatorFilter.endElement(createQName(uri,local,qname),null);
346         } catch( WrappedSAXException e ) {
347             throw e.exception;
348         }
349     }
350     
351     public void characters( char[] buf, int offset, int len ) throws SAXException JavaDoc {
352         try {
353             validatorFilter.characters(new XMLString(buf,offset,len),null);
354         } catch( WrappedSAXException e ) {
355             throw e.exception;
356         }
357     }
358     
359     public void ignorableWhitespace( char[] buf, int offset, int len ) throws SAXException JavaDoc {
360         try {
361             validatorFilter.ignorableWhitespace(new XMLString(buf,offset,len),null);
362         } catch( WrappedSAXException e ) {
363             throw e.exception;
364         }
365     }
366     
367     public void startPrefixMapping( String JavaDoc prefix, String JavaDoc uri ) {
368         nsContext.pushContext();
369         nsContext.declarePrefix(prefix,uri);
370     }
371     
372     public void endPrefixMapping( String JavaDoc prefix ) {
373         nsContext.popContext();
374     }
375     
376     public void processingInstruction( String JavaDoc target, String JavaDoc data ) throws SAXException JavaDoc {
377         try {
378             validatorFilter.processingInstruction(
379             symbolize(target),createXMLString(data),null);
380         } catch( WrappedSAXException e ) {
381             throw e.exception;
382         }
383     }
384     
385     public void skippedEntity( String JavaDoc name ) {
386         // there seems to be no corresponding method on XMLDocumentFilter.
387
// just pass it down to the output, if any.
388
ContentHandler JavaDoc handler = getContentHandler();
389         if( handler!=null )
390             skippedEntity(name);
391     }
392     
393     private Locator locator;
394     public void setDocumentLocator( Locator _loc ) {
395         this.locator = _loc;
396     }
397     
398     
399     public TypeInfoProvider JavaDoc getTypeInfoProvider() {
400         return typeInfoProvider;
401     }
402     
403     
404     /**
405      * {@link TypeInfoProvider} implementation.
406      *
407      * REVISIT: I'm not sure if this code should belong here.
408      */

409     private final TypeInfoProvider JavaDoc typeInfoProvider = new TypeInfoProvider JavaDoc() {
410         /**
411          * Throws a {@link IllegalStateException} if we are not in
412          * the startElement callback. the JAXP API requires this
413          * for most of the public methods.
414          */

415         private void checkState() {
416             if( !inStartElement )
417                 throw new IllegalStateException JavaDoc();
418         }
419         
420         public TypeInfo JavaDoc getAttributeTypeInfo(int index) {
421             checkState();
422             return getAttributeType(index);
423         }
424         
425         private XSTypeDefinition getAttributeType( int index ) {
426             checkState();
427             XMLAttributes atts = getCurrentAttributes();
428             if( index<0 || atts.getLength()<=index )
429                 throw new IndexOutOfBoundsException JavaDoc(Integer.toString(index));
430             Augmentations augs = atts.getAugmentations(index);
431             if(augs==null) return null;
432             AttributePSVI psvi = (AttributePSVI)augs.getItem(Constants.ATTRIBUTE_PSVI);
433             return getTypeInfoFromPSVI(psvi);
434         }
435         
436         public TypeInfo JavaDoc getAttributeTypeInfo(String JavaDoc attributeUri, String JavaDoc attributeLocalName) {
437             checkState();
438             return getAttributeTypeInfo(getCurrentAttributes().getIndex(attributeUri,attributeLocalName));
439         }
440         
441         public TypeInfo JavaDoc getAttributeTypeInfo(String JavaDoc attributeQName) {
442             checkState();
443             return getAttributeTypeInfo(getCurrentAttributes().getIndex(attributeQName));
444         }
445         
446         public TypeInfo JavaDoc getElementTypeInfo() {
447             checkState();
448             Augmentations augs = getCurrentAugmentation();
449             if(augs==null) return null;
450             ElementPSVI psvi = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI);
451             return getTypeInfoFromPSVI(psvi);
452         }
453         
454         private XSTypeDefinition getTypeInfoFromPSVI( ItemPSVI psvi ) {
455             if(psvi==null) return null;
456             
457             // TODO: make sure if this is correct.
458
// TODO: since the number of types in a schema is quite limited,
459
// TypeInfoImpl should be pooled. Even better, it should be a part
460
// of the element decl.
461
if( psvi.getValidity()== ElementPSVI.VALIDITY_VALID ) {
462                 XSTypeDefinition t = psvi.getMemberTypeDefinition();
463                 if(t!=null) return t;
464             }
465             
466             XSTypeDefinition t = psvi.getTypeDefinition();
467             if(t!=null) return t; // TODO: can t be null?
468
return null;
469         }
470         
471         public boolean isIdAttribute(int index) {
472             checkState();
473             XSSimpleType type = (XSSimpleType)getAttributeType(index);
474             if(type==null) return false;
475             return type.isIDType();
476         }
477         
478         public boolean isSpecified(int index) {
479             checkState();
480             return getCurrentAttributes().isSpecified(index);
481         }
482     };
483     
484     
485     
486     //
487
//
488
// helper methods
489
//
490
//
491
/** Symbolizes the specified string. */
492     private String JavaDoc symbolize(String JavaDoc s) {
493         if (s == null)
494             return null;
495         else
496             return symbolTable.addSymbol(s);
497     }
498     
499     /** Creates a QName object. */
500     private QName createQName(String JavaDoc uri, String JavaDoc local, String JavaDoc raw) {
501         
502         if( local.length()==0 ) {
503             // if naemspace processing is turned off, local could be "".
504
// in that case, treat everything to be in the no namespace.
505
uri = "";
506             local = raw;
507         }
508         
509         int idx = raw.indexOf(':');
510         String JavaDoc prefix;
511         if (idx < 0)
512             prefix = null;
513         else
514             prefix = raw.substring(0, idx);
515         
516         if (uri != null && uri.length() == 0)
517             uri = null; // XNI uses null whereas SAX uses the empty string
518

519         return new QName(symbolize(prefix), symbolize(local), symbolize(raw), symbolize(uri));
520     }
521     
522     /** only one instance of XMLAttributes is used. */
523     private final XMLAttributes xa = new XMLAttributesImpl();
524     
525     /** Creates an XMLAttributes object. */
526     private XMLAttributes createAttributes(Attributes att) {
527         xa.removeAllAttributes();
528         int len = att.getLength();
529         for (int i = 0; i < len; i++) {
530             int idx = xa.addAttribute(
531             createQName(att.getURI(i), att.getLocalName(i), att.getQName(i)),
532             att.getType(i),
533             att.getValue(i));
534             // attributes present in the original SAX event streams
535
// are considered as "specified".
536
xa.setSpecified(idx,true);
537         }
538         return xa;
539     }
540     
541     private XMLString createXMLString(String JavaDoc str) {
542         // with my patch
543
// return new XMLString(str);
544

545         // for now
546
return new XMLString(str.toCharArray(), 0, str.length());
547     }
548     
549     /**
550      * Resets this handler.
551      * <p>
552      * Meaning resets all the user-specified configurations to the
553      * initial state, then also resets all the components.
554      */

555     public void reset() {
556         resetComponents();
557         errorHandler = null;
558         resourceResolver = null;
559     }
560 }
561
Popular Tags