KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > tools > adaptor > http > XSLTProcessor


1 /*
2  * Copyright (C) The MX4J Contributors.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.tools.adaptor.http;
10
11 import java.io.BufferedInputStream JavaDoc;
12 import java.io.BufferedOutputStream JavaDoc;
13 import java.io.ByteArrayOutputStream JavaDoc;
14 import java.io.File JavaDoc;
15 import java.io.FileInputStream JavaDoc;
16 import java.io.FileNotFoundException JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.io.InputStream JavaDoc;
19 import java.net.MalformedURLException JavaDoc;
20 import java.net.URL JavaDoc;
21 import java.net.URLClassLoader JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Locale JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.StringTokenizer JavaDoc;
27 import javax.management.MBeanException JavaDoc;
28 import javax.management.ReflectionException JavaDoc;
29 import javax.management.RuntimeMBeanException JavaDoc;
30 import javax.xml.transform.Source JavaDoc;
31 import javax.xml.transform.Templates JavaDoc;
32 import javax.xml.transform.Transformer JavaDoc;
33 import javax.xml.transform.TransformerConfigurationException JavaDoc;
34 import javax.xml.transform.TransformerException JavaDoc;
35 import javax.xml.transform.TransformerFactory JavaDoc;
36 import javax.xml.transform.URIResolver JavaDoc;
37 import javax.xml.transform.dom.DOMSource JavaDoc;
38 import javax.xml.transform.stream.StreamResult JavaDoc;
39 import javax.xml.transform.stream.StreamSource JavaDoc;
40
41 import mx4j.log.Log;
42 import mx4j.log.Logger;
43 import org.w3c.dom.Document JavaDoc;
44
45 /**
46  * XSLTPostProcessor pass the document through an XSLT transformation
47  *
48  * @version $Revision: 1.8 $
49  */

50 public class XSLTProcessor implements ProcessorMBean, XSLTProcessorMBean, URIResolver JavaDoc
51 {
52    private String JavaDoc path = "mx4j/tools/adaptor/http/xsl";
53    private String JavaDoc defaultPage = "serverbydomain";
54    private TransformerFactory JavaDoc factory;
55    private Map JavaDoc templatesCache = new HashMap JavaDoc();
56    private File JavaDoc root;
57    private Map JavaDoc mimeTypes = new HashMap JavaDoc();
58    /**
59     * Indicated whether the file are read from a file
60     */

61    private boolean useJar = true;
62    private volatile boolean useCache = true;
63    private ClassLoader JavaDoc targetClassLoader = ClassLoader.getSystemClassLoader();
64    /**
65     * The locale is set with the default as en_US since it is the
66     * one bundled
67     */

68    private Locale JavaDoc locale = new Locale JavaDoc("en", "");
69
70    public XSLTProcessor()
71    {
72       factory = TransformerFactory.newInstance();
73       factory.setURIResolver(this);
74       mimeTypes.put(".gif", "image/gif");
75       mimeTypes.put(".jpg", "image/jpg");
76       mimeTypes.put(".png", "image/png");
77       mimeTypes.put(".tif", "image/tiff");
78       mimeTypes.put(".tiff", "image/tiff");
79       mimeTypes.put(".ico", "image/ico");
80       mimeTypes.put(".html", "text/html");
81       mimeTypes.put(".htm", "text/html");
82       mimeTypes.put(".txt", "text/plain");
83       mimeTypes.put(".xml", "text/xml");
84       mimeTypes.put(".xsl", "text/xsl");
85       mimeTypes.put(".css", "text/css");
86       mimeTypes.put(".js", "text/x-javascript");
87       mimeTypes.put(".jar", "application/java-archive");
88    }
89
90    private Logger getLogger()
91    {
92       return Log.getLogger(getClass().getName());
93    }
94
95    public void writeResponse(HttpOutputStream out, HttpInputStream in, Document JavaDoc document) throws IOException JavaDoc
96    {
97       Logger log = getLogger();
98
99       out.setCode(HttpConstants.STATUS_OKAY);
100       out.setHeader("Content-Type", "text/html");
101       // added some caching attributes to force not to cache
102
out.setHeader("Cache-Control", "no-cache");
103       out.setHeader("expires", "now");
104       out.setHeader("pragma", "no-cache");
105       out.sendHeaders();
106       Transformer JavaDoc transformer = null;
107       String JavaDoc path = preProcess(in.getPath());
108
109       if (in.getVariable("template") != null)
110       {
111          transformer = createTransformer(in.getVariable("template") + ".xsl");
112       }
113       else
114       {
115          transformer = createTransformer(path + ".xsl");
116       }
117
118       if (transformer != null)
119       {
120          // added so that the document() function works
121
transformer.setURIResolver(this);
122          // The variables are passed to the XSLT as (param.name, value)
123
Map JavaDoc variables = in.getVariables();
124          Iterator JavaDoc j = variables.keySet().iterator();
125          while (j.hasNext())
126          {
127             String JavaDoc key = (String JavaDoc)j.next();
128             Object JavaDoc value = variables.get(key);
129             if (value instanceof String JavaDoc)
130             {
131                transformer.setParameter("request." + key, value);
132             }
133             if (value instanceof String JavaDoc[])
134             {
135                String JavaDoc[] allvalues = (String JavaDoc[])value;
136                // not a good solution, only the first one is presented
137
transformer.setParameter("request." + key, allvalues[0]);
138             }
139
140          }
141          if (!variables.containsKey("locale"))
142          {
143             transformer.setParameter("request.locale", locale.toString());
144          }
145          try
146          {
147             ByteArrayOutputStream JavaDoc output = new ByteArrayOutputStream JavaDoc();
148             if (log.isEnabledFor(Logger.TRACE)) log.trace("transforming " + path);
149             transformer.transform(new DOMSource JavaDoc(document), new StreamResult JavaDoc(output));
150             output.writeTo(out);
151          }
152          catch (TransformerException JavaDoc e)
153          {
154             log.error("Transformation exception ", e);
155          }
156       }
157       else
158       {
159          log.warn("Transformer for path " + path + " not found");
160       }
161    }
162
163    protected Transformer JavaDoc createTransformer(String JavaDoc path)
164    {
165       Logger logger = getLogger();
166       try
167       {
168          synchronized (this)
169          {
170             if (useCache && templatesCache.containsKey(path))
171             {
172                return ((Templates JavaDoc)templatesCache.get(path)).newTransformer();
173             }
174             else
175             {
176                InputStream JavaDoc stream = getInputStream(path);
177                if (stream != null)
178                {
179                   if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Creating template for path " + path);
180                   Templates JavaDoc template = factory.newTemplates(new StreamSource JavaDoc(stream));
181                   if (useCache) templatesCache.put(path, template);
182                   return template.newTransformer();
183                }
184                else
185                {
186                   if (logger.isEnabledFor(Logger.INFO)) logger.info("XSL template for path '" + path + "' not found");
187                }
188             }
189          }
190       }
191       catch (TransformerConfigurationException JavaDoc e)
192       {
193          logger.error("Exception during XSL template construction", e);
194       }
195       return null;
196    }
197
198    protected void processHttpException(HttpInputStream in, HttpOutputStream out, HttpException e) throws IOException JavaDoc
199    {
200       out.setCode(e.getCode());
201       out.setHeader("Content-Type", "text/html");
202       out.sendHeaders();
203       // hardcoded dir :-P
204
Transformer JavaDoc transformer = createTransformer("error.xsl");
205       transformer.setURIResolver(this);
206       Document JavaDoc doc = e.getResponseDoc();
207       if (doc != null)
208       {
209          try
210          {
211             if (!in.getVariables().containsKey("locale"))
212             {
213                transformer.setParameter("request.locale", locale.toString());
214             }
215             ByteArrayOutputStream JavaDoc output = new ByteArrayOutputStream JavaDoc();
216             transformer.transform(new DOMSource JavaDoc(doc), new StreamResult JavaDoc(output));
217             output.writeTo(out);
218          }
219          catch (TransformerException JavaDoc ex)
220          {
221             Logger log = getLogger();
222             log.error("Exception during error output", ex);
223          }
224       }
225    }
226
227    public void writeError(HttpOutputStream out, HttpInputStream in, Exception JavaDoc e) throws IOException JavaDoc
228    {
229       Logger log = getLogger();
230       Exception JavaDoc t = e;
231       if (e instanceof RuntimeMBeanException JavaDoc)
232       {
233          t = ((RuntimeMBeanException JavaDoc)e).getTargetException();
234       }
235       if (log.isEnabledFor(Logger.DEBUG)) log.debug("Processing error " + t.getMessage());
236       if (t instanceof HttpException)
237       {
238          processHttpException(in, out, (HttpException)t);
239       }
240       else if ((t instanceof MBeanException JavaDoc) && (((MBeanException JavaDoc)t).getTargetException() instanceof HttpException))
241       {
242          processHttpException(in, out, (HttpException)((MBeanException JavaDoc)t).getTargetException());
243       }
244       else if ((t instanceof ReflectionException JavaDoc) && (((ReflectionException JavaDoc)t).getTargetException() instanceof HttpException))
245       {
246          processHttpException(in, out, (HttpException)((ReflectionException JavaDoc)t).getTargetException());
247       }
248       else
249       {
250          out.setCode(HttpConstants.STATUS_INTERNAL_ERROR);
251          out.setHeader("Content-Type", "text/html");
252          out.sendHeaders();
253       }
254    }
255
256    public String JavaDoc preProcess(String JavaDoc path)
257    {
258       if (path.equals("/"))
259       {
260          path = "/" + defaultPage;
261       }
262       return path;
263    }
264
265    public String JavaDoc notFoundElement(String JavaDoc path, HttpOutputStream out, HttpInputStream in) throws IOException JavaDoc, HttpException
266    {
267       Logger log = getLogger();
268
269       File JavaDoc file = new File JavaDoc(this.path, path);
270       if (log.isEnabledFor(Logger.DEBUG)) log.debug("Processing file request " + file);
271       String JavaDoc name = file.getName();
272       int extensionIndex = name.lastIndexOf('.');
273       String JavaDoc mime = null;
274       if (extensionIndex < 0)
275       {
276          log.warn("Filename has no extensions " + file.toString());
277          mime = "text/plain";
278       }
279       else
280       {
281          String JavaDoc extension = name.substring(extensionIndex, name.length());
282          if (mimeTypes.containsKey(extension))
283          {
284             mime = (String JavaDoc)mimeTypes.get(extension);
285          }
286          else
287          {
288             log.warn("MIME type not found " + extension);
289             mime = "text/plain";
290          }
291       }
292       try
293       {
294          if (log.isEnabledFor(Logger.DEBUG)) log.debug("Trying to read file " + file);
295          BufferedInputStream JavaDoc fileIn = new BufferedInputStream JavaDoc(getInputStream(path));
296          ByteArrayOutputStream JavaDoc outArray = new ByteArrayOutputStream JavaDoc();
297          BufferedOutputStream JavaDoc outBuffer = new BufferedOutputStream JavaDoc(outArray);
298          int piece = 0;
299          while ((piece = fileIn.read()) >= 0)
300          {
301             outBuffer.write(piece);
302          }
303          outBuffer.flush();
304          out.setCode(HttpConstants.STATUS_OKAY);
305          out.setHeader("Content-type", mime);
306          out.sendHeaders();
307          if (log.isEnabledFor(Logger.DEBUG)) log.debug("File output " + mime);
308          outArray.writeTo(out);
309          fileIn.close();
310       }
311       catch (Exception JavaDoc e)
312       {
313          log.warn("Exception loading file " + file, e);
314          throw new HttpException(HttpConstants.STATUS_NOT_FOUND, "file " + file + " not found");
315       }
316       return null;
317    }
318
319    protected InputStream JavaDoc getInputStream(String JavaDoc path)
320    {
321       InputStream JavaDoc file = null;
322       if (!useJar)
323       {
324          try
325          {
326             // load from a dir
327
file = new FileInputStream JavaDoc(new File JavaDoc(this.root, path));
328          }
329          catch (FileNotFoundException JavaDoc e)
330          {
331             Logger log = getLogger();
332             log.error("File not found", e);
333          }
334       }
335       else
336       {
337          // load from a jar
338
String JavaDoc targetFile = this.path;
339          // workaround, should tought of somehting better
340
if (path.startsWith("/"))
341          {
342             targetFile += path;
343          }
344          else
345          {
346             targetFile += "/" + path;
347          }
348          if (root != null)
349          {
350             file = targetClassLoader.getResourceAsStream(targetFile);
351          }
352          if (file == null)
353          {
354             ClassLoader JavaDoc cl = getClass().getClassLoader();
355             if (cl == null)
356             {
357                file = ClassLoader.getSystemClassLoader().getResourceAsStream(targetFile);
358             }
359             else
360             {
361                file = getClass().getClassLoader().getResourceAsStream(targetFile);
362             }
363             file = getClass().getClassLoader().getResourceAsStream(targetFile);
364          }
365       }
366
367       return file;
368    }
369
370    public Source JavaDoc resolve(String JavaDoc href, String JavaDoc base)
371    {
372       StreamSource JavaDoc source = new StreamSource JavaDoc(getInputStream(href));
373       // this works with saxon7/saxon6.5.2/xalan
374
source.setSystemId(href);
375       return source;
376    }
377
378    public void setFile(String JavaDoc file)
379    {
380       if (file != null)
381       {
382          Logger log = getLogger();
383
384          File JavaDoc target = new File JavaDoc(file);
385          if (!target.exists())
386          {
387             log.warn("Target file " + file + " does not exist, defaulting to previous");
388             return;
389          }
390          if (target.isDirectory())
391          {
392             useJar = false;
393             if (log.isEnabledFor(Logger.DEBUG)) log.debug("Using " + file + " as the root dir");
394             this.root = target;
395             return;
396          }
397          if (target.isFile() && (target.getName().endsWith(".jar") ||
398                                  (target.getName().endsWith(".zip"))))
399          {
400             try
401             {
402                URL JavaDoc url = target.toURL();
403                targetClassLoader = new URLClassLoader JavaDoc(new URL JavaDoc[]{url});
404                if (log.isEnabledFor(Logger.DEBUG)) log.debug("Using compressed file " + url + " as the root file");
405                this.root = target;
406                useJar = true;
407             }
408             catch (MalformedURLException JavaDoc e)
409             {
410                log.warn("Unable to create class loader", e);
411             }
412          }
413          else
414          {
415             log.warn("Target file " + file + " does not exist, defaulting to previous");
416          }
417       }
418    }
419
420    public String JavaDoc getFile()
421    {
422       return (root != null) ? root.getName() : null;
423    }
424
425    public String JavaDoc getPathInJar()
426    {
427       return path;
428    }
429
430    public void setPathInJar(String JavaDoc path)
431    {
432       this.path = path;
433    }
434
435    public String JavaDoc getDefaultPage()
436    {
437       return defaultPage;
438    }
439
440    public void setDefaultPage(String JavaDoc defaultPage)
441    {
442       this.defaultPage = defaultPage;
443    }
444
445    public boolean isUseJar()
446    {
447       return useJar;
448    }
449
450    public boolean isUsePath()
451    {
452       return !useJar;
453    }
454
455    public void addMimeType(String JavaDoc extension, String JavaDoc type)
456    {
457       if (extension != null && type != null)
458       {
459          Logger log = getLogger();
460          if (log.isEnabledFor(Logger.DEBUG)) log.debug("Added MIME type " + type + " for extension " + extension);
461          mimeTypes.put(extension, type);
462       }
463    }
464
465    public void setUseCache(boolean useCache)
466    {
467       this.useCache = useCache;
468    }
469
470    public boolean isUseCache()
471    {
472       return useCache;
473    }
474
475    public String JavaDoc getName()
476    {
477       return "XSLT Processor";
478    }
479
480    public Locale JavaDoc getLocale()
481    {
482       return locale;
483    }
484
485    public void setLocale(Locale JavaDoc locale)
486    {
487       this.locale = locale;
488    }
489
490    public void setLocaleString(String JavaDoc locale)
491    {
492       if (locale == null || locale.length() == 0)
493       {
494          this.locale = new Locale JavaDoc("en", "");
495       }
496       else
497       {
498          // split locale based on underbar
499
StringTokenizer JavaDoc tknzr = new StringTokenizer JavaDoc(locale, "_");
500          String JavaDoc language = tknzr.nextToken();
501          String JavaDoc country = "";
502          String JavaDoc variant = "";
503          if (tknzr.hasMoreTokens())
504             country = tknzr.nextToken();
505          if (tknzr.hasMoreTokens())
506             variant = tknzr.nextToken();
507          this.locale = new Locale JavaDoc(language, country, variant);
508       }
509    }
510 }
511
Popular Tags