1 28 29 package com.caucho.filters; 30 31 import com.caucho.loader.DynamicClassLoader; 32 import com.caucho.log.Log; 33 import com.caucho.server.connection.CauchoRequest; 34 import com.caucho.server.connection.RequestAdapter; 35 import com.caucho.util.CompileException; 36 import com.caucho.util.L10N; 37 import com.caucho.vfs.MergePath; 38 import com.caucho.vfs.Path; 39 import com.caucho.vfs.ReadStream; 40 import com.caucho.vfs.TempStream; 41 import com.caucho.vfs.Vfs; 42 import com.caucho.vfs.WriteStream; 43 import com.caucho.xml.Xml; 44 import com.caucho.xml.XmlUtil; 45 import com.caucho.xpath.XPath; 46 import com.caucho.xpath.XPathException; 47 import com.caucho.xsl.AbstractStylesheetFactory; 48 import com.caucho.xsl.CauchoStylesheet; 49 import com.caucho.xsl.StyleScript; 50 import com.caucho.xsl.TransformerImpl; 51 52 import org.w3c.dom.Document ; 53 import org.w3c.dom.ProcessingInstruction ; 54 55 import javax.servlet.*; 56 import javax.servlet.http.HttpServletRequest ; 57 import javax.servlet.http.HttpServletResponse ; 58 import javax.xml.transform.OutputKeys ; 59 import javax.xml.transform.Result ; 60 import javax.xml.transform.Source ; 61 import javax.xml.transform.Templates ; 62 import javax.xml.transform.Transformer ; 63 import javax.xml.transform.TransformerFactory ; 64 import javax.xml.transform.dom.DOMSource ; 65 import javax.xml.transform.stream.StreamResult ; 66 import javax.xml.transform.stream.StreamSource ; 67 import java.io.IOException ; 68 import java.io.OutputStream ; 69 import java.net.URL ; 70 import java.util.ArrayList ; 71 import java.util.logging.Level ; 72 import java.util.logging.Logger ; 73 74 79 public class XsltFilter implements Filter { 80 private static final L10N L = new L10N(XsltFilter.class); 81 private static final Logger log = Log.open(XsltFilter.class); 82 83 private String _mimeType = "x-application/xslt"; 84 private MergePath _stylePath; 85 private ServletContext _application; 86 private boolean _isConditional = true; 87 88 public void setMimeType(String mimeType) 89 { 90 _mimeType = mimeType; 91 } 92 93 public void setUnconditional(boolean isUnconditional) 94 { 95 _isConditional = ! isUnconditional; 96 } 97 98 public void init(FilterConfig config) 99 throws ServletException 100 { 101 _stylePath = new MergePath(); 102 _stylePath.addMergePath(Vfs.lookup()); 103 DynamicClassLoader loader; 104 loader = (DynamicClassLoader) Thread.currentThread().getContextClassLoader(); 105 String resourcePath = loader.getResourcePathSpecificFirst(); 106 _stylePath.addClassPath(resourcePath); 107 108 _application = config.getServletContext(); 109 110 if ("true".equals(config.getInitParameter("unconditional"))) 111 _isConditional = false; 112 } 113 114 117 public void doFilter(ServletRequest request, ServletResponse response, 118 FilterChain nextFilter) 119 throws ServletException, IOException 120 { 121 HttpServletRequest req = (HttpServletRequest ) request; 122 HttpServletResponse res = (HttpServletResponse ) response; 123 124 XsltResponse xsltResponse = new XsltResponse(req, res); 125 126 nextFilter.doFilter(req, xsltResponse); 127 xsltResponse.finish(req, res); 128 } 129 130 133 public void destroy() 134 { 135 } 136 137 class XsltResponse extends CauchoResponseWrapper { 138 private HttpServletRequest _request; 139 private XsltTempStream _xsltStream; 140 private String _chainingType; 141 142 XsltResponse(HttpServletRequest request, HttpServletResponse response) 143 { 144 super(response); 145 146 _request = request; 147 } 148 149 153 public void setContentLength(int length) 154 { 155 } 156 157 160 public void setContentType(String contentType) 161 { 162 super.setContentType(contentType); 163 164 int p = contentType.indexOf(';'); 165 166 if (p > 0) 167 contentType = contentType.substring(0, p); 168 169 if (! _isConditional || 170 contentType.equals("x-application/xslt") || 171 contentType.equals("x-application/xsl") || 172 contentType.equals("x-application/stylescript")) { 173 _chainingType = contentType; 174 175 if (log.isLoggable(Level.FINER)) 176 log.finer(L.l("'{0}' chaining xslt with {1}", 177 _request.getRequestURI(), contentType)); 178 179 if (_xsltStream == null) 180 _xsltStream = new XsltTempStream(_response); 181 182 _xsltStream.setChaining(); 183 } 184 } 185 186 189 protected OutputStream getStream() throws IOException 190 { 191 if (_xsltStream == null) 192 _xsltStream = new XsltTempStream(_response); 193 194 return _xsltStream; 195 } 196 197 200 public void flushBuffer() 201 throws IOException 202 { 203 super.flushBuffer(); 204 205 if (_stream != null) 206 _stream.flush(); 207 } 208 209 212 public void finish(HttpServletRequest req, 213 HttpServletResponse res) 214 throws IOException , ServletException 215 { 216 try { 217 flushBuffer(); 218 219 if (_chainingType == null) 220 return; 221 222 TempStream ts = _xsltStream.getTempStream(); 223 224 Document doc = null; 225 226 ReadStream is = ts.openRead(true); 227 Path userPath = Vfs.lookup(); 228 if (req instanceof CauchoRequest) 229 userPath.setUserPath(((CauchoRequest) req).getPageURI()); 230 else 231 userPath.setUserPath(req.getRequestURI()); 232 is.setPath(userPath); 233 234 try { 235 doc = new Xml().parseDocument(is); 236 } finally { 237 is.close(); 238 } 239 240 String href = (String ) req.getAttribute("caucho.xsl.stylesheet"); 241 242 if (href == null) 243 href = getStylesheetHref(doc); 244 245 if (href == null) 246 href = "default.xsl"; 247 248 Templates stylesheet = null; 249 250 try { 252 254 TransformerFactory factory; 255 256 if (_chainingType.equals("x-application/stylescript")) 257 factory = new StyleScript(); 258 else { 259 factory = TransformerFactory.newInstance(); 260 } 261 262 if (factory instanceof AbstractStylesheetFactory) 263 ((AbstractStylesheetFactory) factory).setStylePath(_stylePath); 264 265 Path path = null; 266 267 if (href.startsWith("/")) 268 path = Vfs.getPwd().lookup(_application.getRealPath(href)); 269 else { 270 String servletPath = RequestAdapter.getPageServletPath(req); 271 272 Path pwd = Vfs.getPwd(); 273 pwd = pwd.lookup(_application.getRealPath(servletPath)); 274 path = pwd.getParent().lookup(href); 275 } 276 277 if (! path.canRead()) { 278 Thread thread = Thread.currentThread(); 279 ClassLoader loader = thread.getContextClassLoader(); 280 281 URL url = loader.getResource(href); 282 283 if (url != null) { 284 Path newPath = Vfs.getPwd().lookup(url.toString()); 285 if (newPath.canRead()) 286 path = newPath; 287 } 288 } 289 290 Source source; 291 if (path.canRead()) 292 source = new StreamSource (path.getURL()); 293 else 294 source = new StreamSource (href); 295 296 if (log.isLoggable(Level.FINE)) 297 log.fine(L.l("'{0}' XSLT filter using stylesheet {1}", 298 req.getRequestURI(), source.getSystemId())); 299 300 stylesheet = factory.newTemplates(source); 301 } finally { 302 } 304 305 Transformer transformer = null; 306 307 transformer = (Transformer ) stylesheet.newTransformer(); 308 309 TransformerImpl cauchoTransformer = null; 310 if (transformer instanceof TransformerImpl) 311 cauchoTransformer = (TransformerImpl) transformer; 312 313 String mediaType = (String ) transformer.getOutputProperty(OutputKeys.MEDIA_TYPE); 314 String encoding = (String ) transformer.getOutputProperty(OutputKeys.ENCODING); 315 String method = (String ) transformer.getOutputProperty(OutputKeys.METHOD); 316 317 if (encoding != null) { 318 } 319 else if (method == null) { 320 } 321 else if (method.equals("xml")) 322 encoding = "UTF-8"; 323 324 if (encoding != null) { 325 if (mediaType == null) 326 mediaType = "text/html"; 327 res.setContentType(mediaType + "; charset=" + encoding); 328 } 329 else if (mediaType != null) 330 res.setContentType(mediaType); 331 else 332 res.setContentType("text/html"); 333 334 if (encoding == null) 335 encoding = "ISO-8859-1"; 336 transformer.setOutputProperty(OutputKeys.ENCODING, encoding); 337 338 ArrayList params = null;; 339 if (cauchoTransformer != null) { 340 params = (ArrayList ) cauchoTransformer.getProperty(CauchoStylesheet.GLOBAL_PARAM); 341 } 342 343 for (int i = 0; params != null && i < params.size(); i++) { 344 String param = (String ) params.get(i); 345 346 transformer.setParameter(param, req.getParameter(param)); 347 } 348 349 DOMSource domSource = new DOMSource (doc); 350 domSource.setSystemId(userPath.getUserPath()); 351 352 Result result = getResult(res.getOutputStream()); 353 354 transformer.transform(domSource, result); 355 } catch (IOException e) { 356 throw e; 357 } catch (Exception e) { 358 if (e instanceof CompileException) 359 throw new ServletException(e.getMessage(), e); 360 else 361 throw new ServletException(e.toString(), e); 362 } 363 } 364 365 368 protected Result getResult(OutputStream out) 369 { 370 return new StreamResult (out); 371 } 372 373 384 private String getStylesheetHref(Document doc) 385 throws XPathException 386 { 387 ProcessingInstruction pi = null; 388 389 pi = (ProcessingInstruction ) XPath.find("//processing-instruction('xml-stylesheet')", doc); 390 391 if (pi == null) 392 return null; 393 394 String value = pi.getNodeValue(); 395 396 return XmlUtil.getPIAttribute(value, "href"); 397 } 398 } 399 400 static class XsltTempStream extends OutputStream { 401 private ServletResponse _response; 402 private OutputStream _os; 403 404 private TempStream _tempStream; 405 406 XsltTempStream(ServletResponse response) 407 { 408 _response = response; 409 } 410 411 void setChaining() 412 { 413 if (_os != null) 414 throw new IllegalStateException (L.l("setContentType for XSLT chaining must be before any data.")); 415 416 _tempStream = new TempStream(null); 417 _tempStream.openWrite(); 418 419 _os = new WriteStream(_tempStream); 420 } 421 422 TempStream getTempStream() 423 throws IOException 424 { 425 if (_tempStream != null) { 426 _os.close(); 427 _os = null; 428 } 429 430 return _tempStream; 431 } 432 433 438 public void write(int ch) 439 throws IOException 440 { 441 if (_os == null) 442 _os = _response.getOutputStream(); 443 444 _os.write(ch); 445 } 446 447 454 public void write(byte []buffer, int offset, int length) 455 throws IOException 456 { 457 if (_os == null) 458 _os = _response.getOutputStream(); 459 460 _os.write(buffer, offset, length); 461 } 462 463 public void flush() 464 throws IOException 465 { 466 if (_os == null) 467 _os = _response.getOutputStream(); 468 469 _os.flush(); 470 } 471 } 472 } 473 | Popular Tags |