KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > transformation > ValidationReportTransformer


1 /*
2  * Copyright 1999-2005 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.cocoon.transformation;
17
18 import java.io.IOException JavaDoc;
19 import java.io.Serializable JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import org.apache.avalon.framework.activity.Disposable;
26 import org.apache.avalon.framework.configuration.Configurable;
27 import org.apache.avalon.framework.configuration.Configuration;
28 import org.apache.avalon.framework.configuration.ConfigurationException;
29 import org.apache.avalon.framework.parameters.Parameters;
30 import org.apache.avalon.framework.service.ServiceException;
31 import org.apache.avalon.framework.service.ServiceManager;
32 import org.apache.avalon.framework.service.Serviceable;
33 import org.apache.cocoon.ProcessingException;
34 import org.apache.cocoon.caching.CacheableProcessingComponent;
35 import org.apache.cocoon.components.validation.ValidationHandler;
36 import org.apache.cocoon.components.validation.Validator;
37 import org.apache.cocoon.environment.SourceResolver;
38 import org.apache.cocoon.xml.XMLConsumer;
39 import org.apache.excalibur.source.Source;
40 import org.apache.excalibur.source.SourceValidity;
41 import org.xml.sax.ContentHandler JavaDoc;
42 import org.xml.sax.ErrorHandler JavaDoc;
43 import org.xml.sax.SAXException JavaDoc;
44 import org.xml.sax.SAXParseException JavaDoc;
45 import org.xml.sax.helpers.AttributesImpl JavaDoc;
46
47 /**
48  * <p>The {@link ValidationReportTransformer} provides a {@link Transformer}
49  * validating documents while being processed in a Cocoon pipeline, and preparing
50  * a report of all detected inconsistancies according the specified schema.</p>
51  *
52  * <p>The only defined (but not required) configuration for this component is
53  * <code>&lt;grammar&gt;<i>...string...</i>&lt;/grammar&gt;</code>
54  * indicating the default grammar language of the schemas to use.</p>
55  *
56  * <p>This configuration parameter can be overridden by specifying the
57  * <code>grammar</code> parameter when using this {@link Transformer} in a
58  * pipeline.</p>
59  *
60  * <p>If no grammar is specified (either as a configuration, or a parameter) this
61  * transformer will instruct the {@link Validator} to try and guess the grammar
62  * of the schema being parsed.</p>
63  *
64  * <p>The report prepared by this transformer will look like the following:</p>
65  *
66  * <pre>
67  * &lt;report xmlns="http://apache.org/cocoon/validation/1.0"&gt;
68  * &lt;warning system="..." public="..." line="..." column="..."&gt;
69  * ... detailed message ...
70  * &lt;/warning&gt;
71  * &lt;error system="..." public="..." line="..." column="..."&gt;
72  * ... detailed message ...
73  * &lt;/error&gt;
74  * &lt;fatal system="..." public="..." line="..." column="..."&gt;
75  * ... message ...
76  * &lt;/fatal&gt;
77  * &lt;/report&gt;
78  * </pre>
79  *
80  * <p>The location attributes specified in the <code>&lt;warning/&gt;</code>,
81  * <code>&lt;error/&gt;</code> and <code>&lt;fatal/&gt;</code> tags are all optional
82  * and will be generated only if known.</p>
83  *
84  * @author <a HREF="mailto:pier@betaversion.org">Pier Fumagalli</a>
85  */

86 public class ValidationReportTransformer extends AbstractTransformer
87 implements Configurable, Serviceable, Disposable, CacheableProcessingComponent {
88     
89     /** <p>The configured {@link ServiceManager} instance.</p> */
90     private ServiceManager serviceManager = null;
91     /** <p>The configured {@link Validator} instance.</p> */
92     private Validator validator = null;
93     /** <p>The configured default grammar language.</p> */
94     private String JavaDoc grammar = null;
95
96     /** <p>The {@link Report} instance to be used while processing a request.</p> */
97     private Report report = null;
98     /** <p>The {@link ValidationHandler} to use in this transformation.</p> */
99     private ValidationHandler handler = null;
100     /** <p>The {@link XMLConsumer} to send the validation report to.</p> */
101     private XMLConsumer consumer = null;
102     /** <p>A unique key identifying the schema source for caching.</p> */
103     private String JavaDoc key = null;
104
105     /**
106      * <p>Create a new {@link ValidationReportTransformer} instance.</p>
107      */

108     public ValidationReportTransformer() {
109         super();
110     }
111
112     /**
113      * <p>Contextualize this component instance specifying its associated
114      * {@link ServiceManager} instance.</p>
115      *
116      * @param manager the {@link ServiceManager} to associate with this component.
117      * @throws ServiceException if a dependancy of this could not be resolved.
118      */

119     public void service(ServiceManager manager)
120     throws ServiceException {
121         this.serviceManager = manager;
122         this.validator = (Validator) manager.lookup(Validator.ROLE);
123     }
124
125     /**
126      * <p>Configure this component instance.</p>
127      *
128      * <p>The only defined (but not required) configuration for this component is
129      * <code>&lt;grammar&gt;<i>...string...</i>&lt;/grammar&gt;</code>
130      * indicating the default grammar used by this transformer used for parsing
131      * schemas.</p>
132      *
133      * @param configuration a {@link Configuration} instance for this component.
134      * @throws ConfigurationException never thrown.
135      */

136     public void configure(Configuration configuration)
137     throws ConfigurationException {
138         this.grammar = configuration.getChild("grammar").getValue(null);
139     }
140
141     /**
142      * <p>Dispose of this component instance releasing all previously acquired
143      * required instances back to the {@link ServiceManager}.</p>
144      */

145     public void dispose() {
146         this.serviceManager.release(this.validator);
147     }
148
149     /**
150      * <p>Contextualize this component in the scope of a pipeline when a request
151      * is processed.</p>
152      *
153      * @param resolver the {@link SourceResolver} contextualized in this request.
154      * @param objectModel unused.
155      * @param source the source URI of the schema to validate against.
156      * @param parameters unused.
157      */

158     public void setup(SourceResolver resolver, Map JavaDoc objectModel, String JavaDoc source,
159                       Parameters parameters)
160     throws ProcessingException, SAXException JavaDoc, IOException JavaDoc {
161         Source s = null;
162         try {
163             Report r = new Report();
164             String JavaDoc g = parameters.getParameter("grammar", this.grammar);
165             s = resolver.resolveURI(source);
166             if (g == null) {
167                 this.handler = this.validator.getValidationHandler(s, r);
168             } else{
169                 this.handler = this.validator.getValidationHandler(s, g, r);
170             }
171             this.setContentHandler(this.handler);
172             this.setLexicalHandler(this.handler);
173             this.report = r;
174         } finally {
175             if (source != null) resolver.release(s);
176         }
177     }
178
179     /**
180      * <p>Specify the {@link XMLConsumer} receiving SAX events emitted by this
181      * {@link Transformer} instance in the scope of a request.</p>
182      *
183      * @param consumer the {@link XMLConsumer} to send SAX events to.
184      */

185     public void setConsumer(XMLConsumer consumer) {
186         this.consumer = consumer;
187     }
188
189     /**
190      * <p>Receive notification of the end of the document and produce the report
191      * of the validation result.</p>
192      *
193      * @throws SAXException
194      * @see org.xml.sax.ContentHandler#endDocument()
195      */

196     public void endDocument()
197     throws SAXException JavaDoc {
198         super.endDocument();
199         this.report.generateReport(this.consumer);
200     }
201
202     /**
203      * <p>Return the unique key to associated with the schema being processed in
204      * the scope of the request being processed for caching.</p>
205      *
206      * @return a non null {@link String} representing the unique key for the schema.
207      */

208     public Serializable JavaDoc getKey() {
209         return this.key;
210     }
211
212     /**
213      * <p>Return the {@link SourceValidity} associated with the schema currently
214      * being processed in the scope of the request being processed.</p>
215      *
216      * @return a non null {@link SourceValidity} instance.
217      */

218     public SourceValidity getValidity() {
219         return this.handler.getValidity();
220     }
221
222     /**
223      * <p>Recycle this component instance at the end of request processing.</p>
224      */

225     public void recycle() {
226         this.consumer = null;
227         this.handler = null;
228         this.report = null;
229         this.key = null;
230         super.recycle();
231     }
232     
233     /**
234      *
235      */

236     private static final class Report implements ErrorHandler JavaDoc {
237
238         private static final String JavaDoc NS = "http://apache.org/cocoon/validation/1.0";
239         private final List JavaDoc entries = new ArrayList JavaDoc();
240
241         public void warning(SAXParseException JavaDoc exception)
242         throws SAXException JavaDoc {
243             this.entries.add(new ReportEntry("warning", exception));
244         }
245
246         public void error(SAXParseException JavaDoc exception)
247         throws SAXException JavaDoc {
248             this.entries.add(new ReportEntry("error", exception));
249         }
250
251         public void fatalError(SAXParseException JavaDoc exception)
252         throws SAXException JavaDoc {
253             this.entries.add(new ReportEntry("fatal", exception));
254         }
255
256         private void generateReport(ContentHandler JavaDoc handler)
257         throws SAXException JavaDoc {
258             /* Start the report */
259             handler.startDocument();
260             handler.startPrefixMapping("", NS);
261             AttributesImpl JavaDoc attributes = new AttributesImpl JavaDoc();
262             handler.startElement(NS, "report", "report", attributes);
263
264             /* Each collected error will generate its own entry */
265             Iterator JavaDoc iterator = this.entries.iterator();
266             while(iterator.hasNext()) {
267                 ReportEntry entry = (ReportEntry) iterator.next();
268                 attributes.clear();
269
270                 if (entry.exception.getPublicId() != null) {
271                     if (! "".equals(entry.exception.getPublicId())) {
272                         attributes.addAttribute("", "public", "public", "CDATA",
273                                                 entry.exception.getPublicId());
274                     }
275                 }
276
277                 if (entry.exception.getSystemId() != null) {
278                     if (! "".equals(entry.exception.getSystemId())) {
279                         attributes.addAttribute("", "system", "system", "CDATA",
280                                                 entry.exception.getSystemId());
281                     }
282                 }
283
284                 if (entry.exception.getLineNumber() >= 0) {
285                     String JavaDoc l = Integer.toString(entry.exception.getLineNumber());
286                     attributes.addAttribute("", "line", "line", "CDATA", l);
287                 }
288
289                 if (entry.exception.getColumnNumber() >= 0) {
290                     String JavaDoc c = Integer.toString(entry.exception.getColumnNumber());
291                     attributes.addAttribute("", "column", "column", "CDATA", c);
292                 }
293                 
294                 String JavaDoc level = entry.level;
295                 handler.startElement(NS, level, level, attributes);
296                 char message[] = entry.exception.getMessage().toCharArray();
297                 handler.characters(message, 0, message.length);
298                 handler.endElement(NS, level, level);
299             }
300
301             /* After all the exceptions have been dumped, close the report */
302             handler.endElement(NS, "report", "report");
303             handler.endPrefixMapping("");
304             handler.endDocument();
305         }
306     }
307
308     private static final class ReportEntry {
309         
310         private final String JavaDoc level;
311         private final SAXParseException JavaDoc exception;
312         
313         private ReportEntry(String JavaDoc level, SAXParseException JavaDoc exception) {
314             this.level = level;
315             this.exception = exception;
316         }
317     }
318 }
319
Popular Tags