View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.jelly.tags.validate;
17  
18  import org.apache.commons.jelly.JellyTagException;
19  import org.apache.commons.jelly.MissingAttributeException;
20  import org.apache.commons.jelly.TagSupport;
21  import org.apache.commons.jelly.XMLOutput;
22  import org.iso_relax.verifier.Verifier;
23  import org.iso_relax.verifier.VerifierFilter;
24  import org.iso_relax.verifier.VerifierHandler;
25  import org.xml.sax.ContentHandler;
26  import org.xml.sax.ErrorHandler;
27  import org.xml.sax.SAXException;
28  import org.xml.sax.SAXParseException;
29  import org.xml.sax.helpers.AttributesImpl;
30  
31  /***
32   * This tag validates its body using a schema Verifier which can
33   * validate against DTDs, XML Schema, RelaxNG, Relax or TREX.
34   * Any JARV compliant Verifier could be used.
35   * The error messages are output as XML events so that they can be styled by the parent tag.
36   *
37   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
38   * @version $Revision: 155420 $
39   */
40  public class ValidateTag extends TagSupport {
41  
42      /*** The verifier that this tag will use */
43      private Verifier verifier;
44  
45      /*** The SAX ErrorHandler */
46      private ErrorHandler errorHandler;
47  
48      /*** The boolean flag for whether the XML is valid */
49      private String var;
50  
51      // Tag interface
52      //-------------------------------------------------------------------------
53      public void doTag(final XMLOutput output) throws MissingAttributeException, JellyTagException {
54          if ( verifier == null ) {
55              throw new MissingAttributeException("verifier");
56          }
57          boolean valid = false;
58  
59          // evaluate the body using the current Verifier
60          if ( errorHandler != null ) {
61  
62              try {
63                  // we are redirecting errors to another handler
64                  // so just filter the body
65                  VerifierFilter filter = verifier.getVerifierFilter();
66  
67                  // now install the current output in the filter chain...
68                  // ####
69  
70                  ContentHandler handler = filter.getContentHandler();
71                  handler.startDocument();
72                  invokeBody( new XMLOutput( handler ) );
73                  handler.endDocument();
74                  valid = filter.isValid();
75              }
76              catch (SAXException e) {
77                  throw new JellyTagException(e);
78              }
79          }
80          else {
81              // outputting the errors to the current output
82              verifier.setErrorHandler(
83                  new ErrorHandler() {
84                      public void error(SAXParseException exception) throws SAXException {
85                          outputException(output, "error", exception);
86                      }
87  
88                      public void fatalError(SAXParseException exception) throws SAXException {
89                          outputException(output, "fatalError", exception);
90                      }
91  
92                      public void warning(SAXParseException exception) throws SAXException {
93                          outputException(output, "warning", exception);
94                      }
95                  }
96              );
97  
98              try {
99                  VerifierHandler handler = verifier.getVerifierHandler();
100                 handler.startDocument();
101                 invokeBody( new XMLOutput( handler ) );
102                 handler.endDocument();
103                 valid = handler.isValid();
104             }
105             catch (SAXException e) {
106                 throw new JellyTagException(e);
107             }
108         }
109         handleValid(valid);
110     }
111 
112     // Properties
113     //-------------------------------------------------------------------------
114 
115     /***
116      * Sets the schema Verifier that this tag will use to verify its body
117      *
118      * @jelly:required
119      */
120     public void setVerifier(Verifier verifier) {
121         this.verifier = verifier;
122     }
123 
124     /***
125      * @return the ErrorHandler used when validating
126      */
127     public ErrorHandler getErrorHandler() {
128         return errorHandler;
129     }
130 
131     /***
132      * Sets the SAX ErrorHandler which is used to capture
133      * XML validation events.
134      * If an ErrorHandler is specified
135      * then this tag will output its body and redirect all error messages
136      * to the ErrorHandler.
137      * If no ErrorHandler is specified then this tag will just output the
138      * error messages as XML events
139      *
140      * @jelly:optional
141      */
142     public void setErrorHandler(ErrorHandler errorHandler) {
143         this.errorHandler = errorHandler;
144     }
145 
146     /***
147      * Sets the name of the variable that will contain a boolean flag for whether or
148      * not the XML is valid.
149      *
150      * @jelly:optional
151      */
152     public void setVar(String var) {
153         this.var = var;
154     }
155 
156     // Implementation methods
157     //-------------------------------------------------------------------------
158 
159     /***
160      * Processes whether or not the document is valid.
161      * Derived classes can overload this method to do different things, such
162      * as to throw assertion exceptions etc.
163      */
164     protected void handleValid(boolean valid) {
165         if (var != null ) {
166             Boolean value = (valid) ? Boolean.TRUE : Boolean.FALSE;
167             context.setVariable(var, value);
168         }
169     }
170 
171     /***
172      * Outputs the given validation exception as XML to the output
173      */
174     protected void outputException(XMLOutput output, String name, SAXParseException e) throws SAXException {
175         AttributesImpl attributes = new AttributesImpl();
176         String uri = "";
177         String type = "CDATA";
178         attributes.addAttribute( uri, "column", "column", type, Integer.toString( e.getColumnNumber() ) );
179         attributes.addAttribute( uri, "line", "line", type, Integer.toString( e.getLineNumber() ) );
180 
181         String publicID = e.getPublicId();
182         if ( publicID != null && publicID.length() > 0 ) {
183             attributes.addAttribute( uri, "publicID", "publicID", type, publicID );
184         }
185         String systemID = e.getSystemId();
186         if ( systemID != null && systemID.length() > 0 ) {
187             attributes.addAttribute( uri, "systemID", "systemID", type, systemID );
188         }
189 
190         output.startElement( uri, name, name, attributes );
191         output.write( e.getMessage() );
192         output.endElement( uri, name, name );
193     }
194 
195 
196 }