| 1 16 package org.apache.cocoon.portlet; 17 18 import org.apache.avalon.excalibur.logger.Log4JLoggerManager; 19 import org.apache.avalon.excalibur.logger.LogKitLoggerManager; 20 import org.apache.avalon.excalibur.logger.LoggerManager; 21 import org.apache.avalon.framework.activity.Disposable; 22 import org.apache.avalon.framework.activity.Initializable; 23 import org.apache.avalon.framework.component.ComponentManager; 24 import org.apache.avalon.framework.configuration.Configurable; 25 import org.apache.avalon.framework.configuration.Configuration; 26 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; 27 import org.apache.avalon.framework.container.ContainerUtil; 28 import org.apache.avalon.framework.context.Contextualizable; 29 import org.apache.avalon.framework.context.DefaultContext; 30 import org.apache.avalon.framework.logger.LogEnabled; 31 import org.apache.avalon.framework.logger.LogKitLogger; 32 import org.apache.avalon.framework.logger.Logger; 33 34 import org.apache.cocoon.Cocoon; 35 import org.apache.cocoon.ConnectionResetException; 36 import org.apache.cocoon.Constants; 37 import org.apache.cocoon.ResourceNotFoundException; 38 import org.apache.cocoon.components.notification.DefaultNotifyingBuilder; 39 import org.apache.cocoon.components.notification.Notifier; 40 import org.apache.cocoon.components.notification.Notifying; 41 import org.apache.cocoon.environment.Environment; 42 import org.apache.cocoon.environment.portlet.PortletContext; 43 import org.apache.cocoon.environment.portlet.PortletEnvironment; 44 import org.apache.cocoon.portlet.multipart.MultipartActionRequest; 45 import org.apache.cocoon.portlet.multipart.RequestFactory; 46 import org.apache.cocoon.util.ClassUtils; 47 import org.apache.cocoon.util.IOUtils; 48 import org.apache.cocoon.util.StringUtils; 49 import org.apache.cocoon.util.log.CocoonLogFormatter; 50 import org.apache.cocoon.util.log.Log4JConfigurator; 51 52 import org.apache.commons.lang.BooleanUtils; 53 import org.apache.commons.lang.SystemUtils; 54 import org.apache.excalibur.instrument.InstrumentManager; 55 import org.apache.excalibur.instrument.manager.impl.DefaultInstrumentManagerImpl; 56 import org.apache.log.ContextMap; 57 import org.apache.log.ErrorHandler; 58 import org.apache.log.Hierarchy; 59 import org.apache.log.Priority; 60 import org.apache.log.util.DefaultErrorHandler; 61 import org.apache.log4j.LogManager; 62 63 import javax.portlet.ActionRequest; 64 import javax.portlet.ActionResponse; 65 import javax.portlet.GenericPortlet; 66 import javax.portlet.PortletConfig; 67 import javax.portlet.PortletException; 68 import javax.portlet.PortletSession; 69 import javax.portlet.RenderRequest; 70 import javax.portlet.RenderResponse; 71 import javax.portlet.PortletRequest; 72 import java.io.File ; 73 import java.io.FileInputStream ; 74 import java.io.FileOutputStream ; 75 import java.io.IOException ; 76 import java.io.InputStream ; 77 import java.io.OutputStream ; 78 import java.io.PrintStream ; 79 import java.lang.reflect.Constructor ; 80 import java.net.MalformedURLException ; 81 import java.net.SocketException ; 82 import java.net.URL ; 83 import java.util.ArrayList ; 84 import java.util.Arrays ; 85 import java.util.HashMap ; 86 import java.util.Iterator ; 87 import java.util.List ; 88 import java.util.StringTokenizer ; 89 import java.util.jar.Attributes ; 90 import java.util.jar.Manifest ; 91 92 97 public class CocoonPortlet extends GenericPortlet { 98 99 103 public static final String CONTEXT_PORTLET_CONFIG = "portlet-config"; 104 105 protected static final String PROCESSED_BY = "Processed by " 107 + Constants.COMPLETE_NAME + " in "; 108 109 static final float SECOND = 1000; 111 static final float MINUTE = 60 * SECOND; 112 static final float HOUR = 60 * MINUTE; 113 114 private Logger log; 115 private LoggerManager loggerManager; 116 117 120 protected long creationTime = 0; 121 122 125 protected Cocoon cocoon; 126 127 130 protected Exception exception; 131 132 135 protected DefaultContext appContext = new DefaultContext(); 136 137 138 141 protected static final boolean ALLOW_RELOAD = false; 142 143 146 protected boolean allowReload; 147 148 149 152 protected boolean showTime; 153 154 157 protected boolean hiddenShowTime; 158 159 160 163 private static final boolean ENABLE_UPLOADS = false; 164 private static final boolean SAVE_UPLOADS_TO_DISK = true; 165 private static final int MAX_UPLOAD_SIZE = 10000000; 167 170 private boolean enableUploads; 171 private boolean autoSaveUploads; 172 private boolean allowOverwrite; 173 private boolean silentlyRename; 174 private int maxUploadSize; 175 176 private File uploadDir; 177 private File workDir; 178 private File cacheDir; 179 private String containerEncoding; 180 private String defaultFormEncoding; 181 182 protected javax.portlet.PortletContext portletContext; 183 184 185 protected ClassLoader classLoader = this.getClass().getClassLoader(); 186 protected boolean initClassLoader = false; 187 188 private String parentComponentManagerClass; 189 private String parentComponentManagerInitParam; 190 191 192 private ComponentManager parentComponentManager; 193 194 protected String forceLoadParameter; 195 protected String forceSystemProperty; 196 197 201 private boolean manageExceptions; 202 203 206 private boolean enableInstrumentation; 207 208 211 private InstrumentManager instrumentManager; 212 213 218 protected String portletContextPath; 219 220 223 protected String portletContextURL; 224 225 229 protected RequestFactory requestFactory; 230 231 236 protected String servletPath; 237 238 247 protected int defaultSessionScope; 248 249 252 protected boolean storeSessionPath; 253 254 272 public void init(PortletConfig conf) throws PortletException { 273 274 super.init(conf); 275 276 if (!this.initClassLoader) { 280 this.initClassLoader = getInitParameterAsBoolean("init-classloader", false); 281 } 282 283 if (this.initClassLoader) { 284 try { 287 Thread.currentThread().setContextClassLoader(this.classLoader); 288 } catch (Exception e) { 289 } 290 } 291 292 try { 293 String value = System.getProperty("javax.xml.parsers.SAXParserFactory"); 297 if (value != null && value.startsWith("weblogic")) { 298 System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl"); 299 System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"); 300 } 301 } catch (SecurityException e) { 302 System.out.println("CocoonPortlet: Could not check system properties, got: " + e); 304 } 305 306 this.portletContext = conf.getPortletContext(); 307 this.appContext.put(Constants.CONTEXT_ENVIRONMENT_CONTEXT, new PortletContext(this.portletContext)); 308 this.portletContextPath = this.portletContext.getRealPath("/"); 309 310 final String workDirParam = getInitParameter("work-directory"); 313 if (workDirParam != null) { 314 if (this.portletContextPath == null) { 315 this.workDir = new File (workDirParam); 317 } else { 318 File workDirParamFile = new File (workDirParam); 320 if (workDirParamFile.isAbsolute()) { 321 this.workDir = workDirParamFile; 323 } else { 324 this.workDir = new File (portletContextPath, workDirParam); 326 } 327 } 328 } else { 329 this.workDir = (File ) this.portletContext.getAttribute("javax.servlet.context.tempdir"); 331 if (this.workDir == null) { 332 this.workDir = new File (this.portletContext.getRealPath("/WEB-INF/work")); 333 } 334 this.workDir = new File (workDir, "cocoon-files"); 335 } 336 this.workDir.mkdirs(); 337 this.appContext.put(Constants.CONTEXT_WORK_DIR, workDir); 338 339 String path = this.portletContextPath; 340 String debugPathOne = null, debugPathTwo = null; 343 if (path == null) { 344 try { 346 path = this.portletContext.getResource("/WEB-INF").toString(); 347 } catch (MalformedURLException me) { 348 throw new PortletException("Unable to get resource 'WEB-INF'.", me); 349 } 350 debugPathOne = path; 351 path = path.substring(0, path.length() - "WEB-INF".length()); 352 debugPathTwo = path; 353 } 354 355 try { 356 if (path.indexOf(':') > 1) { 357 this.portletContextURL = path; 358 } else { 359 this.portletContextURL = new File (path).toURL().toExternalForm(); 360 } 361 } catch (MalformedURLException me) { 362 try { 366 this.portletContextURL = new File (path).toURL().toExternalForm(); 367 } catch (MalformedURLException ignored) { 368 throw new PortletException("Unable to determine portlet context URL.", me); 369 } 370 } 371 try { 372 this.appContext.put("context-root", new URL (this.portletContextURL)); 373 } catch (MalformedURLException ignore) { 374 } 376 377 initLogger(); 379 380 if (getLogger().isDebugEnabled()) { 381 getLogger().debug("getRealPath for /: " + this.portletContextPath); 382 if (this.portletContextPath == null) { 383 getLogger().debug("getResource for /WEB-INF: " + debugPathOne); 384 getLogger().debug("Path for Root: " + debugPathTwo); 385 } 386 } 387 388 this.forceLoadParameter = getInitParameter("load-class", null); 389 this.forceSystemProperty = getInitParameter("force-property", null); 390 391 if (getLogger().isDebugEnabled()) { 393 getLogger().debug("Portlet Context URL: " + this.portletContextURL); 394 if (workDirParam != null) { 395 getLogger().debug("Using work-directory " + this.workDir); 396 } else { 397 getLogger().debug("Using default work-directory " + this.workDir); 398 } 399 } 400 401 final String uploadDirParam = conf.getInitParameter("upload-directory"); 402 if (uploadDirParam != null) { 403 if (this.portletContextPath == null) { 404 this.uploadDir = new File (uploadDirParam); 405 } else { 406 File uploadDirParamFile = new File (uploadDirParam); 408 if (uploadDirParamFile.isAbsolute()) { 409 this.uploadDir = uploadDirParamFile; 411 } else { 412 this.uploadDir = new File (portletContextPath, uploadDirParam); 414 } 415 } 416 if (getLogger().isDebugEnabled()) { 417 getLogger().debug("Using upload-directory " + this.uploadDir); 418 } 419 } else { 420 this.uploadDir = new File (workDir, "upload-dir" + File.separator); 421 if (getLogger().isDebugEnabled()) { 422 getLogger().debug("Using default upload-directory " + this.uploadDir); 423 } 424 } 425 this.uploadDir.mkdirs(); 426 this.appContext.put(Constants.CONTEXT_UPLOAD_DIR, this.uploadDir); 427 428 this.enableUploads = getInitParameterAsBoolean("enable-uploads", ENABLE_UPLOADS); 429 430 this.autoSaveUploads = getInitParameterAsBoolean("autosave-uploads", SAVE_UPLOADS_TO_DISK); 431 432 String overwriteParam = getInitParameter("overwrite-uploads", "rename"); 433 if ("deny".equalsIgnoreCase(overwriteParam)) { 435 this.allowOverwrite = false; 436 this.silentlyRename = false; 437 } else if ("allow".equalsIgnoreCase(overwriteParam)) { 438 this.allowOverwrite = true; 439 this.silentlyRename = false; } else { 441 this.allowOverwrite = false; 443 this.silentlyRename = true; 444 } 445 446 this.maxUploadSize = getInitParameterAsInteger("upload-max-size", MAX_UPLOAD_SIZE); 447 448 String cacheDirParam = conf.getInitParameter("cache-directory"); 449 if (cacheDirParam != null) { 450 if (this.portletContextPath == null) { 451 this.cacheDir = new File (cacheDirParam); 452 } else { 453 File cacheDirParamFile = new File (cacheDirParam); 455 if (cacheDirParamFile.isAbsolute()) { 456 this.cacheDir = cacheDirParamFile; 458 } else { 459 this.cacheDir = new File (portletContextPath, cacheDirParam); 461 } 462 } 463 if (getLogger().isDebugEnabled()) { 464 getLogger().debug("Using cache-directory " + this.cacheDir); 465 } 466 } else { 467 this.cacheDir = IOUtils.createFile(workDir, "cache-dir" + File.separator); 468 if (getLogger().isDebugEnabled()) { 469 getLogger().debug("cache-directory was not set - defaulting to " + this.cacheDir); 470 } 471 } 472 this.cacheDir.mkdirs(); 473 this.appContext.put(Constants.CONTEXT_CACHE_DIR, this.cacheDir); 474 475 this.appContext.put(Constants.CONTEXT_CONFIG_URL, 476 getConfigFile(conf.getInitParameter("configurations"))); 477 if (conf.getInitParameter("configurations") == null) { 478 if (getLogger().isDebugEnabled()) { 479 getLogger().debug("configurations was not set - defaulting to... ?"); 480 } 481 } 482 483 this.allowReload = getInitParameterAsBoolean("allow-reload", ALLOW_RELOAD); 485 486 String value = conf.getInitParameter("show-time"); 487 this.showTime = BooleanUtils.toBoolean(value) || (this.hiddenShowTime = "hide".equals(value)); 488 if (value == null) { 489 if (getLogger().isDebugEnabled()) { 490 getLogger().debug("show-time was not set - defaulting to false"); 491 } 492 } 493 494 parentComponentManagerClass = getInitParameter("parent-component-manager", null); 495 if (parentComponentManagerClass != null) { 496 int dividerPos = parentComponentManagerClass.indexOf('/'); 497 if (dividerPos != -1) { 498 parentComponentManagerInitParam = parentComponentManagerClass.substring(dividerPos + 1); 499 parentComponentManagerClass = parentComponentManagerClass.substring(0, dividerPos); 500 } 501 } 502 503 this.containerEncoding = getInitParameter("container-encoding", "ISO-8859-1"); 504 this.defaultFormEncoding = getInitParameter("form-encoding", "ISO-8859-1"); 505 506 this.appContext.put(Constants.CONTEXT_DEFAULT_ENCODING, this.defaultFormEncoding); 507 this.manageExceptions = getInitParameterAsBoolean("manage-exceptions", true); 508 509 this.enableInstrumentation = getInitParameterAsBoolean("enable-instrumentation", false); 510 511 this.requestFactory = new RequestFactory(this.autoSaveUploads, 512 this.uploadDir, 513 this.allowOverwrite, 514 this.silentlyRename, 515 this.maxUploadSize, 516 this.defaultFormEncoding); 517 518 this.servletPath = getInitParameter("servlet-path", null); 519 if (this.servletPath != null) { 520 if (this.servletPath.startsWith("/")) { 521 this.servletPath = this.servletPath.substring(1); 522 } 523 if (this.servletPath.endsWith("/")) { 524 this.servletPath = servletPath.substring(0, servletPath.length() - 1); 525 } 526 } 527 528 final String sessionScopeParam = getInitParameter("default-session-scope", "portlet"); 529 if ("application".equalsIgnoreCase(sessionScopeParam)) { 530 this.defaultSessionScope = javax.portlet.PortletSession.APPLICATION_SCOPE; 531 } else { 532 this.defaultSessionScope = javax.portlet.PortletSession.PORTLET_SCOPE; 533 } 534 535 this.appContext.put(CONTEXT_PORTLET_CONFIG, conf); 537 this.createCocoon(); 538 } 539 540 543 public void destroy() { 544 if (this.initClassLoader) { 545 try { 546 Thread.currentThread().setContextClassLoader(this.classLoader); 547 } catch (Exception e) { 548 } 549 } 550 551 if (this.cocoon != null) { 552 if (getLogger().isDebugEnabled()) { 553 getLogger().debug("Portlet destroyed - disposing Cocoon"); 554 } 555 this.disposeCocoon(); 556 } 557 558 if (this.instrumentManager instanceof Disposable) { 559 ((Disposable) this.instrumentManager).dispose(); 560 } 561 562 if (this.parentComponentManager != null && this.parentComponentManager instanceof Disposable) { 563 ((Disposable) this.parentComponentManager).dispose(); 564 } 565 } 566 567 571 protected void addClassLoaderURL(URL URL) { 572 } 574 575 579 protected void addClassLoaderDirectory(String dir) { 580 } 582 583 599 protected String getClassPath() throws PortletException { 600 StringBuffer buildClassPath = new StringBuffer (); 601 602 File root = null; 603 if (portletContextPath != null) { 604 606 String classDir = this.portletContext.getRealPath("/WEB-INF/classes"); 607 String libDir = this.portletContext.getRealPath("/WEB-INF/lib"); 608 609 if (libDir != null) { 610 root = new File (libDir); 611 } 612 613 if (classDir != null) { 614 buildClassPath.append(classDir); 615 616 addClassLoaderDirectory(classDir); 617 } 618 } else { 619 URL classDirURL = null; 621 URL libDirURL = null; 622 623 try { 624 classDirURL = this.portletContext.getResource("/WEB-INF/classes"); 625 } catch (MalformedURLException me) { 626 if (getLogger().isWarnEnabled()) { 627 this.getLogger().warn("Unable to add WEB-INF/classes to the classpath", me); 628 } 629 } 630 631 try { 632 libDirURL = this.portletContext.getResource("/WEB-INF/lib"); 633 } catch (MalformedURLException me) { 634 if (getLogger().isWarnEnabled()) { 635 this.getLogger().warn("Unable to add WEB-INF/lib to the classpath", me); 636 } 637 } 638 639 if (libDirURL != null && libDirURL.toExternalForm().startsWith("file:")) { 640 root = new File (libDirURL.toExternalForm().substring("file:".length())); 641 } 642 643 if (classDirURL != null) { 644 buildClassPath.append(classDirURL.toExternalForm()); 645 646 addClassLoaderURL(classDirURL); 647 } 648 } 649 650 if (root == null) { 652 root = extractLibraries(); 653 } 654 655 if (root != null && root.isDirectory()) { 656 File [] libraries = root.listFiles(); 657 Arrays.sort(libraries); 658 for (int i = 0; i < libraries.length; i++) { 659 String fullName = IOUtils.getFullFilename(libraries[i]); 660 buildClassPath.append(File.pathSeparatorChar).append(fullName); 661 662 addClassLoaderDirectory(fullName); 663 } 664 } 665 666 buildClassPath.append(File.pathSeparatorChar) 667 .append(SystemUtils.JAVA_CLASS_PATH); 668 669 buildClassPath.append(File.pathSeparatorChar) 670 .append(getExtraClassPath()); 671 return buildClassPath.toString(); 672 } 673 674 private File extractLibraries() { 675 try { 676 URL manifestURL = this.portletContext.getResource("/META-INF/MANIFEST.MF"); 677 if (manifestURL == null) { 678 this.getLogger().fatalError("Unable to get Manifest"); 679 return null; 680 } 681 682 Manifest mf = new Manifest (manifestURL.openStream()); 683 Attributes attr = mf.getMainAttributes(); 684 String libValue = attr.getValue("Cocoon-Libs"); 685 if (libValue == null) { 686 this.getLogger().fatalError("Unable to get 'Cocoon-Libs' attribute from the Manifest"); 687 return null; 688 } 689 690 List libList = new ArrayList (); 691 for (StringTokenizer st = new StringTokenizer (libValue, " "); st.hasMoreTokens();) { 692 libList.add(st.nextToken()); 693 } 694 695 File root = new File (this.workDir, "lib"); 696 root.mkdirs(); 697 698 File [] oldLibs = root.listFiles(); 699 for (int i = 0; i < oldLibs.length; i++) { 700 String oldLib = oldLibs[i].getName(); 701 if (!libList.contains(oldLib)) { 702 this.getLogger().debug("Removing old library " + oldLibs[i]); 703 oldLibs[i].delete(); 704 } 705 } 706 707 this.getLogger().warn("Extracting libraries into " + root); 708 byte[] buffer = new byte[65536]; 709 for (Iterator i = libList.iterator(); i.hasNext();) { 710 String libName = (String ) i.next(); 711 712 long lastModified = -1; 713 try { 714 lastModified = Long.parseLong(attr.getValue("Cocoon-Lib-" + libName.replace('.', '_'))); 715 } catch (Exception e) { 716 this.getLogger().debug("Failed to parse lastModified: " + attr.getValue("Cocoon-Lib-" + libName.replace('.', '_'))); 717 } 718 719 File lib = new File (root, libName); 720 if (lib.exists() && lib.lastModified() != lastModified) { 721 this.getLogger().debug("Removing modified library " + lib); 722 lib.delete(); 723 } 724 725 InputStream is = this.portletContext.getResourceAsStream("/WEB-INF/lib/" + libName); 726 if (is == null) { 727 this.getLogger().warn("Skipping " + libName); 728 } else { 729 this.getLogger().debug("Extracting " + libName); 730 OutputStream os = null; 731 try { 732 os = new FileOutputStream (lib); 733 &nbs
|