1 16 17 package org.apache.cocoon.transformation; 18 19 import java.io.IOException ; 20 import java.io.Serializable ; 21 import java.lang.reflect.Method ; 22 import java.util.Enumeration ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.Map ; 26 import java.util.Set ; 27 import java.util.Map.Entry; 28 29 import javax.xml.transform.sax.SAXResult ; 30 import javax.xml.transform.sax.TransformerHandler ; 31 32 import org.apache.avalon.framework.activity.Disposable; 33 import org.apache.avalon.framework.configuration.Configurable; 34 import org.apache.avalon.framework.configuration.Configuration; 35 import org.apache.avalon.framework.configuration.ConfigurationException; 36 import org.apache.avalon.framework.logger.LogEnabled; 37 import org.apache.avalon.framework.parameters.Parameters; 38 import org.apache.avalon.framework.service.ServiceException; 39 import org.apache.avalon.framework.service.ServiceManager; 40 import org.apache.avalon.framework.service.Serviceable; 41 import org.apache.cocoon.ProcessingException; 42 import org.apache.cocoon.caching.CacheableProcessingComponent; 43 import org.apache.cocoon.components.source.SourceUtil; 44 import org.apache.cocoon.components.xslt.TraxErrorListener; 45 import org.apache.cocoon.environment.Cookie; 46 import org.apache.cocoon.environment.ObjectModelHelper; 47 import org.apache.cocoon.environment.Request; 48 import org.apache.cocoon.environment.Session; 49 import org.apache.cocoon.environment.SourceResolver; 50 import org.apache.cocoon.xml.XMLConsumer; 51 import org.apache.commons.lang.BooleanUtils; 52 import org.apache.commons.lang.exception.NestableRuntimeException; 53 import org.apache.excalibur.source.Source; 54 import org.apache.excalibur.source.SourceException; 55 import org.apache.excalibur.source.SourceValidity; 56 import org.apache.excalibur.xml.xslt.XSLTProcessor; 57 import org.apache.excalibur.xml.xslt.XSLTProcessorException; 58 import org.xml.sax.SAXException ; 59 60 149 public class TraxTransformer extends AbstractTransformer 150 implements Serviceable, Configurable, CacheableProcessingComponent, Disposable { 151 152 153 protected ServiceManager manager; 154 155 156 protected Map objectModel; 157 158 159 protected Map logicSheetParameters; 160 161 162 private boolean useParameters = false; 163 private boolean _useParameters = false; 164 165 166 private boolean useCookies = false; 167 private boolean _useCookies = false; 168 169 170 private boolean useSessionInfo = false; 171 private boolean _useSessionInfo = false; 172 173 174 private boolean checkIncludes = true; 175 176 177 protected TransformerHandler transformerHandler; 178 179 180 protected SourceValidity transformerValidity; 181 182 183 private Source inputSource; 184 185 private Parameters par; 186 187 private SourceResolver resolver; 188 189 190 private String defaultSrc; 191 192 193 private XSLTProcessor xsltProcessor; 194 195 196 private boolean finishedDocument = false; 197 198 199 private Method xalanDtmManagerGetIncrementalMethod; 200 201 202 private SAXException exceptionDuringSetConsumer; 203 204 205 private TraxErrorListener errorListener; 206 207 210 public void configure(Configuration conf) 211 throws ConfigurationException { 212 Configuration child; 213 214 child = conf.getChild("use-request-parameters"); 215 this.useParameters = child.getValueAsBoolean(false); 216 this._useParameters = this.useParameters; 217 218 child = conf.getChild("use-cookies"); 219 this.useCookies = child.getValueAsBoolean(false); 220 this._useCookies = this.useCookies; 221 222 child = conf.getChild("use-session-info"); 223 this.useSessionInfo = child.getValueAsBoolean(false); 224 this._useSessionInfo = this.useSessionInfo; 225 226 child = conf.getChild("transformer-factory"); 227 final String traxFactory = child.getValue(null); 229 230 child = conf.getChild("xslt-processor-role"); 231 String xsltProcessorRole = child.getValue(XSLTProcessor.ROLE); 232 if (!xsltProcessorRole.startsWith(XSLTProcessor.ROLE)) { 233 xsltProcessorRole = XSLTProcessor.ROLE + '/' + xsltProcessorRole; 234 } 235 236 child = conf.getChild("check-includes"); 237 this.checkIncludes = child.getValueAsBoolean(this.checkIncludes); 238 239 child = conf.getChild("default-src",false); 240 if(child!=null) { 241 this.defaultSrc = child.getValue(); 242 } 243 244 if (getLogger().isDebugEnabled()) { 245 getLogger().debug("Use parameters is " + this.useParameters); 246 getLogger().debug("Use cookies is " + this.useCookies); 247 getLogger().debug("Use session info is " + this.useSessionInfo); 248 getLogger().debug("Use TrAX Processor " + xsltProcessorRole); 249 getLogger().debug("Check for included stylesheets is " + this.checkIncludes); 250 if (traxFactory != null) { 251 getLogger().debug("Use TrAX Transformer Factory " + traxFactory); 252 } else { 253 getLogger().debug("Use default TrAX Transformer Factory."); 254 } 255 getLogger().debug("Default source = " + this.defaultSrc); 256 } 257 258 try { 259 this.xsltProcessor = (XSLTProcessor) this.manager.lookup(xsltProcessorRole); 260 if (traxFactory != null) { 261 this.xsltProcessor.setTransformerFactory(traxFactory); 262 } 263 } catch (ServiceException e) { 264 throw new ConfigurationException("Cannot load XSLT processor", e); 265 } 266 267 try { 268 Class dtmManagerClass = Class.forName("org.apache.xml.dtm.DTMManager"); 270 xalanDtmManagerGetIncrementalMethod = dtmManagerClass.getMethod("getIncremental", null); 271 } catch (ClassNotFoundException e) { 272 } catch (NoSuchMethodException e) { 274 throw new ConfigurationException("Was not able to get getIncremental method from Xalan's DTMManager.", e); 275 } 276 } 277 278 282 public void service(ServiceManager manager) throws ServiceException { 283 this.manager = manager; 284 } 285 286 291 public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) 292 throws SAXException , ProcessingException, IOException { 293 294 if(src==null && defaultSrc!=null) { 295 if(getLogger().isDebugEnabled()) { 296 getLogger().debug("src is null, using default source " + defaultSrc); 297 } 298 src = defaultSrc; 299 } 300 301 if (src == null) { 302 throw new ProcessingException("Stylesheet URI can't be null"); 303 } 304 305 this.par = par; 306 this.objectModel = objectModel; 307 this.resolver = resolver; 308 try { 309 this.inputSource = resolver.resolveURI(src); 310 } catch (SourceException se) { 311 throw SourceUtil.handle("Unable to resolve " + src, se); 312 } 313 _useParameters = par.getParameterAsBoolean("use-request-parameters", this.useParameters); 314 _useCookies = par.getParameterAsBoolean("use-cookies", this.useCookies); 315 _useSessionInfo = par.getParameterAsBoolean("use-session-info", this.useSessionInfo); 316 final boolean _checkIncludes = par.getParameterAsBoolean("check-includes", this.checkIncludes); 317 318 if (getLogger().isDebugEnabled()) { 319 getLogger().debug("Using stylesheet: '" + this.inputSource.getURI() + "' in " + this); 320 getLogger().debug("Use parameters is " + this._useParameters); 321 getLogger().debug("Use cookies is " + this._useCookies); 322 getLogger().debug("Use session info is " + this._useSessionInfo); 323 getLogger().debug("Check for included stylesheets is " + _checkIncludes); 324 } 325 326 try { 329 if ( _checkIncludes ) { 330 XSLTProcessor.TransformerHandlerAndValidity handlerAndValidity = 331 this.xsltProcessor.getTransformerHandlerAndValidity(this.inputSource, null); 332 this.transformerHandler = handlerAndValidity.getTransfomerHandler(); 333 this.transformerValidity = handlerAndValidity.getTransfomerValidity(); 334 } else { 335 this.transformerValidity = this.inputSource.getValidity(); 336 } 337 } catch (XSLTProcessorException se) { 338 throw new ProcessingException("Unable to get transformer handler for " + this.inputSource.getURI(), se); 339 } 340 } 341 342 348 public Serializable getKey() { 349 Map map = getLogicSheetParameters(); 350 if (map == null) { 351 return this.inputSource.getURI(); 352 } 353 354 StringBuffer sb = new StringBuffer (); 355 sb.append(this.inputSource.getURI()); 356 Set entries = map.entrySet(); 357 for(Iterator i=entries.iterator(); i.hasNext();){ 358 sb.append(';'); 359 Map.Entry entry = (Map.Entry )i.next(); 360 sb.append(entry.getKey()); 361 sb.append('='); 362 sb.append(entry.getValue()); 363 } 364 return sb.toString(); 365 } 366 367 373 public SourceValidity getValidity() { 374 return this.transformerValidity; 381 } 382 383 386 public void setConsumer(XMLConsumer consumer) { 387 388 if ( this.transformerHandler == null ) { 389 try { 390 this.transformerHandler = this.xsltProcessor.getTransformerHandler(this.inputSource); 391 } catch (XSLTProcessorException se) { 392 this.exceptionDuringSetConsumer = 394 new SAXException ("Unable to get transformer handler for " + this.inputSource.getURI(), se); 395 return; 396 } 397 } 398 final Map map = getLogicSheetParameters(); 399 if (map != null) { 400 final javax.xml.transform.Transformer transformer = this.transformerHandler.getTransformer(); 401 final Iterator iterator = map.entrySet().iterator(); 402 while (iterator.hasNext()) { 403 final Map.Entry entry = (Entry) iterator.next(); 404 transformer.setParameter((String )entry.getKey(), entry.getValue()); 405 } 406 } 407 408 super.setContentHandler(this.transformerHandler); 409 super.setLexicalHandler(this.transformerHandler); 410 411 if (this.transformerHandler instanceof LogEnabled) { 412 ((LogEnabled)this.transformerHandler).enableLogging(getLogger()); 413 } 414 final SAXResult result = new SAXResult (consumer); 416 result.setLexicalHandler(consumer); 417 this.transformerHandler.setResult(result); 418 419 this.errorListener = new TraxErrorListener(getLogger(), this.inputSource.getURI()); 420 this.transformerHandler.getTransformer().setErrorListener(this.errorListener); 421 } 422 423 426 protected Map getLogicSheetParameters() { 427 if (this.logicSheetParameters != null) { 428 return this.logicSheetParameters; 429 } 430 HashMap map = null; 431 if (par != null) { 432 String [] params = par.getNames(); 433 if (params != null) { 434 for(int i = 0; i < params.length; i++) { 435 String name = params[i]; 436 if (isValidXSLTParameterName(name)) { 437 String value = par.getParameter(name,null); 438 if (value != null) { 439 if (map == null) { 440 map = new HashMap (params.length); 441 } 442 map.put(name,value); 443 } 444 } 445 } 446 } 447 } 448 449 if (this._useParameters) { 450 Request request = ObjectModelHelper.getRequest(objectModel); 451 452 Enumeration parameters = request.getParameterNames(); 453 if (parameters != null) { 454 while (parameters.hasMoreElements()) { 455 String name = (String ) parameters.nextElement(); 456 if (isValidXSLTParameterName(name)) { 457 String value = request.getParameter(name); 458 if (map == null) { 459 map = new HashMap (); 460 } 461 map.put(name,value); 462 } 463 } 464 } 465 } 466 467 if (this._useSessionInfo) { 468 final Request request = ObjectModelHelper.getRequest(objectModel); 469 if (map == null) { 470 map = new HashMap (6); 471 } 472 473 final Session session = request.getSession(false); 474 if (session != null) { 475 map.put("session-available", "true"); 476 map.put("session-is-new", BooleanUtils.toStringTrueFalse(session.isNew())); 477 map.put("session-id-from-cookie", BooleanUtils.toStringTrueFalse(request.isRequestedSessionIdFromCookie())); 478 map.put("session-id-from-url", BooleanUtils.toStringTrueFalse(request.isRequestedSessionIdFromURL())); 479 map.put("session-valid", BooleanUtils.toStringTrueFalse(request.isRequestedSessionIdValid())); 480 map.put("session-id", session.getId()); 481 } else { 482 map.put("session-available", "false"); 483 } 484 } 485 486 if (this._useCookies) { 487 Request request = ObjectModelHelper.getRequest(objectModel); 488 Cookie cookies[] = request.getCookies(); 489 if (cookies != null) { 490 for (int i = 0; i < cookies.length; i++) { 491 String name = cookies[i].getName(); 492 if (isValidXSLTParameterName(name)) { 493 String value = cookies[i].getValue(); 494 if (map == null) { 495 map = new HashMap (cookies.length); 496 } 497 map.put(name,value); 498 } 499 } 500 } 501 } 502 this.logicSheetParameters = map; 503 return this.logicSheetParameters; 504 } 505 506 509 static boolean isValidXSLTParameterName(String name) { 510 if (name.length() == 0) { 511 return false; 512 } 513 514 char c = name.charAt(0); 515 if (!(Character.isLetter(c) || c == '_')) { 516 return false; 517 } 518 519 for (int i = name.length()-1; i > 1; i--) { 520 c = name.charAt(i); 521 if (!(Character.isLetterOrDigit(c) || 522 c == '-' || 523 c == '_' || 524 c == '.')) { 525 return false; 526 } 527 } 528 return true; 529 } 530 531 534 public void dispose() { 535 if ( this.manager != null ) { 536 this.manager.release(this.xsltProcessor); 537 this.xsltProcessor = null; 538 this.manager = null; 539 } 540 } 541 542 545 public void recycle() { 546 this.objectModel = null; 547 if (this.inputSource != null) { 548 this.resolver.release(this.inputSource); 549 this.inputSource = null; 550 } 551 this.resolver = null; 552 this.par = null; 553 if (!this.finishedDocument && transformerHandler != null) { 554 if (xalanDtmManagerGetIncrementalMethod != null 561 && transformerHandler.getClass().getName().equals("org.apache.xalan.transformer.TransformerHandlerImpl")) { 562 try { 563 final boolean incremental = ((Boolean )xalanDtmManagerGetIncrementalMethod.invoke(null, null)).booleanValue(); 564 if (incremental) { 565 super.endDocument(); 566 } 567 } catch (Exception ignore) {} 568 } 569 } 570 this.finishedDocument = true; 571 this.logicSheetParameters = null; 572 this.transformerHandler = null; 573 this.transformerValidity = null; 574 this.exceptionDuringSetConsumer = null; 575 this.errorListener = null; 576 super.recycle(); 577 } 578 579 582 public void endDocument() 583 throws SAXException { 584 try { 585 super.endDocument(); 586 } catch(Exception e) { 587 588 Throwable realEx = this.errorListener.getThrowable(); 589 if (realEx == null) realEx = e; 590 591 if (realEx instanceof RuntimeException ) { 592 throw (RuntimeException )realEx; 593 } 594 595 if (realEx instanceof SAXException ) { 596 throw (SAXException )realEx; 597 } 598 599 if (realEx instanceof Error ) { 600 throw (Error )realEx; 601 } 602 603 throw new NestableRuntimeException(realEx); 604 } 605 this.finishedDocument = true; 606 } 607 608 611 public void startDocument() throws SAXException { 612 if ( this.exceptionDuringSetConsumer != null ) { 615 throw this.exceptionDuringSetConsumer; 616 } 617 this.finishedDocument = false; 618 super.startDocument(); 619 } 620 } 621 | Popular Tags |