1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.xmlhammer.gui.xslt;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.ByteArrayOutputStream;
26 import java.io.File;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.io.PrintStream;
31 import java.net.MalformedURLException;
32 import java.net.URI;
33 import java.util.ArrayList;
34 import java.util.List;
35
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import javax.xml.parsers.SAXParser;
40 import javax.xml.transform.Source;
41 import javax.xml.transform.Transformer;
42 import javax.xml.transform.TransformerConfigurationException;
43 import javax.xml.transform.TransformerException;
44 import javax.xml.transform.TransformerFactory;
45 import javax.xml.transform.dom.DOMSource;
46 import javax.xml.transform.sax.SAXSource;
47 import javax.xml.transform.stream.StreamResult;
48 import javax.xml.transform.stream.StreamSource;
49
50 import org.apache.log4j.Logger;
51 import org.bounce.util.URIUtils;
52 import org.xml.sax.InputSource;
53 import org.xml.sax.SAXException;
54 import org.xml.sax.SAXParseException;
55 import org.xmlhammer.DefaultErrorHandler;
56 import org.xmlhammer.Module;
57 import org.xmlhammer.ResultModel;
58 import org.xmlhammer.DefaultErrorHandler.Error;
59 import org.xmlhammer.DefaultErrorHandler.Fatal;
60 import org.xmlhammer.DefaultErrorHandler.Message;
61 import org.xmlhammer.DefaultErrorHandler.Problem;
62 import org.xmlhammer.DefaultErrorHandler.Warning;
63 import org.xmlhammer.gui.status.StatusModel;
64 import org.xmlhammer.model.preferences.Preferences;
65 import org.xmlhammer.model.project.Parameter;
66 import org.xmlhammer.model.project.ParameterisedSource;
67 import org.xmlhammer.model.project.Project;
68 import org.xmlhammer.model.tools.xslt.Associated;
69 import org.xmlhammer.model.tools.xslt.OutputProperty;
70 import org.xmlhammer.model.tools.xslt.XSLT.Transform;
71
72 /***
73 * Put comment...
74 *
75 * @version $Revision$, $Date$
76 * @author Edwin Dankert <edankert@gmail.com>
77 */
78 public class XSLTModule extends Module {
79 private SAXParser parser = null;
80 private DocumentBuilder builder = null;
81 private TransformerFactory factory = null;
82 private ArrayList<Transformer> transformers = null;
83 private Associated associated = null;
84 private Transform transform = null;
85
86 public XSLTModule(Preferences preferences, Project project, Logger logger, boolean logSettings) throws SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException {
87 super(preferences, project, logger, logSettings);
88
89 if ("dom".equals(getProject().getParser().getType())) {
90 DocumentBuilderFactory factory = getDocumentBuilderFactory();
91 builder = factory.newDocumentBuilder();
92 } else {
93 parser = getSAXParser();
94 }
95
96 factory = getTransformerFactory();
97
98 transform = project.getXSLT().getTransform();
99 if (transform.getAssociated() != null) {
100 associated = transform.getAssociated();
101 return;
102 }
103
104 if (associated == null) {
105 transformers = getTransformers(logger);
106 }
107 }
108
109 /***
110 * Sets-up an XML Validator Module.
111 *
112 * @param preferences the global preferences.
113 * @param project the project specific properties;
114 * @throws ParserConfigurationException
115 * @throws SAXException
116 */
117 public XSLTModule(Preferences preferences, Project project, Logger logger) throws SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException {
118 this(preferences, project, logger, true);
119 }
120
121 private void setOutputProperties(Transformer transformer) {
122 if (transformer != null) {
123 List<OutputProperty> properties = getProject().getXSLT().getOutputProperties().getOutputProperty();
124 for (OutputProperty property : properties) {
125 if (property.isActive()) {
126 transformer.setOutputProperty(property.getName(), property.getValue());
127 }
128 }
129 }
130 }
131
132 public boolean isResultEnabled() {
133 return true;
134 }
135
136 /***
137 * Execute the XPath expressio.
138 * @throws MalformedURLException
139 * @throws ParserConfigurationException
140 */
141 @Override
142 public void execute(StatusModel status, ResultModel result, URI sourceURI, URI resultURI) {
143 PrintStream err = System.err;
144 PrintStream out = System.out;
145 DefaultErrorHandler errorHandler = new DefaultErrorHandler(null);
146
147 if (sourceURI != null && resultURI != null) {
148
149
150
151 InputSource in = new InputSource(sourceURI.toString());
152
153 System.setErr(new PrintStream(new LogOutputStream("err", errorHandler), true));
154 System.setOut(new PrintStream(new LogOutputStream("out", errorHandler), true));
155
156 try {
157 FileOutputStream resultOuputStream = new FileOutputStream(new File(resultURI));
158
159
160 if ( "dom".equals(getProject().getParser().getType())) {
161 builder.setErrorHandler(errorHandler);
162 builder.setEntityResolver(getCatalogResolver());
163 DOMSource source = new DOMSource(builder.parse( in), in.getSystemId());
164
165 if (associated != null) {
166 transformers = new ArrayList<Transformer>();
167 Source style = factory.getAssociatedStylesheet(source, associated.getMedia(), associated.getTitle(), associated.getCharset());
168 Transformer transformer = null;
169
170 try {
171 transformer = getTransformer(result, sourceURI, style, associated.getParameter());
172 } catch (TransformerException e) {
173 return;
174 }
175
176 setOutputProperties(transformer);
177
178 transformers.add(transformer);
179 }
180
181 getLogger().info( "transform: "+URIUtils.toString(sourceURI));
182
183 for (Transformer transformer : transformers) {
184 transformer.setErrorListener(errorHandler);
185 StreamResult stream = null;
186
187 if (transformer == transformers.get(transformers.size()-1)) {
188 stream = new StreamResult(resultOuputStream);
189 } else {
190 stream = new StreamResult(new ByteArrayOutputStream());
191 }
192
193 transformer.transform(source, stream);
194
195 if (stream.getOutputStream() instanceof ByteArrayOutputStream) {
196 in.setByteStream(new ByteArrayInputStream(((ByteArrayOutputStream)stream.getOutputStream()).toByteArray()));
197 source = new DOMSource(builder.parse( in), in.getSystemId());
198 }
199 }
200 } else {
201 parser.getXMLReader().setErrorHandler(errorHandler);
202 parser.getXMLReader().setEntityResolver(getCatalogResolver());
203 SAXSource source = new SAXSource(parser.getXMLReader(), in);
204
205 if (associated != null) {
206 transformers = new ArrayList<Transformer>();
207 Source style = factory.getAssociatedStylesheet(source, associated.getMedia(), associated.getTitle(), associated.getCharset());
208
209 Transformer transformer = null;
210
211 try {
212 transformer = getTransformer(result, sourceURI, style, associated.getParameter());
213 } catch (TransformerException e) {
214 return;
215 }
216
217 setOutputProperties(transformer);
218
219 transformers.add(transformer);
220 }
221
222 getLogger().info( "transform: "+URIUtils.toString(sourceURI));
223
224 for (Transformer transformer : transformers) {
225 transformer.setErrorListener(errorHandler);
226 StreamResult stream = null;
227
228 if (transformer == transformers.get(transformers.size()-1)) {
229 stream = new StreamResult(resultOuputStream);
230 } else {
231 stream = new StreamResult(new ByteArrayOutputStream());
232 }
233
234 transformer.transform(source, stream);
235
236 if (stream.getOutputStream() instanceof ByteArrayOutputStream) {
237 in.setByteStream(new ByteArrayInputStream(((ByteArrayOutputStream)stream.getOutputStream()).toByteArray()));
238 }
239 }
240 }
241
242 resultOuputStream.flush();
243 resultOuputStream.close();
244
245 } catch ( SAXException e) {
246 if ( e instanceof SAXParseException) {
247 try {
248 errorHandler.fatalError( (SAXParseException)e);
249 } catch ( Exception x) {}
250 }
251 } catch (IOException e) {
252 errorHandler.fatalError(e);
253 } catch (TransformerException e) {
254 errorHandler.fatalError(e);
255 } finally {
256 System.setErr(err);
257 System.setOut(out);
258 }
259
260 ArrayList<Problem> list = errorHandler.getProblems();
261 if ( list.size() > 0) {
262 for (Problem problem : list) {
263 if (problem instanceof Warning) {
264 if (problem.getException() instanceof SAXParseException) {
265 logWarning(sourceURI, (SAXParseException)problem.getException());
266
267 if (result != null) {
268 result.addWarning(sourceURI, (SAXParseException)problem.getException());
269 }
270 } else {
271 logWarning(sourceURI, (TransformerException)problem.getException());
272
273 if (result != null) {
274 result.addWarning(sourceURI, (TransformerException)problem.getException());
275 }
276 }
277 } else if (problem instanceof Error) {
278 if (problem.getException() instanceof SAXParseException) {
279 logError(sourceURI, (SAXParseException)problem.getException());
280
281 if (result != null) {
282 result.addError(sourceURI, (SAXParseException)problem.getException());
283 }
284 } else {
285 logError(sourceURI, (TransformerException)problem.getException());
286
287 if (result != null) {
288 result.addError(sourceURI, (TransformerException)problem.getException());
289 }
290 }
291 } else if (problem instanceof Fatal) {
292 logFatal(sourceURI, problem.getException());
293
294 if (result != null) {
295 Exception exception = problem.getException();
296 if ( exception instanceof IOException) {
297 result.addFatal(sourceURI, (IOException)problem.getException());
298 } else if ( exception instanceof SAXParseException) {
299 result.addFatal(sourceURI, (SAXParseException)problem.getException());
300 } else {
301 result.addFatal(sourceURI, (TransformerException)problem.getException());
302 }
303 }
304 } else if ( problem instanceof Message) {
305 getLogger().info( "\t[message] "+((Message)problem).getMessage());
306
307 if (result != null) {
308 result.addMessage(sourceURI, ((Message)problem).getType(), ((Message)problem).getMessage());
309 }
310 }
311 }
312 } else {
313 getLogger().info( "\t[processed] Document Processed");
314
315 if (result != null) {
316 result.addValid(sourceURI);
317 }
318 }
319 }
320 }
321
322 private ArrayList<Transformer> getTransformers(Logger logger) throws TransformerException {
323 if (transformers == null) {
324 transformers = new ArrayList<Transformer>();
325
326 if (transform.getStylesheets() != null) {
327 List<ParameterisedSource> stylesheets = transform.getStylesheets().getParameterisedSource();
328 for (ParameterisedSource stylesheet: stylesheets) {
329 Transformer transformer = getTransformer(null, null, new StreamSource(stylesheet.getSrc()), stylesheet.getParameter());
330
331 transformers.add(transformer);
332 }
333
334 setOutputProperties(transformers.get(transformers.size()-1));
335 } else {
336 try {
337 Transformer transformer = factory.newTransformer();
338 transformers.add(transformer);
339 setOutputProperties(transformer);
340 } catch (TransformerConfigurationException e) {
341
342 e.printStackTrace();
343 }
344 }
345 }
346
347 return transformers;
348 }
349
350 private Transformer getTransformer(ResultModel result, URI base, Source source, List<Parameter> parameters) throws TransformerException {
351 Transformer transformer = null;
352 TransformerException exception = null;
353
354 if (source != null) {
355 getLogger().info( "validate stylesheet: "+source.getSystemId());
356
357 DefaultErrorHandler errorHandler = new DefaultErrorHandler(URIUtils.createURI(source.getSystemId()));
358
359 try {
360 factory.setErrorListener(errorHandler);
361 transformer = factory.newTransformer(source);
362
363 for (Parameter parameter : parameters) {
364 if (parameter.isActive()) {
365 getLogger().info("\t[parameter] "+parameter.getName()+" = "+parameter.getValue());
366 transformer.setParameter(parameter.getName(), parameter.getValue());
367 }
368 }
369 } catch (TransformerException e) {
370 errorHandler.fatalError(e);
371 exception = e;
372 }
373
374 ArrayList<Problem> list = errorHandler.getProblems();
375 if ( list.size() > 0) {
376 for ( Problem problem : list) {
377 if ( problem instanceof Warning) {
378 logWarning(base, (TransformerException)problem.getException());
379
380 if (result != null) {
381 result.addWarning(base, (TransformerException)problem.getException());
382 }
383 } else if ( problem instanceof Error) {
384 logError(base, (TransformerException)problem.getException());
385
386 if (result != null) {
387 result.addError(base, (TransformerException)problem.getException());
388 }
389 } else if ( problem instanceof Fatal) {
390 logFatal(base, problem.getException());
391
392 if (result != null) {
393 if (problem.getException() instanceof IOException) {
394 result.addFatal(base, (IOException)problem.getException());
395 } else {
396 result.addFatal(base, (TransformerException)problem.getException());
397 }
398 }
399 }
400 }
401 } else {
402 getLogger().info( "\t[valid] Valid Stylesheet");
403 }
404 }
405
406 if (exception != null) {
407 throw exception;
408 }
409
410 return transformer;
411 }
412
413 class LogOutputStream extends OutputStream {
414 private StringBuffer buffer = new StringBuffer();
415 private DefaultErrorHandler handler = null;
416 private String type = null;
417
418 public LogOutputStream(String type, DefaultErrorHandler handler) {
419 this.handler = handler;
420 this.type = type;
421 }
422
423 public void write(int b) {
424 buffer.append( (char)b);
425 }
426
427 public void flush () {
428 String message = buffer.toString().trim();
429 if (message.length() > 0) {
430 handler.message(type, message);
431 }
432
433 buffer = new StringBuffer();
434 }
435 }
436 }