1 5 package org.infohazard.maverick.transform; 6 7 import java.io.File ; 8 import java.io.IOException ; 9 import java.net.MalformedURLException ; 10 import java.util.Iterator ; 11 import java.util.Map ; 12 13 import javax.servlet.ServletContext ; 14 import javax.servlet.ServletException ; 15 import javax.xml.transform.Result ; 16 import javax.xml.transform.Source ; 17 import javax.xml.transform.Templates ; 18 import javax.xml.transform.Transformer ; 19 import javax.xml.transform.TransformerConfigurationException ; 20 import javax.xml.transform.TransformerException ; 21 import javax.xml.transform.TransformerFactory ; 22 import javax.xml.transform.URIResolver ; 23 import javax.xml.transform.sax.SAXResult ; 24 import javax.xml.transform.sax.SAXTransformerFactory ; 25 import javax.xml.transform.sax.TransformerHandler ; 26 import javax.xml.transform.stream.StreamResult ; 27 import javax.xml.transform.stream.StreamSource ; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 import org.infohazard.maverick.flow.ConfigException; 32 import org.infohazard.maverick.flow.Transform; 33 import org.infohazard.maverick.flow.TransformContext; 34 import org.infohazard.maverick.flow.TransformStep; 35 import org.xml.sax.ContentHandler ; 36 37 44 class XSLTransform implements Transform 45 { 46 47 public static final int CACHE_PRELOAD = 1; 48 49 public static final int CACHE_LAZY = 2; 50 51 public static final int CACHE_DISABLED = 3; 52 53 54 private static Log log = LogFactory.getLog(XSLTransform.class); 55 56 57 protected final static String UNFINISHED_CONTENTTYPE = "text/xml"; 58 59 60 protected String path; 61 62 63 protected boolean isMonitoredFile = false; 64 65 66 protected File monitoredFile = null; 67 68 69 protected long monitoredFileLastModified; 70 71 72 protected Templates compiled; 73 74 75 protected String finalContentType; 76 77 78 protected URIResolver uriResolver; 79 80 81 protected int cachingStyle; 82 83 94 public XSLTransform(String path, 95 boolean isMonitored, 96 int templateCachingStyle, 97 ServletContext webAppContext, 98 String finishedContentType, 99 URIResolver uriRes) throws ConfigException 100 { 101 log.debug("Creating xslt transform: " + path); 102 103 this.path = path; 104 this.isMonitoredFile = isMonitored; 105 this.finalContentType = finishedContentType; 106 this.uriResolver = uriRes; 107 this.cachingStyle = templateCachingStyle; 108 109 if (cachingStyle == CACHE_PRELOAD) 110 this.compiled = loadTemplate(this.path, webAppContext); 111 } 112 113 116 public TransformStep createStep(TransformContext tctx) throws ServletException 117 { 118 return new Step(tctx); 119 } 120 121 126 protected Templates loadTemplate(String path, ServletContext servletCtx) throws ConfigException 127 { 128 129 boolean pathIsFileUrl = false; 130 boolean pathIsOtherUrl = false; 131 java.net.URL resURL = null; 132 133 if (this.isMonitoredFile && this.monitoredFile != null) 134 { 135 try 137 { 138 resURL = this.monitoredFile.toURL(); 139 this.monitoredFileLastModified = this.monitoredFile.lastModified(); 140 } 141 catch (MalformedURLException me) 142 { 143 log.fatal("Eror parsing monitored template URL " + path + ": " + me.toString()); 144 throw new ConfigException(me); 145 } 146 catch (SecurityException se) 147 { 148 log.fatal("Unable to access monitored template " + path + ": " + se.toString()); 149 throw new ConfigException(se); 150 } 151 } 152 else 153 { 154 if (path.toLowerCase().startsWith("file:")) 157 pathIsFileUrl = true; 158 else if (path.toLowerCase().startsWith("http:") || 159 path.toLowerCase().startsWith("https:") || 160 path.toLowerCase().startsWith("ftp:")) 161 pathIsOtherUrl = true; 162 else if (!path.startsWith("/")) 163 path = "/" + path; 164 165 try 166 { 167 if (pathIsFileUrl && this.isMonitoredFile) 168 { 169 resURL = new java.net.URL (path); 170 this.monitoredFile = new File (resURL.getFile()); 171 172 if (this.monitoredFile == null || !this.monitoredFile.canRead()) 173 { 174 this.monitoredFile = null; 175 log.fatal("Resource not found or unable to read file: " + path); 176 throw new ConfigException("Resource not found or unable to read file: " + path); 177 } 178 179 this.monitoredFileLastModified = this.monitoredFile.lastModified(); 180 } 181 else if (pathIsFileUrl || pathIsOtherUrl) 182 resURL = new java.net.URL (path); 183 else 184 resURL = servletCtx.getResource(path); 185 186 if (resURL == null) 187 { 188 log.fatal("Resource not found: " + path); 189 throw new ConfigException("Resource not found: " + path); 190 } 191 } 192 catch (MalformedURLException me) 193 { 194 log.fatal("Eror parsing template URL " + path + ": " + me.toString()); 195 throw new ConfigException(me); 196 } 197 } 198 199 try 200 { 201 TransformerFactory tFactory = TransformerFactory.newInstance(); 202 if (this.uriResolver != null) 203 tFactory.setURIResolver(this.uriResolver); 204 205 return tFactory.newTemplates(new StreamSource (resURL.openStream(), resURL.toString())); 206 } 207 catch (TransformerException ex) 208 { 209 log.fatal("Error loading template " + path + ": " + ex.toString()); 210 throw new ConfigException(ex); 211 } 212 catch (IOException ex) 213 { 214 log.fatal("Eror loading template " + path + ": " + ex.toString()); 215 throw new ConfigException(ex); 216 } 217 218 } 219 220 226 protected void populateParams(Transformer t, Map params) 227 { 228 Iterator entriesIt = params.entrySet().iterator(); 229 while (entriesIt.hasNext()) 230 { 231 Map.Entry entry = (Map.Entry )entriesIt.next(); 232 t.setParameter((String )entry.getKey(), entry.getValue()); 233 } 234 } 235 236 239 protected class Step extends XMLTransformStep 240 { 241 242 protected boolean handlerUsed = false; 243 244 245 public Step(TransformContext tctx) throws ServletException 246 { 247 super(tctx); 248 } 249 250 253 protected void assignContentType(TransformContext tctx) throws ServletException 254 { 255 if (this.getNext().isLast() && !tctx.halting()) 256 this.getNext().setContentType(finalContentType); 257 else 258 this.getNext().setContentType(UNFINISHED_CONTENTTYPE); 259 } 260 261 265 public void done() throws IOException , ServletException 266 { 267 log.debug("Done being written to"); 268 269 if (this.fakeResponse == null) 270 { 271 if (this.handlerUsed) 272 this.getNext().done(); 273 else 274 throw new IllegalStateException ("done() called illegally"); 275 } 276 else 277 { 278 this.go(this.fakeResponse.getOutputAsReader()); 279 this.fakeResponse = null; 280 } 281 } 282 283 284 public ContentHandler getSAXHandler() throws IOException , ServletException 285 { 286 this.handlerUsed = true; 287 288 assignContentType(this.getTransformCtx()); 290 291 TransformerHandler tHandler; 292 try 293 { 294 SAXTransformerFactory saxTFact = (SAXTransformerFactory )TransformerFactory.newInstance(); 295 tHandler = saxTFact.newTransformerHandler(this.getCompiled()); 296 } 297 catch (TransformerConfigurationException ex) 298 { 299 throw new ServletException (ex); 300 } 301 302 if (this.getTransformCtx().getTransformParams() != null) 304 populateParams(tHandler.getTransformer(), this.getTransformCtx().getTransformParams()); 305 306 if (this.getNext().isLast()) 307 tHandler.setResult(new StreamResult (this.getNext().getResponse().getOutputStream())); 308 else 309 tHandler.setResult(new SAXResult (this.getNext().getSAXHandler())); 310 311 return tHandler; 312 } 313 314 315 public void go(Source input) throws IOException , ServletException 316 { 317 assignContentType(this.getTransformCtx()); 319 320 Transformer trans; 321 try 322 { 323 trans = this.getCompiled().newTransformer(); 324 } 325 catch (TransformerConfigurationException ex) 326 { 327 throw new ServletException (ex); 328 } 329 330 if (this.getTransformCtx().getTransformParams() != null) 332 populateParams(trans, this.getTransformCtx().getTransformParams()); 333 334 Result res; 335 if (this.getNext().isLast()) 336 res = new StreamResult (this.getNext().getResponse().getOutputStream()); 337 else 338 res = new SAXResult (this.getNext().getSAXHandler()); 339 340 try 341 { 342 trans.transform(input, res); 343 } 344 catch (TransformerException ex) 345 { 346 throw new ServletException (ex); 347 } 348 349 this.getNext().done(); 350 } 351 352 356 public Templates getCompiled() throws ConfigException 357 { 358 359 try 360 { 361 if (isMonitoredFile && monitoredFile != null) 362 { 363 long lastModified = monitoredFile.lastModified(); 364 365 if (lastModified <= 0L) 366 { 367 log.error("Unable to access monitored template " + path); 368 369 if (compiled != null) 370 return compiled; 371 else 372 throw new IllegalStateException ("Unable to access monitored template " + path); 373 } 374 else if (monitoredFileLastModified < lastModified) 375 { 376 compiled = loadTemplate(path, this.getTransformCtx().getServletContext()); 377 return compiled; 378 } 379 } 380 381 switch (cachingStyle) 382 { 383 case CACHE_PRELOAD: 384 { 385 return compiled; 386 } 387 case CACHE_LAZY: 388 { 389 if (compiled == null) 390 compiled = loadTemplate(path, this.getTransformCtx().getServletContext()); 391 392 return compiled; 393 } 394 case CACHE_DISABLED: 395 { 396 return loadTemplate(path, this.getTransformCtx().getServletContext()); 397 } 398 default: 399 { 400 throw new IllegalStateException ("Unknown caching style"); 401 } 402 } 403 404 } 405 catch (SecurityException se) 406 { 407 log.error("Unable to access monitored template " + path, se); 408 409 if (compiled != null) 410 return compiled; 411 else 412 throw new ConfigException(se); 413 } 414 415 } 416 } 417 418 } 419 420 | Popular Tags |