001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon;
018:
019: import org.apache.avalon.excalibur.component.ComponentProxyGenerator;
020: import org.apache.avalon.excalibur.component.DefaultRoleManager;
021: import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
022: import org.apache.avalon.excalibur.logger.LoggerManager;
023: import org.apache.avalon.framework.activity.Disposable;
024: import org.apache.avalon.framework.activity.Initializable;
025: import org.apache.avalon.framework.component.Component;
026: import org.apache.avalon.framework.component.ComponentException;
027: import org.apache.avalon.framework.component.ComponentManager;
028: import org.apache.avalon.framework.component.Composable;
029: import org.apache.avalon.framework.configuration.Configuration;
030: import org.apache.avalon.framework.configuration.ConfigurationException;
031: import org.apache.avalon.framework.configuration.DefaultConfiguration;
032: import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
033: import org.apache.avalon.framework.container.ContainerUtil;
034: import org.apache.avalon.framework.context.Context;
035: import org.apache.avalon.framework.context.ContextException;
036: import org.apache.avalon.framework.context.Contextualizable;
037: import org.apache.avalon.framework.context.DefaultContext;
038: import org.apache.avalon.framework.logger.AbstractLogEnabled;
039: import org.apache.avalon.framework.logger.Logger;
040: import org.apache.avalon.framework.thread.ThreadSafe;
041:
042: import org.apache.cocoon.components.CocoonComponentManager;
043: import org.apache.cocoon.components.ComponentContext;
044: import org.apache.cocoon.components.PropertyAwareSAXConfigurationHandler;
045: import org.apache.cocoon.components.pipeline.ProcessingPipeline;
046: import org.apache.cocoon.components.source.SourceUtil;
047: import org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper;
048: import org.apache.cocoon.environment.Environment;
049: import org.apache.cocoon.environment.ObjectModelHelper;
050: import org.apache.cocoon.environment.Request;
051: import org.apache.cocoon.environment.Session;
052: import org.apache.cocoon.util.ClassUtils;
053: import org.apache.cocoon.util.Deprecation;
054: import org.apache.cocoon.util.SimpleSourceResolver;
055: import org.apache.cocoon.util.Settings;
056: import org.apache.cocoon.util.SettingsHelper;
057: import org.apache.cocoon.util.location.Location;
058: import org.apache.cocoon.util.location.LocationImpl;
059: import org.apache.cocoon.util.location.LocationUtils;
060:
061: import org.apache.commons.lang.SystemUtils;
062: import org.apache.excalibur.instrument.InstrumentManageable;
063: import org.apache.excalibur.instrument.InstrumentManager;
064: import org.apache.excalibur.source.Source;
065: import org.apache.excalibur.source.SourceResolver;
066: import org.apache.excalibur.source.impl.URLSource;
067: import org.apache.excalibur.xml.impl.XercesParser;
068: import org.apache.excalibur.xml.sax.SAXParser;
069: import org.xml.sax.InputSource;
070:
071: import java.io.BufferedInputStream;
072: import java.io.File;
073: import java.io.IOException;
074: import java.net.URL;
075: import java.util.Collections;
076: import java.util.Enumeration;
077: import java.util.Map;
078: import java.util.ConcurrentModificationException;
079:
080: /**
081: * The Cocoon Object is the main Kernel for the entire Cocoon system.
082: *
083: * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a> (Apache Software Foundation)
084: * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
085: * @author <a href="mailto:leo.sutic@inspireinfrastructure.com">Leo Sutic</a>
086: * @version CVS $Id: Cocoon.java 446922 2006-09-16 19:24:36Z vgritsenko $
087: */
088: public class Cocoon extends AbstractLogEnabled implements ThreadSafe,
089: Component, Initializable, Disposable, Modifiable, Processor,
090: Contextualizable, Composable, InstrumentManageable {
091:
092: // Register the location finder for Avalon configuration objects and exceptions
093: // and keep a strong reference to it.
094: private static final LocationUtils.LocationFinder LOCATION_FINDER = new LocationUtils.LocationFinder() {
095: public Location getLocation(Object obj, String description) {
096: if (obj instanceof Configuration) {
097: Configuration config = (Configuration) obj;
098: String locString = config.getLocation();
099: Location result = LocationUtils.parse(locString);
100: if (LocationUtils.isKnown(result)) {
101: // Add description
102: StringBuffer desc = new StringBuffer().append('<');
103: // Unfortunately Configuration.getPrefix() is not public
104: try {
105: if (config.getNamespace().startsWith(
106: "http://apache.org/cocoon/sitemap/")) {
107: desc.append("map:");
108: }
109: } catch (ConfigurationException e) {
110: // no namespace: ignore
111: }
112: desc.append(config.getName()).append('>');
113: return new LocationImpl(desc.toString(), result);
114: } else {
115: return result;
116: }
117: }
118:
119: if (obj instanceof Exception) {
120: // Many exceptions in Cocoon have a message like "blah blah at file://foo/bar.xml:12:1"
121: String msg = ((Exception) obj).getMessage();
122: if (msg == null) {
123: return null;
124: }
125:
126: int pos = msg.lastIndexOf(" at ");
127: if (pos != -1) {
128: return LocationUtils.parse(msg.substring(pos + 4));
129: } else {
130: // Will try other finders
131: return null;
132: }
133: }
134:
135: // Try next finders.
136: return null;
137: }
138: };
139:
140: static {
141: LocationUtils.addFinder(LOCATION_FINDER);
142: }
143:
144: static Cocoon instance;
145:
146: /** The root Cocoon logger */
147: private Logger rootLogger;
148:
149: /** The application context */
150: private Context context;
151:
152: /** The configuration file */
153: private Source configurationFile;
154:
155: /** The configuration tree */
156: private Configuration configuration;
157:
158: /** The logger manager */
159: private LoggerManager loggerManager;
160:
161: /** The instrument manager */
162: private InstrumentManager instrumentManager;
163:
164: /** The classpath (null if not available) */
165: private String classpath;
166:
167: /** The working directory (null if not available) */
168: private File workDir;
169:
170: /** The component manager. */
171: private ExcaliburComponentManager componentManager;
172:
173: /** The parent component manager. */
174: private ComponentManager parentComponentManager;
175:
176: /** Flag for disposed or not */
177: private boolean disposed;
178:
179: /** Active request count */
180: private volatile int activeRequestCount;
181:
182: /** The Processor if it is ThreadSafe */
183: private Processor threadSafeProcessor;
184:
185: /** The source resolver */
186: protected SourceResolver sourceResolver;
187:
188: /** An optional Avalon Component that is called before and after processing all requests. */
189: protected RequestListener requestListener;
190:
191: /**
192: * Creates a new <code>Cocoon</code> instance.
193: *
194: * @exception ConfigurationException if an error occurs
195: */
196: public Cocoon() throws ConfigurationException {
197: // Set the system properties needed by Xalan2.
198: setSystemProperties();
199:
200: // HACK: Provide a way to share an instance of Cocoon object between
201: // several servlets/portlets.
202: Cocoon.instance = this ;
203: }
204:
205: public void enableLogging(Logger logger) {
206: this .rootLogger = logger;
207: super .enableLogging(logger.getChildLogger("cocoon"));
208: }
209:
210: /**
211: * Get the parent component manager. For purposes of
212: * avoiding extra method calls, the manager parameter may be null.
213: *
214: * @param manager the parent component manager. May be <code>null</code>
215: */
216: public void compose(ComponentManager manager)
217: throws ComponentException {
218: this .parentComponentManager = manager;
219: }
220:
221: /**
222: * Describe <code>contextualize</code> method here.
223: *
224: * @param context a <code>Context</code> value
225: * @exception ContextException if an error occurs
226: */
227: public void contextualize(Context context) throws ContextException {
228: if (this .context == null) {
229: this .context = new ComponentContext(context);
230: SettingsHelper.createSettings(
231: (DefaultContext) this .context, getLogger());
232: ((DefaultContext) this .context).makeReadOnly();
233:
234: this .classpath = (String) context
235: .get(Constants.CONTEXT_CLASSPATH);
236: this .workDir = (File) context
237: .get(Constants.CONTEXT_WORK_DIR);
238: try {
239: // FIXME: add a configuration option for the refresh delay.
240: // for now, hard-coded to 1 second.
241: URLSource urlSource = new URLSource();
242: urlSource.init((URL) context
243: .get(Constants.CONTEXT_CONFIG_URL), null);
244: this .configurationFile = new DelayedRefreshSourceWrapper(
245: urlSource, 1000L);
246:
247: } catch (IOException e) {
248: throw new ContextException(
249: "Could not open configuration file.", e);
250: } catch (Exception e) {
251: throw new ContextException(
252: "contextualize(..) Exception", e);
253: }
254: }
255: }
256:
257: /**
258: * The <code>setLoggerManager</code> method will get a <code>LoggerManager</code>
259: * for further use.
260: *
261: * @param loggerManager a <code>LoggerManager</code> value
262: */
263: public void setLoggerManager(LoggerManager loggerManager) {
264: this .loggerManager = loggerManager;
265: Deprecation.setLogger(this .loggerManager
266: .getLoggerForCategory("deprecation"));
267: }
268:
269: /**
270: * Set the <code>InstrumentManager</code> for this Cocoon instance.
271: *
272: * @param manager an <code>InstrumentManager</code> instance
273: */
274: public void setInstrumentManager(final InstrumentManager manager) {
275: this .instrumentManager = manager;
276: }
277:
278: /**
279: * The <code>initialize</code> method
280: *
281: * @exception Exception if an error occurs
282: */
283: public void initialize() throws Exception {
284: if (parentComponentManager != null) {
285: this .componentManager = new CocoonComponentManager(
286: parentComponentManager, (ClassLoader) this .context
287: .get(Constants.CONTEXT_CLASS_LOADER));
288: } else {
289: this .componentManager = new CocoonComponentManager(
290: (ClassLoader) this .context
291: .get(Constants.CONTEXT_CLASS_LOADER));
292: }
293: ContainerUtil.enableLogging(this .componentManager,
294: this .rootLogger.getChildLogger("manager"));
295: ContainerUtil
296: .contextualize(this .componentManager, this .context);
297: this .componentManager
298: .setInstrumentManager(this .instrumentManager);
299: getLogger().debug("New Cocoon object.");
300:
301: // Log the System Properties.
302: dumpSystemProperties();
303:
304: // Setup the default parser, for parsing configuration.
305: // If one need to use a different parser, set the given system property
306: // first check for deprecated property to be compatible:
307: String parser = getSystemProperty(
308: Constants.DEPRECATED_PARSER_PROPERTY,
309: Constants.DEFAULT_PARSER);
310: if (!Constants.DEFAULT_PARSER.equals(parser)) {
311: getLogger().warn(
312: "Deprecated property "
313: + Constants.DEPRECATED_PARSER_PROPERTY
314: + " is used. Please use "
315: + Constants.PARSER_PROPERTY + " instead.");
316: if ("org.apache.cocoon.components.parser.XercesParser"
317: .equals(parser)) {
318: parser = XercesParser.class.getName();
319: } else {
320: getLogger()
321: .warn(
322: "Unknown value for deprecated property: "
323: + Constants.DEPRECATED_PARSER_PROPERTY
324: + ", value: "
325: + parser
326: + ". If you experience problems during startup, check the parser configuration section of the documentation.");
327: }
328: } else {
329: parser = getSystemProperty(Constants.PARSER_PROPERTY,
330: Constants.DEFAULT_PARSER);
331: }
332: if (getLogger().isDebugEnabled()) {
333: getLogger().debug("Parser: " + parser);
334: getLogger().debug("Classpath: " + classpath);
335: getLogger().debug(
336: "Work directory: " + workDir.getCanonicalPath());
337: }
338:
339: ExcaliburComponentManager startupManager = new ExcaliburComponentManager(
340: (ClassLoader) this .context
341: .get(Constants.CONTEXT_CLASS_LOADER));
342: ContainerUtil.enableLogging(startupManager, this .rootLogger
343: .getChildLogger("startup"));
344: ContainerUtil.contextualize(startupManager, this .context);
345: startupManager.setLoggerManager(this .loggerManager);
346:
347: try {
348: startupManager.addComponent(SAXParser.ROLE, ClassUtils
349: .loadClass(parser), new DefaultConfiguration("",
350: "empty"));
351: } catch (Exception e) {
352: throw new ConfigurationException("Could not load parser "
353: + parser, e);
354: }
355:
356: ContainerUtil.initialize(startupManager);
357: configure(startupManager);
358: ContainerUtil.dispose(startupManager);
359: startupManager = null;
360:
361: // add the logger manager to the component locator
362: final ComponentProxyGenerator proxyGenerator = new ComponentProxyGenerator();
363: final Component loggerManagerProxy = proxyGenerator.getProxy(
364: LoggerManager.class.getName(), loggerManager);
365: componentManager.addComponentInstance(LoggerManager.ROLE,
366: loggerManagerProxy);
367:
368: ContainerUtil.initialize(this .componentManager);
369:
370: // Get the Processor and keep it if it's ThreadSafe
371: Processor processor = (Processor) this .componentManager
372: .lookup(Processor.ROLE);
373: if (processor instanceof ThreadSafe) {
374: if (getLogger().isDebugEnabled()) {
375: getLogger().debug(
376: "Processor of class "
377: + processor.getClass().getName()
378: + " is ThreadSafe");
379: }
380: this .threadSafeProcessor = processor;
381: } else {
382: if (getLogger().isDebugEnabled()) {
383: getLogger()
384: .debug(
385: "Processor of class "
386: + processor.getClass()
387: .getName()
388: + " is NOT ThreadSafe -- will be looked up at each request");
389: }
390: this .componentManager.release(processor);
391: }
392:
393: this .sourceResolver = (SourceResolver) this .componentManager
394: .lookup(SourceResolver.ROLE);
395:
396: if (this .componentManager.hasComponent(RequestListener.ROLE)) {
397: this .requestListener = (RequestListener) this .componentManager
398: .lookup(RequestListener.ROLE);
399: }
400: }
401:
402: /** Dump System Properties */
403: private void dumpSystemProperties() {
404: if (getLogger().isDebugEnabled()) {
405: try {
406: Enumeration e = System.getProperties().propertyNames();
407: getLogger()
408: .debug("===== System Properties Start =====");
409: for (; e.hasMoreElements();) {
410: String key = (String) e.nextElement();
411: getLogger().debug(
412: key + "=" + System.getProperty(key));
413: }
414: getLogger().debug("===== System Properties End =====");
415: } catch (SecurityException se) {
416: // Ignore Exceptions.
417: }
418: }
419: }
420:
421: /**
422: * Configure this <code>Cocoon</code> instance.
423: *
424: * @param startupManager an <code>ExcaliburComponentManager</code> value
425: * @exception ConfigurationException if an error occurs
426: * @exception ContextException if an error occurs
427: */
428: public void configure(ExcaliburComponentManager startupManager)
429: throws ConfigurationException, ContextException {
430: SAXParser p = null;
431: Settings settings = SettingsHelper.getSettings(this .context);
432:
433: Configuration roles = null;
434: try {
435: p = (SAXParser) startupManager.lookup(SAXParser.ROLE);
436: SAXConfigurationHandler b = new PropertyAwareSAXConfigurationHandler(
437: settings, getLogger());
438: URL url = ClassUtils
439: .getResource("org/apache/cocoon/cocoon.roles");
440: InputSource is = new InputSource(url.openStream());
441: is.setSystemId(url.toString());
442: p.parse(is, b);
443: roles = b.getConfiguration();
444: } catch (Exception e) {
445: throw new ConfigurationException(
446: "Error trying to load configurations", e);
447: } finally {
448: if (p != null)
449: startupManager.release((Component) p);
450: }
451:
452: DefaultRoleManager drm = new DefaultRoleManager();
453: ContainerUtil.enableLogging(drm, this .rootLogger
454: .getChildLogger("roles"));
455: ContainerUtil.configure(drm, roles);
456: roles = null;
457:
458: try {
459: this .configurationFile.refresh();
460: p = (SAXParser) startupManager.lookup(SAXParser.ROLE);
461: SAXConfigurationHandler b = new PropertyAwareSAXConfigurationHandler(
462: settings, getLogger());
463: InputSource is = SourceUtil
464: .getInputSource(this .configurationFile);
465: p.parse(is, b);
466: this .configuration = b.getConfiguration();
467: } catch (Exception e) {
468: throw new ConfigurationException(
469: "Error trying to load configurations", e);
470: } finally {
471: if (p != null)
472: startupManager.release((Component) p);
473: }
474:
475: Configuration conf = this .configuration;
476: if (getLogger().isDebugEnabled()) {
477: getLogger().debug("Root configuration: " + conf.getName());
478: }
479: if (!"cocoon".equals(conf.getName())) {
480: throw new ConfigurationException(
481: "Invalid configuration file\n" + conf.toString());
482: }
483: if (getLogger().isDebugEnabled()) {
484: getLogger().debug(
485: "Configuration version: "
486: + conf.getAttribute("version"));
487: }
488: if (!Constants.CONF_VERSION
489: .equals(conf.getAttribute("version"))) {
490: throw new ConfigurationException(
491: "Invalid configuration schema version. Must be '"
492: + Constants.CONF_VERSION + "'.");
493: }
494:
495: String userRoles = conf.getAttribute("user-roles", "");
496: if (!"".equals(userRoles)) {
497: try {
498: p = (SAXParser) startupManager.lookup(SAXParser.ROLE);
499: SAXConfigurationHandler b = new PropertyAwareSAXConfigurationHandler(
500: settings, getLogger());
501: org.apache.cocoon.environment.Context context = (org.apache.cocoon.environment.Context) this .context
502: .get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
503: URL url = context.getResource(userRoles);
504: if (url == null) {
505: throw new ConfigurationException(
506: "User-roles configuration '" + userRoles
507: + "' cannot be found.");
508: }
509: InputSource is = new InputSource(
510: new BufferedInputStream(url.openStream()));
511: is.setSystemId(url.toString());
512: p.parse(is, b);
513: roles = b.getConfiguration();
514: } catch (Exception e) {
515: throw new ConfigurationException(
516: "Error trying to load user-roles configuration",
517: e);
518: } finally {
519: startupManager.release((Component) p);
520: }
521:
522: DefaultRoleManager urm = new DefaultRoleManager(drm);
523: ContainerUtil.enableLogging(urm, this .rootLogger
524: .getChildLogger("roles").getChildLogger("user"));
525: ContainerUtil.configure(urm, roles);
526: roles = null;
527: drm = urm;
528: }
529:
530: this .componentManager.setRoleManager(drm);
531: this .componentManager.setLoggerManager(this .loggerManager);
532:
533: getLogger().debug("Setting up components...");
534: ContainerUtil.configure(this .componentManager, conf);
535: }
536:
537: /**
538: * Queries the class to estimate its ergodic period termination.
539: *
540: * @param date a <code>long</code> value
541: * @return a <code>boolean</code> value
542: */
543: public boolean modifiedSince(long date) {
544: return date < this .configurationFile.getLastModified();
545: }
546:
547: /**
548: * Helper method to retrieve system property.
549: * Returns default value if SecurityException is caught.
550: */
551: public static String getSystemProperty(String property, String value) {
552: try {
553: return System.getProperty(property, value);
554: } catch (SecurityException e) {
555: System.err
556: .println("Caught a SecurityException reading the system property '"
557: + property
558: + "';"
559: + " Cocoon will default to '"
560: + value
561: + "' value.");
562: return value;
563: }
564: }
565:
566: /**
567: * Sets required system properties.
568: */
569: protected void setSystemProperties() {
570: try {
571: // FIXME We shouldn't have to specify the SAXParser...
572: // This is needed by Xalan2, it is used by org.xml.sax.helpers.XMLReaderFactory
573: // to locate the SAX2 driver.
574: if (getSystemProperty("org.xml.sax.driver", null) == null) {
575: System.setProperty("org.xml.sax.driver",
576: "org.apache.xerces.parsers.SAXParser");
577: }
578: } catch (SecurityException e) {
579: // Ignore security exceptions
580: System.out
581: .println("Caught a SecurityException writing the system property: "
582: + e);
583: }
584:
585: try {
586: // FIXME We shouldn't have to specify these. Needed to override jaxp implementation of weblogic.
587: if (getSystemProperty(
588: "javax.xml.parsers.DocumentBuilderFactory", "")
589: .startsWith("weblogic")) {
590: System
591: .setProperty(
592: "javax.xml.parsers.DocumentBuilderFactory",
593: "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
594: System.setProperty(
595: "javax.xml.parsers.SAXParserFactory",
596: "org.apache.xerces.jaxp.SAXParserFactoryImpl");
597: }
598: } catch (SecurityException e) {
599: // Ignore security exceptions
600: System.out
601: .println("Caught a SecurityException writing the system property: "
602: + e);
603: }
604: }
605:
606: /**
607: * Dispose this instance
608: */
609: public void dispose() {
610: if (this .componentManager != null) {
611: if (this .requestListener != null) {
612: this .componentManager.release(this .requestListener);
613: }
614: this .componentManager.release(this .threadSafeProcessor);
615: this .threadSafeProcessor = null;
616:
617: this .componentManager.release(this .sourceResolver);
618: this .sourceResolver = null;
619:
620: ContainerUtil.dispose(this .componentManager);
621: this .componentManager = null;
622: }
623:
624: this .context = null;
625: if (Cocoon.instance == this ) {
626: Cocoon.instance = null;
627: }
628: this .disposed = true;
629: }
630:
631: /**
632: * Log debug information about the current environment.
633: *
634: * @param environment an <code>Environment</code> value
635: */
636: protected void debug(Environment environment, boolean internal) {
637: String lineSeparator = SystemUtils.LINE_SEPARATOR;
638: Map objectModel = environment.getObjectModel();
639: Request request = ObjectModelHelper.getRequest(objectModel);
640: Session session = request.getSession(false);
641: StringBuffer msg = new StringBuffer(2048);
642: msg.append("DEBUGGING INFORMATION:").append(lineSeparator);
643: if (internal) {
644: msg.append("INTERNAL ");
645: }
646: msg.append("REQUEST: ").append(request.getRequestURI()).append(
647: lineSeparator).append(lineSeparator);
648: msg.append("CONTEXT PATH: ").append(request.getContextPath())
649: .append(lineSeparator);
650: msg.append("SERVLET PATH: ").append(request.getServletPath())
651: .append(lineSeparator);
652: msg.append("PATH INFO: ").append(request.getPathInfo()).append(
653: lineSeparator).append(lineSeparator);
654:
655: msg.append("REMOTE HOST: ").append(request.getRemoteHost())
656: .append(lineSeparator);
657: msg.append("REMOTE ADDRESS: ").append(request.getRemoteAddr())
658: .append(lineSeparator);
659: msg.append("REMOTE USER: ").append(request.getRemoteUser())
660: .append(lineSeparator);
661: msg.append("REQUEST SESSION ID: ").append(
662: request.getRequestedSessionId()).append(lineSeparator);
663: msg.append("REQUEST PREFERRED LOCALE: ").append(
664: request.getLocale().toString()).append(lineSeparator);
665: msg.append("SERVER HOST: ").append(request.getServerName())
666: .append(lineSeparator);
667: msg.append("SERVER PORT: ").append(request.getServerPort())
668: .append(lineSeparator).append(lineSeparator);
669:
670: msg.append("METHOD: ").append(request.getMethod()).append(
671: lineSeparator);
672: msg.append("CONTENT LENGTH: ").append(
673: request.getContentLength()).append(lineSeparator);
674: msg.append("PROTOCOL: ").append(request.getProtocol()).append(
675: lineSeparator);
676: msg.append("SCHEME: ").append(request.getScheme()).append(
677: lineSeparator);
678: msg.append("AUTH TYPE: ").append(request.getAuthType()).append(
679: lineSeparator).append(lineSeparator);
680: msg.append("CURRENT ACTIVE REQUESTS: ").append(
681: activeRequestCount).append(lineSeparator);
682:
683: // log all of the request parameters
684: Enumeration e = request.getParameterNames();
685:
686: msg.append("REQUEST PARAMETERS:").append(lineSeparator).append(
687: lineSeparator);
688:
689: while (e.hasMoreElements()) {
690: String p = (String) e.nextElement();
691:
692: msg.append("PARAM: '").append(p).append("' ").append(
693: "VALUES: '");
694: String[] params = request.getParameterValues(p);
695: for (int i = 0; i < params.length; i++) {
696: msg.append("[" + params[i] + "]");
697: if (i != (params.length - 1)) {
698: msg.append(", ");
699: }
700: }
701:
702: msg.append("'").append(lineSeparator);
703: }
704:
705: // log all of the header parameters
706: Enumeration e2 = request.getHeaderNames();
707:
708: msg.append("HEADER PARAMETERS:").append(lineSeparator).append(
709: lineSeparator);
710:
711: while (e2.hasMoreElements()) {
712: String p = (String) e2.nextElement();
713:
714: msg.append("PARAM: '").append(p).append("' ").append(
715: "VALUES: '");
716: Enumeration e3 = request.getHeaders(p);
717: while (e3.hasMoreElements()) {
718: msg.append("[" + e3.nextElement() + "]");
719: if (e3.hasMoreElements()) {
720: msg.append(", ");
721: }
722: }
723:
724: msg.append("'").append(lineSeparator);
725: }
726:
727: msg.append(lineSeparator).append("SESSION ATTRIBUTES:").append(
728: lineSeparator).append(lineSeparator);
729:
730: // log all of the session attributes
731: if (session != null) {
732: StringBuffer buffer = new StringBuffer("");
733: int count = -1;
734: while (count <= 0) {
735: // Fix bug #12139: Session can be modified while still
736: // being enumerated here
737: try {
738: e = session.getAttributeNames();
739: while (e.hasMoreElements()) {
740: String p = (String) e.nextElement();
741: buffer.append("PARAM: '").append(p)
742: .append("' ").append("VALUE: '")
743: .append(session.getAttribute(p))
744: .append("'").append(lineSeparator);
745: }
746: break;
747: } catch (ConcurrentModificationException ex) {
748: buffer = new StringBuffer("");
749: ++count;
750: }
751:
752: }
753: msg.append(buffer.toString());
754: }
755:
756: getLogger().debug(msg.toString());
757: }
758:
759: /**
760: * Process the given <code>Environment</code> to produce the output.
761: *
762: * @param environment an <code>Environment</code> value
763: * @return a <code>boolean</code> value
764: * @exception Exception if an error occurs
765: */
766: public boolean process(Environment environment) throws Exception {
767: if (this .disposed) {
768: throw new IllegalStateException(
769: "You cannot process a Disposed Cocoon engine.");
770: }
771:
772: Object key = CocoonComponentManager
773: .startProcessing(environment);
774: final int environmentDepth = CocoonComponentManager
775: .markEnvironment();
776: CocoonComponentManager.enterEnvironment(environment,
777: this .componentManager, this );
778: try {
779: boolean result;
780: if (getLogger().isDebugEnabled()) {
781: ++activeRequestCount;
782: debug(environment, false);
783: }
784:
785: if (this .requestListener != null) {
786: try {
787: requestListener.onRequestStart(environment);
788: } catch (Exception e) {
789: getLogger().error(
790: "Error encountered monitoring request start: "
791: + e.getMessage());
792: }
793: }
794:
795: if (this .threadSafeProcessor != null) {
796: result = this .threadSafeProcessor.process(environment);
797: if (this .requestListener != null) {
798: try {
799: requestListener.onRequestEnd(environment);
800: } catch (Exception e) {
801: getLogger().error(
802: "Error encountered monitoring request start: "
803: + e.getMessage());
804: }
805: }
806: } else {
807: Processor processor = (Processor) this .componentManager
808: .lookup(Processor.ROLE);
809: try {
810: result = processor.process(environment);
811: if (this .requestListener != null) {
812: try {
813: requestListener.onRequestEnd(environment);
814: } catch (Exception e) {
815: getLogger().error(
816: "Error encountered monitoring request start: "
817: + e.getMessage());
818: }
819: }
820: } finally {
821: this .componentManager.release(processor);
822: }
823: }
824: // commit response on success
825: environment.commitResponse();
826:
827: return result;
828: } catch (Exception any) {
829: if (this .requestListener != null) {
830: try {
831: requestListener
832: .onRequestException(environment, any);
833: } catch (Exception e) {
834: getLogger().error(
835: "Error encountered monitoring request start: "
836: + e.getMessage());
837: }
838: }
839: // reset response on error
840: environment.tryResetResponse();
841: throw any;
842: } finally {
843: CocoonComponentManager.leaveEnvironment();
844: CocoonComponentManager.endProcessing(environment, key);
845: if (getLogger().isDebugEnabled()) {
846: --activeRequestCount;
847: }
848:
849: // TODO (CZ): This is only for testing - remove it later on
850: CocoonComponentManager.checkEnvironment(environmentDepth,
851: getLogger());
852: }
853: }
854:
855: /**
856: * Process the given <code>Environment</code> to assemble
857: * a <code>ProcessingPipeline</code>.
858: * @since 2.1
859: */
860: public ProcessingPipeline buildPipeline(Environment environment)
861: throws Exception {
862: if (disposed) {
863: throw new IllegalStateException(
864: "You cannot process a Disposed Cocoon engine.");
865: }
866:
867: try {
868: if (getLogger().isDebugEnabled()) {
869: ++activeRequestCount;
870: debug(environment, true);
871: }
872:
873: if (this .threadSafeProcessor != null) {
874: return this .threadSafeProcessor
875: .buildPipeline(environment);
876: } else {
877: Processor processor = (Processor) this .componentManager
878: .lookup(Processor.ROLE);
879: try {
880: return processor.buildPipeline(environment);
881: } finally {
882: this .componentManager.release(processor);
883: }
884: }
885:
886: } finally {
887: if (getLogger().isDebugEnabled()) {
888: --activeRequestCount;
889: }
890: }
891: }
892:
893: /**
894: * Get the sitemap component configurations
895: * @since 2.1
896: */
897: public Map getComponentConfigurations() {
898: return Collections.EMPTY_MAP;
899: }
900:
901: /**
902: * Return this (Cocoon is always at the root of the processing chain).
903: * @since 2.1.1
904: */
905: public Processor getRootProcessor() {
906: return this ;
907: }
908:
909: /**
910: * Accessor for active request count
911: */
912: public int getActiveRequestCount() {
913: return activeRequestCount;
914: }
915:
916: public ExcaliburComponentManager getComponentManager() {
917: return this .componentManager;
918: }
919:
920: /**
921: * Create a simple source resolver.
922: */
923: protected SourceResolver createSourceResolver(Logger logger)
924: throws ContextException {
925: // Create our own resolver
926: final SimpleSourceResolver resolver = new SimpleSourceResolver();
927: resolver.enableLogging(logger);
928: try {
929: resolver.contextualize(this .context);
930: } catch (ContextException ce) {
931: throw new ContextException("Cannot setup source resolver.",
932: ce);
933: }
934: return resolver;
935: }
936: }
|