1 8 9 package mx4j.tools.adaptor.http; 10 11 import java.io.BufferedInputStream ; 12 import java.io.BufferedOutputStream ; 13 import java.io.ByteArrayOutputStream ; 14 import java.io.File ; 15 import java.io.FileInputStream ; 16 import java.io.FileNotFoundException ; 17 import java.io.IOException ; 18 import java.io.InputStream ; 19 import java.net.MalformedURLException ; 20 import java.net.URL ; 21 import java.net.URLClassLoader ; 22 import java.util.HashMap ; 23 import java.util.Iterator ; 24 import java.util.Locale ; 25 import java.util.Map ; 26 import java.util.StringTokenizer ; 27 import javax.management.MBeanException ; 28 import javax.management.ReflectionException ; 29 import javax.management.RuntimeMBeanException ; 30 import javax.xml.transform.Source ; 31 import javax.xml.transform.Templates ; 32 import javax.xml.transform.Transformer ; 33 import javax.xml.transform.TransformerConfigurationException ; 34 import javax.xml.transform.TransformerException ; 35 import javax.xml.transform.TransformerFactory ; 36 import javax.xml.transform.URIResolver ; 37 import javax.xml.transform.dom.DOMSource ; 38 import javax.xml.transform.stream.StreamResult ; 39 import javax.xml.transform.stream.StreamSource ; 40 41 import mx4j.log.Log; 42 import mx4j.log.Logger; 43 import org.w3c.dom.Document ; 44 45 50 public class XSLTProcessor implements ProcessorMBean, XSLTProcessorMBean, URIResolver 51 { 52 private String path = "mx4j/tools/adaptor/http/xsl"; 53 private String defaultPage = "serverbydomain"; 54 private TransformerFactory factory; 55 private Map templatesCache = new HashMap (); 56 private File root; 57 private Map mimeTypes = new HashMap (); 58 61 private boolean useJar = true; 62 private volatile boolean useCache = true; 63 private ClassLoader targetClassLoader = ClassLoader.getSystemClassLoader(); 64 68 private Locale locale = new Locale ("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 document) throws IOException 96 { 97 Logger log = getLogger(); 98 99 out.setCode(HttpConstants.STATUS_OKAY); 100 out.setHeader("Content-Type", "text/html"); 101 out.setHeader("Cache-Control", "no-cache"); 103 out.setHeader("expires", "now"); 104 out.setHeader("pragma", "no-cache"); 105 out.sendHeaders(); 106 Transformer transformer = null; 107 String 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 transformer.setURIResolver(this); 122 Map variables = in.getVariables(); 124 Iterator j = variables.keySet().iterator(); 125 while (j.hasNext()) 126 { 127 String key = (String )j.next(); 128 Object value = variables.get(key); 129 if (value instanceof String ) 130 { 131 transformer.setParameter("request." + key, value); 132 } 133 if (value instanceof String []) 134 { 135 String [] allvalues = (String [])value; 136 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 output = new ByteArrayOutputStream (); 148 if (log.isEnabledFor(Logger.TRACE)) log.trace("transforming " + path); 149 transformer.transform(new DOMSource (document), new StreamResult (output)); 150 output.writeTo(out); 151 } 152 catch (TransformerException 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 createTransformer(String path) 164 { 165 Logger logger = getLogger(); 166 try 167 { 168 synchronized (this) 169 { 170 if (useCache && templatesCache.containsKey(path)) 171 { 172 return ((Templates )templatesCache.get(path)).newTransformer(); 173 } 174 else 175 { 176 InputStream stream = getInputStream(path); 177 if (stream != null) 178 { 179 if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Creating template for path " + path); 180 Templates template = factory.newTemplates(new StreamSource (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 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 199 { 200 out.setCode(e.getCode()); 201 out.setHeader("Content-Type", "text/html"); 202 out.sendHeaders(); 203 Transformer transformer = createTransformer("error.xsl"); 205 transformer.setURIResolver(this); 206 Document 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 output = new ByteArrayOutputStream (); 216 transformer.transform(new DOMSource (doc), new StreamResult (output)); 217 output.writeTo(out); 218 } 219 catch (TransformerException 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 e) throws IOException 228 { 229 Logger log = getLogger(); 230 Exception t = e; 231 if (e instanceof RuntimeMBeanException ) 232 { 233 t = ((RuntimeMBeanException )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 ) && (((MBeanException )t).getTargetException() instanceof HttpException)) 241 { 242 processHttpException(in, out, (HttpException)((MBeanException )t).getTargetException()); 243 } 244 else if ((t instanceof ReflectionException ) && (((ReflectionException )t).getTargetException() instanceof HttpException)) 245 { 246 processHttpException(in, out, (HttpException)((ReflectionException )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 preProcess(String path) 257 { 258 if (path.equals("/")) 259 { 260 path = "/" + defaultPage; 261 } 262 return path; 263 } 264 265 public String notFoundElement(String path, HttpOutputStream out, HttpInputStream in) throws IOException , HttpException 266 { 267 Logger log = getLogger(); 268 269 File file = new File (this.path, path); 270 if (log.isEnabledFor(Logger.DEBUG)) log.debug("Processing file request " + file); 271 String name = file.getName(); 272 int extensionIndex = name.lastIndexOf('.'); 273 String 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 extension = name.substring(extensionIndex, name.length()); 282 if (mimeTypes.containsKey(extension)) 283 { 284 mime = (String )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 fileIn = new BufferedInputStream (getInputStream(path)); 296 ByteArrayOutputStream outArray = new ByteArrayOutputStream (); 297 BufferedOutputStream outBuffer = new BufferedOutputStream (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 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 getInputStream(String path) 320 { 321 InputStream file = null; 322 if (!useJar) 323 { 324 try 325 { 326 file = new FileInputStream (new File (this.root, path)); 328 } 329 catch (FileNotFoundException e) 330 { 331 Logger log = getLogger(); 332 log.error("File not found", e); 333 } 334 } 335 else 336 { 337 String targetFile = this.path; 339 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 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 resolve(String href, String base) 371 { 372 StreamSource source = new StreamSource (getInputStream(href)); 373 source.setSystemId(href); 375 return source; 376 } 377 378 public void setFile(String file) 379 { 380 if (file != null) 381 { 382 Logger log = getLogger(); 383 384 File target = new File (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 url = target.toURL(); 403 targetClassLoader = new URLClassLoader (new URL []{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 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 getFile() 421 { 422 return (root != null) ? root.getName() : null; 423 } 424 425 public String getPathInJar() 426 { 427 return path; 428 } 429 430 public void setPathInJar(String path) 431 { 432 this.path = path; 433 } 434 435 public String getDefaultPage() 436 { 437 return defaultPage; 438 } 439 440 public void setDefaultPage(String 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 extension, String 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 getName() 476 { 477 return "XSLT Processor"; 478 } 479 480 public Locale getLocale() 481 { 482 return locale; 483 } 484 485 public void setLocale(Locale locale) 486 { 487 this.locale = locale; 488 } 489 490 public void setLocaleString(String locale) 491 { 492 if (locale == null || locale.length() == 0) 493 { 494 this.locale = new Locale ("en", ""); 495 } 496 else 497 { 498 StringTokenizer tknzr = new StringTokenizer (locale, "_"); 500 String language = tknzr.nextToken(); 501 String country = ""; 502 String variant = ""; 503 if (tknzr.hasMoreTokens()) 504 country = tknzr.nextToken(); 505 if (tknzr.hasMoreTokens()) 506 variant = tknzr.nextToken(); 507 this.locale = new Locale (language, country, variant); 508 } 509 } 510 } 511 | Popular Tags |