Author: cziegeler
Date: Fri Apr 8 12:17:34 2005
New Revision: 160589
URL: http://svn.apache.org/viewcvs?view=rev&rev=160589
Log:
Let CoreUtil manage the Cocoon lifecycle
Added:
cocoon/trunk/src/java/org/apache/cocoon/core/BootstrapEnvironment.java
(with props)
Removed:
cocoon/trunk/src/java/org/apache/cocoon/util/log/LoggingHelper.java
Modified:
cocoon/trunk/src/java/org/apache/cocoon/core/Core.java
cocoon/trunk/src/java/org/apache/cocoon/core/CoreUtil.java
cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java
Added: cocoon/trunk/src/java/org/apache/cocoon/core/BootstrapEnvironment.java
URL:
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/core/BootstrapEnvironment.java?view=auto&rev=160589
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/core/BootstrapEnvironment.java
(added)
+++ cocoon/trunk/src/java/org/apache/cocoon/core/BootstrapEnvironment.java Fri
Apr 8 12:17:34 2005
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.core;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.avalon.framework.context.DefaultContext;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.cocoon.configuration.Settings;
+import org.apache.log.LogTarget;
+
+/**
+* The BootstrapEnvironment is the connection between the real environment
+* (servlet, cli etc.) and the Cocoon core. The core uses this object to
+* access information from the real environment and to pass several objects
+* back.
+* A BootstrapEnvironment can be used to create a new Cocoon system using
+* the [EMAIL PROTECTED] CoreUtil}.
+*
+* @version SVN $Id:$
+* @since 2.2
+*/
+public interface BootstrapEnvironment {
+
+ /** Log a message during bootstrapping. This is used to log
+ * information before the logging system is setup.
+ * @param message A message.
+ */
+ void log(String message);
+
+ /** Log a message during bootstrapping. This is used to log
+ * information before the logging system is setup.
+ * @param message A message.
+ * @param error An error.
+ */
+ void log(String message, Throwable error);
+
+ /**
+ * Pass the root logger back to the environment. As soon as the
+ * logging system is set up, this method is called.
+ * @param rootLogger The root logger.
+ */
+ void setLogger(Logger rootLogger);
+
+ InputStream getInputStream(String path);
+
+ void configure(Settings settings);
+ void configureLoggingContext(DefaultContext context);
+
+ void configure(DefaultContext context);
+
+ ClassLoader getInitClassLoader();
+
+ org.apache.cocoon.environment.Context getEnvironmentContext();
+
+ /**
+ * Returns the URL to the application context.
+ */
+ String getContextURL();
+
+ /**
+ * Returns a file to the application context.
+ * @return A file pointing to the context or null if the context is not
+ * writeable.
+ */
+ File getContextForWriting();
+
+ LogTarget getDefaultLogTarget();
+
+ /**
+ * Set the ConfigFile for the Cocoon object.
+ *
+ * @param configFileName The file location for the cocoon.xconf
+ *
+ * @throws Exception
+ */
+ URL getConfigFile(String configFileName)
+ throws Exception;
+
+ String getClassPath(Settings settings);
+}
\ No newline at end of file
Propchange:
cocoon/trunk/src/java/org/apache/cocoon/core/BootstrapEnvironment.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cocoon/trunk/src/java/org/apache/cocoon/core/BootstrapEnvironment.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: cocoon/trunk/src/java/org/apache/cocoon/core/Core.java
URL:
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/core/Core.java?view=diff&r1=160588&r2=160589
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/core/Core.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/core/Core.java Fri Apr 8 12:17:34
2005
@@ -17,8 +17,6 @@
package org.apache.cocoon.core;
import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -28,12 +26,9 @@
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
-import org.apache.avalon.framework.context.DefaultContext;
-import org.apache.avalon.framework.logger.Logger;
import org.apache.cocoon.Constants;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.configuration.Settings;
-import org.apache.log.LogTarget;
/**
* This is the core Cocoon component.
@@ -48,6 +43,7 @@
public class Core
implements Contextualizable {
+ /** The key to lookup the component. */
public static String ROLE = Core.class.getName();
/** Application <code>Context</code> Key for the settings. Please don't
@@ -180,47 +176,6 @@
} catch (ContextException ce) {
throw new CascadingRuntimeException("Unable to get the settings
object from the context.", ce);
}
- }
-
- public static interface BootstrapEnvironment {
-
- void log(String message);
- void log(String message, Throwable error);
-
- InputStream getInputStream(String path);
-
- void configure(Settings settings);
- void configureLoggingContext(DefaultContext context);
-
- void configure(DefaultContext context);
-
- ClassLoader getInitClassLoader();
-
- org.apache.cocoon.environment.Context getEnvironmentContext();
-
- /**
- * Returns the URL to the application context.
- */
- String getContextURL();
-
- /**
- * Returns a file to the application context.
- * @return A file pointing to the context or null if the context is not
- * writeable.
- */
- File getContextForWriting();
-
- LogTarget getDefaultLogTarget();
-
- /**
- * Set the ConfigFile for the Cocoon object.
- *
- * @param configFileName The file location for the cocoon.xconf
- *
- * @throws Exception
- */
- public URL getConfigFile(final Logger logger, final String
configFileName)
- throws Exception;
}
}
Modified: cocoon/trunk/src/java/org/apache/cocoon/core/CoreUtil.java
URL:
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/core/CoreUtil.java?view=diff&r1=160588&r2=160589
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/core/CoreUtil.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/core/CoreUtil.java Fri Apr 8
12:17:34 2005
@@ -32,6 +32,7 @@
import org.apache.avalon.excalibur.logger.LogKitLoggerManager;
import org.apache.avalon.excalibur.logger.LoggerManager;
import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
@@ -43,14 +44,15 @@
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.Cocoon;
import org.apache.cocoon.Constants;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.configuration.ConfigurationBuilder;
import org.apache.cocoon.configuration.Settings;
-import org.apache.cocoon.core.Core.BootstrapEnvironment;
import org.apache.cocoon.core.source.SimpleSourceResolver;
import org.apache.cocoon.matching.helpers.WildcardHelper;
import org.apache.cocoon.util.ClassUtils;
+import org.apache.cocoon.util.StringUtils;
import org.apache.cocoon.util.log.Log4JConfigurator;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.TraversableSource;
@@ -61,6 +63,7 @@
import org.apache.log4j.LogManager;
/**
+ * This is an utility class to create a new Cocoon instance.
*
* @version SVN $Id$
* @since 2.2
@@ -73,7 +76,7 @@
protected final static String CORE_KEY = Core.class.getName();
/** The callback to the real environment */
- protected final Core.BootstrapEnvironment env;
+ protected final BootstrapEnvironment env;
/** "legacy" support: create an avalon context */
protected final DefaultContext appContext = new DefaultContext();
@@ -81,28 +84,29 @@
/** The settings */
protected final Settings settings;
- /** The parent service manager TODO This will be made protected*/
- public ServiceManager parentManager;
+ /** The parent service manager. */
+ protected ServiceManager parentManager;
- /** TODO This will be made protected */
- public Logger log;
- /** TODO This will be made protected */
- public LoggerManager loggerManager;
+ /** The root logger. */
+ protected Logger log;
- /** TODO This will be made protected */
- public Object cocoon;
+ /** The logger manager. */
+ protected LoggerManager loggerManager;
+
+ /** The Cocoon instance (the root processor). */
+ protected Cocoon cocoon;
/**
* The time the cocoon instance was created
*/
protected long creationTime;
- public CoreUtil(Core.BootstrapEnvironment environment)
+ public CoreUtil(BootstrapEnvironment environment)
throws Exception {
this.env = environment;
// create settings
- this.settings = createSettings(this.env);
+ this.settings = this.createSettings();
this.appContext.put(Core.CONTEXT_SETTINGS, this.settings);
if (this.settings.isInitClassloader()) {
@@ -157,7 +161,8 @@
this.settings.setWorkDirectory(workDir.getAbsolutePath());
// Init logger
- initLogger();
+ this.initLogger();
+ this.env.setLogger(this.log);
// Output some debug info
if (this.log.isDebugEnabled()) {
@@ -233,7 +238,7 @@
this.settings.setCacheDirectory(cacheDir.getAbsolutePath());
// update settings
- final URL u = this.env.getConfigFile(this.log,
this.settings.getConfiguration());
+ final URL u = this.env.getConfigFile(this.settings.getConfiguration());
this.settings.setConfiguration(u.toExternalForm());
this.appContext.put(Constants.CONTEXT_CONFIG_URL, u);
@@ -305,9 +310,8 @@
/**
* Get the settings for Cocoon
* @param env This provides access to various parts of the used
environment.
- * TODO Make a non-static, protected method out of this
*/
- public static Settings createSettings(BootstrapEnvironment env) {
+ protected Settings createSettings() {
// create an empty settings objects
final Settings s = new Settings();
@@ -551,7 +555,8 @@
return WildcardHelper.match(null, uri, parsedPattern);
}
- public static final class RootServiceManager implements ServiceManager {
+ public static final class RootServiceManager
+ implements ServiceManager, Disposable {
protected final ServiceManager parent;
protected final Core cocoon;
@@ -561,7 +566,7 @@
this.cocoon = c;
}
- /* (non-Javadoc)
+ /**
* @see
org.apache.avalon.framework.service.ServiceManager#hasService(java.lang.String)
*/
public boolean hasService(String key) {
@@ -574,7 +579,7 @@
return false;
}
- /* (non-Javadoc)
+ /**
* @see
org.apache.avalon.framework.service.ServiceManager#lookup(java.lang.String)
*/
public Object lookup(String key) throws ServiceException {
@@ -587,7 +592,7 @@
throw new ServiceException("Cocoon", "Component for key '" + key +
"' not found.");
}
- /* (non-Javadoc)
+ /**
* @see
org.apache.avalon.framework.service.ServiceManager#release(java.lang.Object)
*/
public void release(Object component) {
@@ -595,12 +600,19 @@
this.parent.release(component);
}
}
+
+ /**
+ * @see org.apache.avalon.framework.activity.Disposable#dispose()
+ */
+ public void dispose() {
+ ContainerUtil.dispose(this.parent);
+ }
}
/**
* Creates the Cocoon object and handles exception handling.
*/
- public synchronized void createCocoon()
+ public synchronized Cocoon createCocoon()
throws Exception {
/* HACK for reducing class loader problems.
*/
@@ -621,9 +633,9 @@
if (this.log.isInfoEnabled()) {
this.log.info("Reloading from: " +
this.settings.getConfiguration());
}
- Object c = ClassUtils.newInstance("org.apache.cocoon.Cocoon");
+ Cocoon c =
(Cocoon)ClassUtils.newInstance("org.apache.cocoon.Cocoon");
ContainerUtil.enableLogging(c, getCocoonLogger());
- // TODO: c.setLoggerManager(this.loggerManager);
+ c.setLoggerManager(this.loggerManager);
ContainerUtil.contextualize(c, this.appContext);
// create the Core object
@@ -634,27 +646,26 @@
ContainerUtil.initialize(c);
this.creationTime = System.currentTimeMillis();
- disposeCocoon();
this.cocoon = c;
} catch (Exception e) {
this.log.error("Exception reloading", e);
this.disposeCocoon();
throw e;
}
+ return this.cocoon;
}
/**
* Gets the current cocoon object. Reload cocoon if configuration
* changed or we are reloading.
*/
- public void getCocoon(final String pathInfo, final String reloadParam)
+ public Cocoon getCocoon(final String pathInfo, final String reloadParam)
throws Exception {
if (this.settings.isAllowReload()) {
boolean reload = false;
if (this.cocoon != null) {
- // TODO: activate
-/* if (this.cocoon.modifiedSince(this.creationTime)) {
+ if (this.cocoon.modifiedSince(this.creationTime)) {
if (this.log.isInfoEnabled()) {
this.log.info("Configuration changed reload attempt");
}
@@ -664,7 +675,7 @@
this.log.info("Forced reload attempt");
}
reload = true;
- } */
+ }
} else if (pathInfo == null && reloadParam != null) {
if (this.log.isInfoEnabled()) {
this.log.info("Invalid configurations reload");
@@ -677,6 +688,7 @@
this.createCocoon();
}
}
+ return this.cocoon;
}
/**
@@ -684,6 +696,9 @@
*/
public final void disposeCocoon() {
if (this.cocoon != null) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Disposing Cocoon");
+ }
ContainerUtil.dispose(this.cocoon);
this.cocoon = null;
}
@@ -766,7 +781,10 @@
* of this class (eg. Cocoon Context).
*/
protected void updateEnvironment() throws Exception {
- // can be overridden
+ StringBuffer buffer = new
StringBuffer(this.env.getClassPath(this.settings));
+ buffer.append(File.pathSeparatorChar).append(this.getExtraClassPath());
+
+ this.appContext.put(Constants.CONTEXT_CLASSPATH, buffer.toString());
}
/**
@@ -780,13 +798,58 @@
// ignore this
}
}
+ this.disposeCocoon();
+ }
- if (this.cocoon != null) {
- if (this.log.isDebugEnabled()) {
- this.log.debug("Servlet destroyed - disposing Cocoon");
+ /**
+ * Retreives the "extra-classpath" attribute, that needs to be
+ * added to the class path.
+ */
+ protected String getExtraClassPath() {
+ if (this.settings.getExtraClasspaths().size() > 0) {
+ StringBuffer sb = new StringBuffer();
+ final Iterator iter =
this.settings.getExtraClasspaths().iterator();
+ int i = 0;
+ while (iter.hasNext()) {
+ String s = (String)iter.next();
+ if (i++ > 0) {
+ sb.append(File.pathSeparatorChar);
+ }
+ if ((s.charAt(0) == File.separatorChar) ||
+ (s.charAt(1) == ':')) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("extraClassPath is absolute: " + s);
+ }
+ sb.append(s);
+
+ } else {
+ if (s.indexOf("${") != -1) {
+ String path = StringUtils.replaceToken(s);
+ sb.append(path);
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("extraClassPath is not absolute
replacing using token: [" + s + "] : " + path);
+ }
+ } else {
+ String path = null;
+ if (this.env.getContextForWriting() != null) {
+ path = this.env.getContextForWriting() + s;
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("extraClassPath is not absolute
pre-pending context path: " + path);
+ }
+ } else {
+ path = this.settings.getWorkDirectory() + s;
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("extraClassPath is not absolute
pre-pending work-directory: " + path);
+ }
+ }
+ sb.append(path);
+ }
+ }
}
- this.disposeCocoon();
+ return sb.toString();
}
+ return "";
}
+
}
Modified: cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java
URL:
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java?view=diff&r1=160588&r2=160589
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java
(original)
+++ cocoon/trunk/src/java/org/apache/cocoon/servlet/CocoonServlet.java Fri Apr
8 12:17:34 2005
@@ -15,12 +15,33 @@
*/
package org.apache.cocoon.servlet;
-import org.apache.avalon.excalibur.logger.LoggerManager;
-import org.apache.avalon.framework.container.ContainerUtil;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.SocketException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.Logger;
-import org.apache.avalon.framework.service.ServiceManager;
-
import org.apache.cocoon.Cocoon;
import org.apache.cocoon.ConnectionResetException;
import org.apache.cocoon.Constants;
@@ -29,7 +50,7 @@
import org.apache.cocoon.components.notification.Notifier;
import org.apache.cocoon.components.notification.Notifying;
import org.apache.cocoon.configuration.Settings;
-import org.apache.cocoon.core.Core;
+import org.apache.cocoon.core.BootstrapEnvironment;
import org.apache.cocoon.core.CoreUtil;
import org.apache.cocoon.environment.Context;
import org.apache.cocoon.environment.Environment;
@@ -37,43 +58,13 @@
import org.apache.cocoon.environment.http.HttpEnvironment;
import org.apache.cocoon.servlet.multipart.MultipartHttpServletRequest;
import org.apache.cocoon.servlet.multipart.RequestFactory;
-import org.apache.cocoon.util.ClassUtils;
import org.apache.cocoon.util.IOUtils;
-import org.apache.cocoon.util.StringUtils;
import org.apache.cocoon.util.log.CocoonLogFormatter;
-
-import org.apache.cocoon.util.log.LoggingHelper;
import org.apache.commons.lang.SystemUtils;
import org.apache.log.ContextMap;
import org.apache.log.LogTarget;
import org.apache.log.output.ServletOutputLogTarget;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.net.SocketException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.StringTokenizer;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-
/**
* This is the entry point for Cocoon execution as an HTTP Servlet.
*
@@ -103,14 +94,6 @@
static final float MINUTE = 60 * SECOND;
static final float HOUR = 60 * MINUTE;
- private Logger log;
- private LoggerManager loggerManager;
-
- /**
- * The time the cocoon instance was created
- */
- protected long creationTime;
-
/**
* The <code>Cocoon</code> instance
*/
@@ -124,7 +107,7 @@
/**
* Avalon application context
*/
- protected DefaultContext appContext;
+ protected org.apache.avalon.framework.context.Context appContext;
private String containerEncoding;
@@ -133,9 +116,6 @@
/** The classloader that will be set as the context classloader if
init-classloader is true */
protected final ClassLoader classLoader = this.getClass().getClassLoader();
- /** The parent ServiceManager, if any. Stored here in order to be able to
dispose it in destroy(). */
- private ServiceManager parentServiceManager;
-
/**
* This is the path to the servlet context (or the result
* of calling getRealPath('/') on the ServletContext.
@@ -154,8 +134,11 @@
*/
protected RequestFactory requestFactory;
- /** Settings */
- protected Settings settings;
+ /** CoreUtil */
+ protected CoreUtil coreUtil;
+
+ /** The logger */
+ protected Logger log;
/**
* Initialize this <code>CocoonServlet</code> instance. You will
@@ -224,15 +207,12 @@
}
// initialize settings
- Core.BootstrapEnvironment env = new ServletBootstrapEnvironment(conf,
this.classLoader, this.servletContextPath, this.servletContextURL);
+ ServletBootstrapEnvironment env = new
ServletBootstrapEnvironment(conf, this.classLoader, this.servletContextPath,
this.servletContextURL);
try {
- CoreUtil util = new CoreUtil(env);
- this.settings = util.getCore().getSettings();
- this.appContext = (DefaultContext)util.getCore().getContext();
- this.log = util.log;
- this.loggerManager = util.loggerManager;
- this.parentServiceManager = util.parentManager;
+ this.coreUtil = new CoreUtil(env);
+ this.appContext = coreUtil.getCore().getContext();
+ this.log = env.logger;
} catch (Exception e) {
if ( e instanceof ServletException ) {
throw (ServletException)e;
@@ -241,7 +221,7 @@
}
if (getLogger().isDebugEnabled()) {
- getLogger().debug(this.settings.toString());
+
getLogger().debug(this.coreUtil.getCore().getSettings().toString());
getLogger().debug("getRealPath for /: " + this.servletContextPath);
if (this.servletContextPath == null) {
getLogger().debug("getResource for /WEB-INF: " + debugPathOne);
@@ -250,14 +230,19 @@
}
this.containerEncoding = getInitParameter("container-encoding",
"ISO-8859-1");
- this.requestFactory = new RequestFactory(settings.isAutosaveUploads(),
- new
File(settings.getUploadDirectory()),
- settings.isAllowOverwrite(),
- settings.isSilentlyRename(),
- settings.getMaxUploadSize(),
+ this.requestFactory = new
RequestFactory(coreUtil.getCore().getSettings().isAutosaveUploads(),
+ new
File(coreUtil.getCore().getSettings().getUploadDirectory()),
+
coreUtil.getCore().getSettings().isAllowOverwrite(),
+
coreUtil.getCore().getSettings().isSilentlyRename(),
+
coreUtil.getCore().getSettings().getMaxUploadSize(),
this.containerEncoding);
- createCocoon();
+ try {
+ this.exception = null;
+ this.cocoon = this.coreUtil.createCocoon();
+ } catch (Exception e) {
+ this.exception = e;
+ }
if (this.exception == null) {
this.servletContext.log("Apache Cocoon " + Constants.VERSION + "
is up and ready.");
} else {
@@ -269,318 +254,12 @@
* Dispose Cocoon when servlet is destroyed
*/
public void destroy() {
- if (this.settings.isInitClassloader()) {
- try {
- Thread.currentThread().setContextClassLoader(this.classLoader);
- } catch (Exception e) {
- // ignore this
- }
- }
-
- if (this.cocoon != null) {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("Servlet destroyed - disposing Cocoon");
- }
- disposeCocoon();
- }
-
- ContainerUtil.dispose(this.parentServiceManager);
- }
-
- /**
- * This builds the important ClassPath used by this Servlet. It
- * does so in a Servlet Engine neutral way. It uses the
- * <code>ServletContext</code>'s <code>getRealPath</code> method
- * to get the Servlet 2.2 identified classes and lib directories.
- * It iterates in alphabetical order through every file in the
- * lib directory and adds it to the classpath.
- *
- * Also, we add the files to the ClassLoader for the Cocoon system.
- * In order to protect ourselves from skitzofrantic classloaders,
- * we need to work with a known one.
- *
- * We need to get this to work properly when Cocoon is in a war.
- *
- * @throws ServletException
- */
- protected String getClassPath() throws ServletException {
- StringBuffer buildClassPath = new StringBuffer();
-
- File root = null;
- if (this.servletContextPath != null) {
- // Old method. There *MUST* be a better method than this...
-
- String classDir =
this.servletContext.getRealPath("/WEB-INF/classes");
- String libDir = this.servletContext.getRealPath("/WEB-INF/lib");
-
- if (libDir != null) {
- root = new File(libDir);
- }
-
- if (classDir != null) {
- buildClassPath.append(classDir);
- }
- } else {
- // New(ish) method for war'd deployments
- URL classDirURL = null;
- URL libDirURL = null;
-
- try {
- classDirURL =
this.servletContext.getResource("/WEB-INF/classes");
- } catch (MalformedURLException me) {
- getLogger().warn("Unable to add WEB-INF/classes to the
classpath", me);
- }
-
- try {
- libDirURL = this.servletContext.getResource("/WEB-INF/lib");
- } catch (MalformedURLException me) {
- getLogger().warn("Unable to add WEB-INF/lib to the classpath",
me);
- }
-
- if (libDirURL != null &&
libDirURL.toExternalForm().startsWith("file:")) {
- root = new
File(libDirURL.toExternalForm().substring("file:".length()));
- }
-
- if (classDirURL != null) {
- buildClassPath.append(classDirURL.toExternalForm());
- }
- }
-
- // Unable to find lib directory. Going the hard way.
- if (root == null) {
- root = extractLibraries();
- }
-
- if (root != null && root.isDirectory()) {
- File[] libraries = root.listFiles();
- Arrays.sort(libraries);
- for (int i = 0; i < libraries.length; i++) {
- String fullName = IOUtils.getFullFilename(libraries[i]);
- buildClassPath.append(File.pathSeparatorChar).append(fullName);
- }
- }
-
- buildClassPath.append(File.pathSeparatorChar)
- .append(SystemUtils.JAVA_CLASS_PATH);
-
- buildClassPath.append(File.pathSeparatorChar)
- .append(getExtraClassPath());
- return buildClassPath.toString();
- }
-
- private File extractLibraries() {
- try {
- URL manifestURL =
this.servletContext.getResource("/META-INF/MANIFEST.MF");
- if (manifestURL == null) {
- this.getLogger().fatalError("Unable to get Manifest");
- return null;
- }
-
- Manifest mf = new Manifest(manifestURL.openStream());
- Attributes attr = mf.getMainAttributes();
- String libValue = attr.getValue("Cocoon-Libs");
- if (libValue == null) {
- this.getLogger().fatalError("Unable to get 'Cocoon-Libs'
attribute from the Manifest");
- return null;
- }
-
- List libList = new ArrayList();
- for (StringTokenizer st = new StringTokenizer(libValue, " ");
st.hasMoreTokens();) {
- libList.add(st.nextToken());
- }
-
- File root = new File(this.settings.getWorkDirectory(), "lib");
- root.mkdirs();
-
- File[] oldLibs = root.listFiles();
- for (int i = 0; i < oldLibs.length; i++) {
- String oldLib = oldLibs[i].getName();
- if (!libList.contains(oldLib)) {
- this.getLogger().debug("Removing old library " +
oldLibs[i]);
- oldLibs[i].delete();
- }
- }
-
- this.getLogger().warn("Extracting libraries into " + root);
- byte[] buffer = new byte[65536];
- for (Iterator i = libList.iterator(); i.hasNext();) {
- String libName = (String) i.next();
-
- long lastModified = -1;
- try {
- lastModified = Long.parseLong(attr.getValue("Cocoon-Lib-"
+ libName.replace('.', '_')));
- } catch (Exception e) {
- this.getLogger().debug("Failed to parse lastModified: " +
attr.getValue("Cocoon-Lib-" + libName.replace('.', '_')));
- }
-
- File lib = new File(root, libName);
- if (lib.exists() && lib.lastModified() != lastModified) {
- this.getLogger().debug("Removing modified library " + lib);
- lib.delete();
- }
-
- InputStream is =
this.servletContext.getResourceAsStream("/WEB-INF/lib/" + libName);
- if (is == null) {
- this.getLogger().warn("Skipping " + libName);
- } else {
- this.getLogger().debug("Extracting " + libName);
- OutputStream os = null;
- try {
- os = new FileOutputStream(lib);
- int count;
- while ((count = is.read(buffer)) > 0) {
- os.write(buffer, 0, count);
- }
- } finally {
- if (is != null) is.close();
- if (os != null) os.close();
- }
- }
-
- if (lastModified != -1) {
- lib.setLastModified(lastModified);
- }
- }
-
- return root;
- } catch (IOException e) {
- this.getLogger().fatalError("Exception while processing Manifest
file", e);
- return null;
- }
- }
-
-
- /**
- * Retreives the "extra-classpath" attribute, that needs to be
- * added to the class path.
- *
- * @throws ServletException
- */
- protected String getExtraClassPath() throws ServletException {
- if (this.settings.getExtraClasspaths().size() > 0) {
- StringBuffer sb = new StringBuffer();
- final Iterator iter =
this.settings.getExtraClasspaths().iterator();
- int i = 0;
- while (iter.hasNext()) {
- String s = (String)iter.next();
- if (i++ > 0) {
- sb.append(File.pathSeparatorChar);
- }
- if ((s.charAt(0) == File.separatorChar) ||
- (s.charAt(1) == ':')) {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("extraClassPath is absolute: " + s);
- }
- sb.append(s);
-
- } else {
- if (s.indexOf("${") != -1) {
- String path = StringUtils.replaceToken(s);
- sb.append(path);
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("extraClassPath is not absolute
replacing using token: [" + s + "] : " + path);
- }
- } else {
- String path = null;
- if (this.servletContextPath != null) {
- path = this.servletContextPath + s;
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("extraClassPath is not
absolute pre-pending context path: " + path);
- }
- } else {
- path = this.settings.getWorkDirectory() + s;
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("extraClassPath is not
absolute pre-pending work-directory: " + path);
- }
- }
- sb.append(path);
- }
- }
- }
- return sb.toString();
- }
- return "";
- }
-
- protected void initLogger() {
- final CocoonLogFormatter formatter = new CocoonLogFormatter();
- formatter.setFormat("%7.7{priority} %{time} [%8.8{category}] " +
- "(%{uri}) %{thread}/%{class:short}:
%{message}\\n%{throwable}");
- final ServletOutputLogTarget servTarget = new
ServletOutputLogTarget(this.servletContext, formatter);
-
- final DefaultContext subcontext = new DefaultContext(this.appContext);
- subcontext.put("servlet-context", this.servletContext);
- subcontext.put("context-work", new
File(this.settings.getWorkDirectory()));
- if (this.servletContextPath == null) {
- File logSCDir = new File(this.settings.getWorkDirectory(), "log");
- logSCDir.mkdirs();
- subcontext.put("context-root", logSCDir.toString());
- } else {
- subcontext.put("context-root", this.servletContextPath);
- }
-
- LoggingHelper lh = new LoggingHelper(this.settings, servTarget,
subcontext);
- this.loggerManager = lh.getLoggerManager();
- this.log = lh.getLogger();
- }
-
- /**
- * Handle the <code>load-class</code> parameter. This overcomes
- * limits in many classpath issues. One of the more notorious
- * ones is a bug in WebSphere that does not load the URL handler
- * for the <code>classloader://</code> protocol. In order to
- * overcome that bug, set <code>load-class</code> parameter to
- * the <code>com.ibm.servlet.classloader.Handler</code> value.
- *
- * <p>If you need to load more than one class, then separate each
- * entry with whitespace, a comma, or a semi-colon. Cocoon will
- * strip any whitespace from the entry.</p>
- */
- private void forceLoad() {
- final Iterator i = this.settings.getLoadClasses();
- while (i.hasNext()) {
- final String fqcn = (String)i.next();
- try {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("Loading: " + fqcn);
- }
- ClassUtils.loadClass(fqcn).newInstance();
- } catch (Exception e) {
- if (getLogger().isWarnEnabled()) {
- getLogger().warn("Could not load class: " + fqcn, e);
- }
- // Do not throw an exception, because it is not a fatal error.
- }
- }
- }
-
- /**
- * Handle the "force-property" parameter.
- *
- * If you need to force more than one property to load, then
- * separate each entry with whitespace, a comma, or a semi-colon.
- * Cocoon will strip any whitespace from the entry.
- */
- private void forceProperty() {
- if (this.settings.getForceProperties().size() > 0) {
- Properties systemProps = System.getProperties();
- final Iterator i =
this.settings.getForceProperties().entrySet().iterator();
- while (i.hasNext()) {
- final Map.Entry current = (Map.Entry)i.next();
- try {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("Setting: " + current.getKey() + "="
+ current.getValue());
- }
- systemProps.setProperty(current.getKey().toString(),
current.getValue().toString());
- } catch (Exception e) {
- if (getLogger().isWarnEnabled()) {
- getLogger().warn("Could not set property: " +
current.getKey(), e);
- }
- // Do not throw an exception, because it is not a fatal
error.
- }
- }
- System.setProperties(systemProps);
+ this.servletContext.log("Destroying Cocoon Servlet.");
+ if ( this.coreUtil != null ) {
+ this.coreUtil.destroy();
+ this.coreUtil = null;
}
+ super.destroy();
}
/**
@@ -592,7 +271,7 @@
/* HACK for reducing class loader problems.
*/
/* example: xalan extensions fail if someone adds xalan jars in
tomcat3.2.1/lib */
- if (this.settings.isInitClassloader()) {
+ if (this.coreUtil.getCore().getSettings().isInitClassloader()) {
try {
Thread.currentThread().setContextClassLoader(this.classLoader);
} catch (Exception e) {
@@ -609,7 +288,7 @@
// get the request (wrapped if contains multipart-form data)
HttpServletRequest request;
try{
- if (this.settings.isEnableUploads()) {
+ if (this.coreUtil.getCore().getSettings().isEnableUploads()) {
request = requestFactory.getServletRequest(req);
} else {
request = req;
@@ -626,7 +305,12 @@
}
// Get the cocoon engine instance
- getCocoon(request.getPathInfo(),
request.getParameter(Constants.RELOAD_PARAM));
+ try {
+ this.exception = null;
+ this.cocoon = this.coreUtil.getCocoon(request.getPathInfo(),
request.getParameter(Constants.RELOAD_PARAM));
+ } catch (Exception e) {
+ this.exception = e;
+ }
// Check if cocoon was initialized
if (this.cocoon == null) {
@@ -766,7 +450,7 @@
if (contentType != null && contentType.equals("text/html")) {
String showTime =
request.getParameter(Constants.SHOWTIME_PARAM);
- boolean show = this.settings.isShowTime();
+ boolean show =
this.coreUtil.getCore().getSettings().isShowTime();
if (showTime != null) {
show = !showTime.equalsIgnoreCase("no");
}
@@ -774,7 +458,7 @@
if ( timeString == null ) {
timeString = processTime(end - start);
}
- boolean hide = this.settings.isHideShowTime();
+ boolean hide =
this.coreUtil.getCore().getSettings().isHideShowTime();
if (showTime != null) {
hide = showTime.equalsIgnoreCase("hide");
}
@@ -826,7 +510,7 @@
String title, String message, String
description,
Exception e)
throws IOException {
- if (this.settings.isManageExceptions()) {
+ if (this.coreUtil.getCore().getSettings().isManageExceptions()) {
if (env != null) {
env.tryResetResponse();
} else {
@@ -884,7 +568,7 @@
String formEncoding = req.getParameter("cocoon-form-encoding");
if (formEncoding == null) {
- formEncoding = this.settings.getFormEncoding();
+ formEncoding =
this.coreUtil.getCore().getSettings().getFormEncoding();
}
env = new HttpEnvironment(uri,
this.servletContextURL,
@@ -898,102 +582,6 @@
return env;
}
- /**
- * Instatiates the parent service manager, as specified in the
- * parent-service-manager init parameter.
- *
- * If none is specified, the method returns <code>null</code>.
- *
- * @return the parent service manager, or <code>null</code>.
- */
- protected synchronized ServiceManager getParentServiceManager() {
- // FIXME - move this to CoreUtil!
-/* ContainerUtil.dispose(this.parentServiceManager);
-
- this.parentServiceManager = null;
- if (parentServiceManagerClass != null) {
- try {
- Class pcm = ClassUtils.loadClass(parentServiceManagerClass);
- Constructor pcmc = pcm.getConstructor(new
Class[]{String.class});
- parentServiceManager = (ServiceManager) pcmc.newInstance(new
Object[]{parentServiceManagerInitParam});
-
- ContainerUtil.enableLogging(parentServiceManager, getLogger());
- ContainerUtil.contextualize(parentServiceManager,
this.appContext);
- ContainerUtil.initialize(parentServiceManager);
- } catch (Exception e) {
- if (getLogger().isErrorEnabled()) {
- getLogger().error("Could not initialize parent component
manager.", e);
- }
- }
- }*/
- return parentServiceManager;
- }
-
- /**
- * Creates the Cocoon object and handles exception handling.
- */
- private synchronized void createCocoon()
- throws ServletException {
-
- /* HACK for reducing class loader problems.
*/
- /* example: xalan extensions fail if someone adds xalan jars in
tomcat3.2.1/lib */
- if (this.settings.isInitClassloader()) {
- try {
- Thread.currentThread().setContextClassLoader(this.classLoader);
- } catch (Exception e) {
- // ignore
- }
- }
-
- updateEnvironment();
- forceLoad();
- forceProperty();
-
- try {
- this.exception = null;
- if (getLogger().isInfoEnabled()) {
- getLogger().info("Reloading from: " +
this.settings.getConfiguration());
- }
- Cocoon c = (Cocoon)
ClassUtils.newInstance("org.apache.cocoon.Cocoon");
- ContainerUtil.enableLogging(c, getCocoonLogger());
- c.setLoggerManager(getLoggerManager());
- ContainerUtil.contextualize(c, this.appContext);
- final ServiceManager parent = this.getParentServiceManager();
- if (parent != null) {
- ContainerUtil.service(c, parent);
- }
- ContainerUtil.initialize(c);
- this.creationTime = System.currentTimeMillis();
-
- disposeCocoon();
- this.cocoon = c;
- } catch (Exception e) {
- getLogger().error("Exception reloading", e);
- this.exception = e;
- disposeCocoon();
- }
- }
-
- private Logger getCocoonLogger() {
- final String rootlogger = this.settings.getCocoonLogger();
- if (rootlogger != null) {
- return this.getLoggerManager().getLoggerForCategory(rootlogger);
- }
- return getLogger();
- }
-
- /**
- * Method to update the environment before Cocoon instances are created.
- *
- * This is also useful if you wish to customize any of the 'protected'
- * variables from this class before a Cocoon instance is built in a
derivative
- * of this class (eg. Cocoon Context).
- */
- protected void updateEnvironment() throws ServletException {
- this.appContext.put(Constants.CONTEXT_CLASS_LOADER, classLoader);
- this.appContext.put(Constants.CONTEXT_CLASSPATH, getClassPath());
- }
-
private String processTime(long time) {
StringBuffer out = new StringBuffer(PROCESSED_BY);
if (time <= SECOND) {
@@ -1013,51 +601,6 @@
}
/**
- * Gets the current cocoon object. Reload cocoon if configuration
- * changed or we are reloading.
- */
- private void getCocoon(final String pathInfo, final String reloadParam)
- throws ServletException {
- if (this.settings.isAllowReload()) {
- boolean reload = false;
-
- if (this.cocoon != null) {
- if (this.cocoon.modifiedSince(this.creationTime)) {
- if (getLogger().isInfoEnabled()) {
- getLogger().info("Configuration changed reload
attempt");
- }
- reload = true;
- } else if (pathInfo == null && reloadParam != null) {
- if (getLogger().isInfoEnabled()) {
- getLogger().info("Forced reload attempt");
- }
- reload = true;
- }
- } else if (pathInfo == null && reloadParam != null) {
- if (getLogger().isInfoEnabled()) {
- getLogger().info("Invalid configurations reload");
- }
- reload = true;
- }
-
- if (reload) {
- initLogger();
- createCocoon();
- }
- }
- }
-
- /**
- * Destroy Cocoon
- */
- private final void disposeCocoon() {
- if (this.cocoon != null) {
- ContainerUtil.dispose(this.cocoon);
- this.cocoon = null;
- }
- }
-
- /**
* Get an initialisation parameter. The value is trimmed, and null is
returned if the trimmed value
* is empty.
*/
@@ -1089,17 +632,14 @@
return this.log;
}
- protected LoggerManager getLoggerManager() {
- return this.loggerManager;
- }
-
protected static final class ServletBootstrapEnvironment
- implements Core.BootstrapEnvironment {
+ implements BootstrapEnvironment {
private final ServletConfig config;
private final ClassLoader classLoader;
private final File writeableContextPath;
private final String contextPath;
+ public Logger logger;
public ServletBootstrapEnvironment(ServletConfig config,
ClassLoader cl,
@@ -1116,28 +656,35 @@
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#log(java.lang.String)
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#log(java.lang.String)
*/
public void log(String message) {
this.config.getServletContext().log(message);
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#log(java.lang.String,
java.lang.Throwable)
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#log(java.lang.String,
java.lang.Throwable)
*/
public void log(String message, Throwable error) {
this.config.getServletContext().log(message, error);
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#getInputStream(java.lang.String)
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#setLogger(org.apache.avalon.framework.logger.Logger)
+ */
+ public void setLogger(Logger rootLogger) {
+ this.logger = rootLogger;
+ }
+
+ /**
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#getInputStream(java.lang.String)
*/
public InputStream getInputStream(String path) {
return this.config.getServletContext().getResourceAsStream(path);
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#configure(org.apache.cocoon.configuration.Settings)
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#configure(org.apache.cocoon.configuration.Settings)
*/
public void configure(Settings settings) {
// fill from the servlet parameters
@@ -1149,21 +696,21 @@
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#getInitClassLoader()
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#getInitClassLoader()
*/
public ClassLoader getInitClassLoader() {
return this.classLoader;
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#getEnvironmentContext()
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#getEnvironmentContext()
*/
public Context getEnvironmentContext() {
return new HttpContext(this.config.getServletContext());
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#getContextURL()
+ * @see org.apache.cocoon.core.BootstrapEnvironment#getContextURL()
*/
public String getContextURL() {
return this.contextPath;
@@ -1171,13 +718,14 @@
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#getContextForWriting()
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#getContextForWriting()
*/
public File getContextForWriting() {
return this.writeableContextPath;
}
+
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#getDefaultLogTarget()
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#getDefaultLogTarget()
*/
public LogTarget getDefaultLogTarget() {
final CocoonLogFormatter formatter = new CocoonLogFormatter();
@@ -1188,41 +736,37 @@
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#configureLoggingContext(org.apache.avalon.framework.context.DefaultContext)
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#configureLoggingContext(org.apache.avalon.framework.context.DefaultContext)
*/
public void configureLoggingContext(DefaultContext context) {
context.put("servlet-context", this.config.getServletContext());
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#configure(org.apache.avalon.framework.context.DefaultContext)
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#configure(org.apache.avalon.framework.context.DefaultContext)
*/
public void configure(DefaultContext context) {
context.put(CONTEXT_SERVLET_CONFIG, this.config);
- // TODO - move the following into CoreUtil
- context.put(Constants.CONTEXT_CLASS_LOADER, classLoader);
- // TODO:
- //context.put(Constants.CONTEXT_CLASSPATH, getClassPath());
}
/**
- * @see
org.apache.cocoon.core.Core.BootstrapEnvironment#getConfigFile(org.apache.avalon.framework.logger.Logger,
java.lang.String)
+ * @see
org.apache.cocoon.core.BootstrapEnvironment#getConfigFile(java.lang.String)
*/
- public URL getConfigFile(final Logger logger, final String
configFileName)
+ public URL getConfigFile(final String configFileName)
throws Exception {
final String usedFileName;
if (configFileName == null) {
- if (logger.isWarnEnabled()) {
- logger.warn("Servlet initialization argument
'configurations' not specified, attempting to use '/WEB-INF/cocoon.xconf'");
+ if (this.logger.isWarnEnabled()) {
+ this.logger.warn("Servlet initialization argument
'configurations' not specified, attempting to use '/WEB-INF/cocoon.xconf'");
}
usedFileName = "/WEB-INF/cocoon.xconf";
} else {
usedFileName = configFileName;
}
- if (logger.isDebugEnabled()) {
- logger.debug("Using configuration file: " + usedFileName);
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug("Using configuration file: " + usedFileName);
}
URL result;
@@ -1235,7 +779,7 @@
}
} catch (Exception mue) {
String msg = "Init parameter 'configurations' is invalid : " +
usedFileName;
- logger.error(msg, mue);
+ this.logger.error(msg, mue);
throw new ServletException(msg, mue);
}
@@ -1246,7 +790,7 @@
result = resultFile.getCanonicalFile().toURL();
} catch (Exception e) {
String msg = "Init parameter 'configurations' is
invalid : " + usedFileName;
- logger.error(msg, e);
+ this.logger.error(msg, e);
throw new ServletException(msg, e);
}
}
@@ -1254,10 +798,170 @@
if (result == null) {
String msg = "Init parameter 'configuration' doesn't name an
existing resource : " + usedFileName;
- logger.error(msg);
+ this.logger.error(msg);
throw new ServletException(msg);
}
return result;
+ }
+
+ /**
+ * This builds the important ClassPath used by this Servlet. It
+ * does so in a Servlet Engine neutral way. It uses the
+ * <code>ServletContext</code>'s <code>getRealPath</code> method
+ * to get the Servlet 2.2 identified classes and lib directories.
+ * It iterates in alphabetical order through every file in the
+ * lib directory and adds it to the classpath.
+ *
+ * Also, we add the files to the ClassLoader for the Cocoon system.
+ * In order to protect ourselves from skitzofrantic classloaders,
+ * we need to work with a known one.
+ *
+ * We need to get this to work properly when Cocoon is in a war.
+ *
+ * @throws ServletException
+ */
+ public String getClassPath(Settings settings) {
+ StringBuffer buildClassPath = new StringBuffer();
+
+ File root = null;
+ if (this.getContextForWriting() != null) {
+ // Old method. There *MUST* be a better method than this...
+
+ String classDir =
this.config.getServletContext().getRealPath("/WEB-INF/classes");
+ String libDir =
this.config.getServletContext().getRealPath("/WEB-INF/lib");
+
+ if (libDir != null) {
+ root = new File(libDir);
+ }
+
+ if (classDir != null) {
+ buildClassPath.append(classDir);
+ }
+ } else {
+ // New(ish) method for war'd deployments
+ URL classDirURL = null;
+ URL libDirURL = null;
+
+ try {
+ classDirURL =
this.config.getServletContext().getResource("/WEB-INF/classes");
+ } catch (MalformedURLException me) {
+ this.logger.warn("Unable to add WEB-INF/classes to the
classpath", me);
+ }
+
+ try {
+ libDirURL =
this.config.getServletContext().getResource("/WEB-INF/lib");
+ } catch (MalformedURLException me) {
+ this.logger.warn("Unable to add WEB-INF/lib to the
classpath", me);
+ }
+
+ if (libDirURL != null &&
libDirURL.toExternalForm().startsWith("file:")) {
+ root = new
File(libDirURL.toExternalForm().substring("file:".length()));
+ }
+
+ if (classDirURL != null) {
+ buildClassPath.append(classDirURL.toExternalForm());
+ }
+ }
+
+ // Unable to find lib directory. Going the hard way.
+ if (root == null) {
+ root = this.extractLibraries(settings);
+ }
+
+ if (root != null && root.isDirectory()) {
+ File[] libraries = root.listFiles();
+ Arrays.sort(libraries);
+ for (int i = 0; i < libraries.length; i++) {
+ String fullName = IOUtils.getFullFilename(libraries[i]);
+
buildClassPath.append(File.pathSeparatorChar).append(fullName);
+ }
+ }
+
+ buildClassPath.append(File.pathSeparatorChar)
+ .append(SystemUtils.JAVA_CLASS_PATH);
+
+ return buildClassPath.toString();
+ }
+
+ private File extractLibraries(Settings settings) {
+ try {
+ URL manifestURL =
this.config.getServletContext().getResource("/META-INF/MANIFEST.MF");
+ if (manifestURL == null) {
+ this.logger.fatalError("Unable to get Manifest");
+ return null;
+ }
+
+ Manifest mf = new Manifest(manifestURL.openStream());
+ Attributes attr = mf.getMainAttributes();
+ String libValue = attr.getValue("Cocoon-Libs");
+ if (libValue == null) {
+ this.logger.fatalError("Unable to get 'Cocoon-Libs'
attribute from the Manifest");
+ return null;
+ }
+
+ List libList = new ArrayList();
+ for (StringTokenizer st = new StringTokenizer(libValue, " ");
st.hasMoreTokens();) {
+ libList.add(st.nextToken());
+ }
+
+ File root = new File(settings.getWorkDirectory(), "lib");
+ root.mkdirs();
+
+ File[] oldLibs = root.listFiles();
+ for (int i = 0; i < oldLibs.length; i++) {
+ String oldLib = oldLibs[i].getName();
+ if (!libList.contains(oldLib)) {
+ this.logger.debug("Removing old library " +
oldLibs[i]);
+ oldLibs[i].delete();
+ }
+ }
+
+ this.logger.warn("Extracting libraries into " + root);
+ byte[] buffer = new byte[65536];
+ for (Iterator i = libList.iterator(); i.hasNext();) {
+ String libName = (String) i.next();
+
+ long lastModified = -1;
+ try {
+ lastModified =
Long.parseLong(attr.getValue("Cocoon-Lib-" + libName.replace('.', '_')));
+ } catch (Exception e) {
+ this.logger.debug("Failed to parse lastModified: " +
attr.getValue("Cocoon-Lib-" + libName.replace('.', '_')));
+ }
+
+ File lib = new File(root, libName);
+ if (lib.exists() && lib.lastModified() != lastModified) {
+ this.logger.debug("Removing modified library " + lib);
+ lib.delete();
+ }
+
+ InputStream is =
this.config.getServletContext().getResourceAsStream("/WEB-INF/lib/" + libName);
+ if (is == null) {
+ this.logger.warn("Skipping " + libName);
+ } else {
+ this.logger.debug("Extracting " + libName);
+ OutputStream os = null;
+ try {
+ os = new FileOutputStream(lib);
+ int count;
+ while ((count = is.read(buffer)) > 0) {
+ os.write(buffer, 0, count);
+ }
+ } finally {
+ if (is != null) is.close();
+ if (os != null) os.close();
+ }
+ }
+
+ if (lastModified != -1) {
+ lib.setLastModified(lastModified);
+ }
+ }
+
+ return root;
+ } catch (IOException e) {
+ this.logger.fatalError("Exception while processing Manifest
file", e);
+ return null;
+ }
}
}