blob: a251bb1d9cbcd9e0b053226cc8e0a34f57c118d4 [file] [log] [blame]
/*
* Copyright 1999-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.servlet;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
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.excalibur.logger.ServletLogger;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.Logger;
import org.apache.cocoon.ConnectionResetException;
import org.apache.cocoon.Constants;
import org.apache.cocoon.Processor;
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.components.notification.DefaultNotifyingBuilder;
import org.apache.cocoon.components.notification.Notifier;
import org.apache.cocoon.components.notification.Notifying;
import org.apache.cocoon.core.BootstrapEnvironment;
import org.apache.cocoon.core.CoreUtil;
import org.apache.cocoon.core.MutableSettings;
import org.apache.cocoon.environment.Context;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.http.HttpContext;
import org.apache.cocoon.environment.http.HttpEnvironment;
import org.apache.cocoon.servlet.multipart.MultipartHttpServletRequest;
import org.apache.cocoon.servlet.multipart.RequestFactory;
import org.apache.commons.lang.time.StopWatch;
/**
* This is the entry point for Cocoon execution as an HTTP Servlet.
*
* @version $Id$
*/
public class CocoonServlet extends HttpServlet {
/**
* Application <code>Context</code> Key for the servlet configuration
* @since 2.1.3
*/
public static final String CONTEXT_SERVLET_CONFIG = "servlet-config";
// Processing time message
protected static final String PROCESSED_BY = "Processed by "
+ Constants.COMPLETE_NAME + " in ";
// Used by "show-time"
static final float SECOND = 1000;
static final float MINUTE = 60 * SECOND;
static final float HOUR = 60 * MINUTE;
/**
* The <code>Processor</code> instance
*/
protected Processor processor;
/**
* Holds exception happened during initialization (if any)
*/
protected Exception exception;
private String containerEncoding;
protected ServletContext servletContext;
/**
* This is the path to the servlet context (or the result
* of calling getRealPath('/') on the ServletContext.
* Note, that this can be null.
*/
protected String servletContextPath;
/**
* This is the url to the servlet context directory
*/
protected String servletContextURL;
/**
* The RequestFactory is responsible for wrapping multipart-encoded
* forms and for handing the file payload of incoming requests
*/
protected RequestFactory requestFactory;
/** CoreUtil */
protected CoreUtil coreUtil;
/** The logger */
protected Logger log;
protected Context environmentContext;
/**
* Initialize this <code>CocoonServlet</code> instance. You will
* notice that I have broken the init into sub methods to make it
* easier to maintain (BL). The context is passed to a couple of
* the subroutines. This is also because it is better to explicitly
* pass variables than implicitely. It is both more maintainable,
* and more elegant.
*
* @param conf The ServletConfig object from the servlet engine.
*
* @throws ServletException
*/
public void init(ServletConfig conf)
throws ServletException {
this.servletContext = conf.getServletContext();
this.servletContext.log("Initializing Apache Cocoon " + Constants.VERSION);
super.init(conf);
this.servletContextPath = this.servletContext.getRealPath("/");
String path = this.servletContextPath;
// these two variables are just for debugging. We can't log at this point
// as the logger isn't initialized yet.
String debugPathOne = null, debugPathTwo = null;
if (path == null) {
// Try to figure out the path of the root from that of WEB-INF/web.xml
try {
path = this.servletContext.getResource("/WEB-INF/web.xml").toString();
} catch (MalformedURLException me) {
throw new ServletException("Unable to get resource 'WEB-INF/web.xml'.", me);
}
debugPathOne = path;
path = path.substring(0, path.length() - "WEB-INF/web.xml".length());
debugPathTwo = path;
}
try {
if (path.indexOf(':') > 1) {
this.servletContextURL = path;
} else {
this.servletContextURL = new File(path).toURL().toExternalForm();
}
} catch (MalformedURLException me) {
// VG: Novell has absolute file names starting with the
// volume name which is easily more then one letter.
// Examples: sys:/apache/cocoon or sys:\apache\cocoon
try {
this.servletContextURL = new File(path).toURL().toExternalForm();
} catch (MalformedURLException ignored) {
throw new ServletException("Unable to determine servlet context URL.", me);
}
}
try {
// FIXME (VG): We shouldn't have to specify these. Need to override
// jaxp implementation of weblogic before initializing logger.
// This piece of code is also required in the Cocoon class.
String value = System.getProperty("javax.xml.parsers.SAXParserFactory");
if (value != null && value.startsWith("weblogic")) {
System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
}
} catch (Exception e) {
// Ignore security exception
this.servletContext.log("CocoonServlet: Could not check system properties, got: " + e);
}
// initialize settings
ServletBootstrapEnvironment env = new ServletBootstrapEnvironment(conf, this.servletContextPath, this.servletContextURL);
try {
this.coreUtil = new CoreUtil(env);
this.environmentContext = env.getEnvironmentContext();
this.log = env.logger;
} catch (Exception e) {
if ( e instanceof ServletException ) {
throw (ServletException)e;
}
throw new ServletException(e);
}
if (getLogger().isDebugEnabled()) {
getLogger().debug(this.coreUtil.getSettings().toString());
getLogger().debug("getRealPath for /: " + this.servletContextPath);
if (this.servletContextPath == null) {
getLogger().debug("getResource for /WEB-INF: " + debugPathOne);
getLogger().debug("Path for Root: " + debugPathTwo);
}
}
this.containerEncoding = this.getInitParameter("container-encoding", "ISO-8859-1");
this.requestFactory = new RequestFactory(coreUtil.getSettings().isAutosaveUploads(),
new File(coreUtil.getCore().getSettings().getUploadDirectory()),
coreUtil.getSettings().isAllowOverwrite(),
coreUtil.getSettings().isSilentlyRename(),
coreUtil.getSettings().getMaxUploadSize(),
this.containerEncoding);
try {
this.exception = null;
this.processor = this.coreUtil.createProcessor();
} catch (Exception e) {
this.exception = e;
}
if (this.exception == null) {
this.servletContext.log("Apache Cocoon " + Constants.VERSION + " is up and ready.");
} else {
final String message = "Errors during initializing Apache Cocoon " + Constants.VERSION + " : " + this.exception.getMessage();
this.servletContext.log(message, this.exception);
}
}
/**
* Dispose Cocoon when servlet is destroyed
*/
public void destroy() {
this.servletContext.log("Destroying Cocoon Servlet.");
if (this.coreUtil != null) {
this.coreUtil.destroy();
this.coreUtil = null;
// coreUtil will dispose it.
this.processor = null;
}
this.requestFactory = null;
this.servletContext = null;
this.environmentContext = null;
this.log = null;
super.destroy();
}
/**
* Process the specified <code>HttpServletRequest</code> producing output
* on the specified <code>HttpServletResponse</code>.
*/
public void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// used for timing the processing
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// add the cocoon header timestamp
if (this.coreUtil.getSettings().isShowVersion()) {
res.addHeader("X-Cocoon-Version", Constants.VERSION);
}
// get the request (wrapped if contains multipart-form data)
HttpServletRequest request;
try{
if (this.coreUtil.getSettings().isEnableUploads()) {
request = requestFactory.getServletRequest(req);
} else {
request = req;
}
} catch (Exception e) {
if (getLogger().isErrorEnabled()) {
getLogger().error("Problem with Cocoon servlet", e);
}
manageException(req, res, null, null,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Problem in creating the Request", null, null, e);
return;
}
// Get the cocoon engine instance
try {
this.exception = null;
this.processor = this.coreUtil.getProcessor(request.getPathInfo(), request.getParameter(Constants.RELOAD_PARAM));
} catch (Exception e) {
this.exception = e;
}
// Check if cocoon was initialized
if (this.processor == null) {
manageException(request, res, null, null,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Initialization Problem",
null /* "Cocoon was not initialized" */,
null /* "Cocoon was not initialized, cannot process request" */,
this.exception);
return;
}
// We got it... Process the request
String uri = request.getServletPath();
if (uri == null) {
uri = "";
}
String pathInfo = request.getPathInfo();
if (pathInfo != null) {
// VG: WebLogic fix: Both uri and pathInfo starts with '/'
// This problem exists only in WL6.1sp2, not in WL6.0sp2 or WL7.0b.
if (uri.length() > 0 && uri.charAt(0) == '/') {
uri = uri.substring(1);
}
uri += pathInfo;
}
if (uri.length() == 0) {
/* empty relative URI
-> HTTP-redirect from /cocoon to /cocoon/ to avoid
StringIndexOutOfBoundsException when calling
"".charAt(0)
else process URI normally
*/
String prefix = request.getRequestURI();
if (prefix == null) {
prefix = "";
}
res.sendRedirect(res.encodeRedirectURL(prefix + "/"));
return;
}
String contentType = null;
Object handle = null;
Environment env;
try{
if (uri.charAt(0) == '/') {
uri = uri.substring(1);
}
// Pass uri into environment without URLDecoding, as it is already decoded.
env = getEnvironment(uri, request, res);
} catch (Exception e) {
if (getLogger().isErrorEnabled()) {
getLogger().error("Problem with Cocoon servlet", e);
}
manageException(request, res, null, uri,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Problem in creating the Environment", null, null, e);
return;
}
try {
try {
handle = this.coreUtil.initializeRequest(env);
if (this.processor.process(env)) {
contentType = env.getContentType();
} else {
// We reach this when there is nothing in the processing change that matches
// the request. For example, no matcher matches.
getLogger().fatalError("The Cocoon engine failed to process the request.");
manageException(request, res, env, uri,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Request Processing Failed",
"Cocoon engine failed in process the request",
"The processing engine failed to process the request. This could be due to lack of matching or bugs in the pipeline engine.",
null);
return;
}
} catch (ResourceNotFoundException e) {
if (getLogger().isDebugEnabled()) {
getLogger().warn(e.getMessage(), e);
} else if (getLogger().isWarnEnabled()) {
getLogger().warn(e.getMessage());
}
manageException(request, res, env, uri,
HttpServletResponse.SC_NOT_FOUND,
"Resource Not Found",
"Resource Not Found",
"The requested resource \"" + request.getRequestURI() + "\" could not be found",
e);
return;
} catch (ConnectionResetException e) {
if (getLogger().isDebugEnabled()) {
getLogger().debug(e.toString(), e);
} else if (getLogger().isWarnEnabled()) {
getLogger().warn(e.toString());
}
} catch (IOException e) {
// Tomcat5 wraps SocketException into ClientAbortException which extends IOException.
if (getLogger().isDebugEnabled()) {
getLogger().debug(e.toString(), e);
} else if (getLogger().isWarnEnabled()) {
getLogger().warn(e.toString());
}
} catch (Exception e) {
if (getLogger().isErrorEnabled()) {
getLogger().error("Internal Cocoon Problem", e);
}
manageException(request, res, env, uri,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Internal Server Error", null, null, e);
return;
}
stopWatch.stop();
String timeString = null;
if (getLogger().isInfoEnabled()) {
timeString = processTime(stopWatch.getTime());
getLogger().info("'" + uri + "' " + timeString);
}
if (contentType != null && contentType.equals("text/html")) {
String showTime = request.getParameter(Constants.SHOWTIME_PARAM);
boolean show = this.coreUtil.getSettings().isShowTime();
if (showTime != null) {
show = !showTime.equalsIgnoreCase("no");
}
if (show) {
if ( timeString == null ) {
timeString = processTime(stopWatch.getTime());
}
boolean hide = this.coreUtil.getSettings().isHideShowTime();
if (showTime != null) {
hide = showTime.equalsIgnoreCase("hide");
}
ServletOutputStream out = res.getOutputStream();
out.print((hide) ? "<!-- " : "<p>");
out.print(timeString);
out.println((hide) ? " -->" : "</p>");
}
}
} finally {
this.coreUtil.cleanUpRequest(handle);
try {
if (request instanceof MultipartHttpServletRequest) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Deleting uploaded file(s).");
}
((MultipartHttpServletRequest) request).cleanup();
}
} catch (IOException e) {
getLogger().error("Cocoon got an Exception while trying to cleanup the uploaded files.", e);
}
/*
* Servlet Specification 2.2, 6.5 Closure of Response Object:
*
* A number of events can indicate that the servlet has provided all of the
* content to satisfy the request and that the response object can be
* considered to be closed. The events are:
* o The termination of the service method of the servlet.
* o When the amount of content specified in the setContentLength method
* of the response has been written to the response.
* o The sendError method is called.
* o The sendRedirect method is called.
* When a response is closed, all content in the response buffer, if any remains,
* must be immediately flushed to the client.
*
* Due to the above, out.flush() and out.close() are not necessary, and sometimes
* (if sendError or sendRedirect were used) request may be already closed.
*/
}
}
protected void manageException(HttpServletRequest req, HttpServletResponse res, Environment env,
String uri, int errorStatus,
String title, String message, String description,
Exception e)
throws IOException {
if (this.coreUtil.getSettings().isManageExceptions()) {
if (env != null) {
env.tryResetResponse();
} else {
res.reset();
}
String type = Notifying.FATAL_NOTIFICATION;
HashMap extraDescriptions = null;
if (errorStatus == HttpServletResponse.SC_NOT_FOUND) {
type = "resource-not-found";
// Do not show the exception stacktrace for such common errors.
e = null;
} else {
extraDescriptions = new HashMap(2);
extraDescriptions.put(Notifying.EXTRA_REQUESTURI, req.getRequestURI());
if (uri != null) {
extraDescriptions.put("Request URI", uri);
}
// Do not show exception stack trace when log level is WARN or above. Show only message.
if (!getLogger().isInfoEnabled()) {
Throwable t = DefaultNotifyingBuilder.getRootCause(e);
if (t != null) extraDescriptions.put(Notifying.EXTRA_CAUSE, t.getMessage());
e = null;
}
}
Notifying n = new DefaultNotifyingBuilder().build(this,
e,
type,
title,
"Cocoon Servlet",
message,
description,
extraDescriptions);
res.setContentType("text/html");
res.setStatus(errorStatus);
Notifier.notify(n, res.getOutputStream(), "text/html");
} else {
res.sendError(errorStatus, title);
res.flushBuffer();
}
}
/**
* Create the environment for the request
*/
protected Environment getEnvironment(String uri,
HttpServletRequest req,
HttpServletResponse res)
throws Exception {
HttpEnvironment env;
String formEncoding = req.getParameter("cocoon-form-encoding");
if (formEncoding == null) {
formEncoding = this.coreUtil.getSettings().getFormEncoding();
}
env = new HttpEnvironment(uri,
this.servletContextURL,
req,
res,
this.servletContext,
this.environmentContext,
this.containerEncoding,
formEncoding);
env.enableLogging(getLogger());
return env;
}
private String processTime(long time) {
StringBuffer out = new StringBuffer(PROCESSED_BY);
if (time <= SECOND) {
out.append(time);
out.append(" milliseconds.");
} else if (time <= MINUTE) {
out.append(time / SECOND);
out.append(" seconds.");
} else if (time <= HOUR) {
out.append(time / MINUTE);
out.append(" minutes.");
} else {
out.append(time / HOUR);
out.append(" hours.");
}
return out.toString();
}
/**
* Get an initialisation parameter. The value is trimmed, and null is returned if the trimmed value
* is empty.
*/
public String getInitParameter(String name) {
String result = super.getInitParameter(name);
if (result != null) {
result = result.trim();
if (result.length() == 0) {
result = null;
}
}
return result;
}
/** Convenience method to access servlet parameters */
protected String getInitParameter(String name, String defaultValue) {
String result = getInitParameter(name);
if (result == null) {
if (getLogger() != null && getLogger().isDebugEnabled()) {
getLogger().debug(name + " was not set - defaulting to '" + defaultValue + "'");
}
return defaultValue;
}
return result;
}
protected Logger getLogger() {
return this.log;
}
protected static final class ServletBootstrapEnvironment
implements BootstrapEnvironment {
private final ServletConfig config;
private final File writeableContextPath;
private final String contextPath;
public Logger logger;
private final HttpContext environmentContext;
public ServletBootstrapEnvironment(ServletConfig config,
String writeablePath,
String path) {
this.config = config;
if ( writeablePath == null ) {
this.writeableContextPath = null;
} else {
this.writeableContextPath = new File(writeablePath);
}
this.contextPath = path;
this.environmentContext = new HttpContext(this.config.getServletContext());
}
/**
* @see org.apache.cocoon.core.BootstrapEnvironment#getBootstrapLogger(org.apache.cocoon.core.BootstrapEnvironment.LogLevel)
*/
public Logger getBootstrapLogger(BootstrapEnvironment.LogLevel logLevel) {
return new ServletLogger(this.config, logLevel.getLevel());
}
/**
* @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.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.BootstrapEnvironment#setLogger(org.apache.avalon.framework.logger.Logger)
*/
public void setLogger(Logger rootLogger) {
this.logger = rootLogger;
}
/**
* @see org.apache.cocoon.core.BootstrapEnvironment#configure(org.apache.cocoon.core.MutableSettings)
*/
public void configure(MutableSettings settings) {
// fill from the servlet parameters
SettingsHelper.fill(settings, this.config);
if ( settings.getWorkDirectory() == null ) {
final File workDir = (File)this.config.getServletContext().getAttribute("javax.servlet.context.tempdir");
settings.setWorkDirectory(workDir.getAbsolutePath());
}
if ( settings.getLoggingConfiguration() == null ) {
settings.setLoggingConfiguration("/WEB-INF/logkit.xconf");
}
}
/**
* @see org.apache.cocoon.core.BootstrapEnvironment#getEnvironmentContext()
*/
public Context getEnvironmentContext() {
return this.environmentContext;
}
/**
* @see org.apache.cocoon.core.BootstrapEnvironment#getContextURL()
*/
public String getContextURL() {
return this.contextPath;
}
/**
* @see org.apache.cocoon.core.BootstrapEnvironment#getContextForWriting()
*/
public File getContextForWriting() {
return this.writeableContextPath;
}
/**
* @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.BootstrapEnvironment#configure(org.apache.avalon.framework.context.DefaultContext)
*/
public void configure(DefaultContext context) {
context.put(CONTEXT_SERVLET_CONFIG, this.config);
}
/**
* @see org.apache.cocoon.core.BootstrapEnvironment#getConfigFile(java.lang.String)
*/
public URL getConfigFile(final String configFileName)
throws Exception {
final String usedFileName;
if (configFileName == null) {
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 (this.logger.isDebugEnabled()) {
this.logger.debug("Using configuration file: " + usedFileName);
}
URL result;
try {
// test if this is a qualified url
if (usedFileName.indexOf(':') == -1) {
result = this.config.getServletContext().getResource(usedFileName);
} else {
result = new URL(usedFileName);
}
} catch (Exception mue) {
String msg = "Init parameter 'configurations' is invalid : " + usedFileName;
this.logger.error(msg, mue);
throw new ServletException(msg, mue);
}
if (result == null) {
File resultFile = new File(usedFileName);
if (resultFile.isFile()) {
try {
result = resultFile.getCanonicalFile().toURL();
} catch (Exception e) {
String msg = "Init parameter 'configurations' is invalid : " + usedFileName;
this.logger.error(msg, e);
throw new ServletException(msg, e);
}
}
}
if (result == null) {
String msg = "Init parameter 'configuration' doesn't name an existing resource : " + usedFileName;
this.logger.error(msg);
throw new ServletException(msg);
}
return result;
}
// (RP) comment this stuff out as it isn't used any more except in the StatusGenerator and I also think it returns wrong information
// under some circumstances.
// /**
// * 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.
// *
// */
// 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 = null;
// OutputStream os = null;
// try {
// is = this.servletContext.getResourceAsStream("/WEB-INF/lib/" + libName);
// if (is != null) {
// this.getLogger().debug("Extracting " + libName);
// os = new FileOutputStream(lib);
// int count;
// while ((count = is.read(buffer)) > 0) {
// os.write(buffer, 0, count);
// }
// } else {
// this.getLogger().warn("Skipping " + libName);
// }
// } finally {
// if (os != null) os.close();
// if (is != null) is.close();
// }
//
// if (lastModified != -1) {
// lib.setLastModified(lastModified);
// }
// }
//
// return root;
// } catch (IOException e) {
// this.logger.fatalError("Exception while processing Manifest file", e);
// return null;
// }
// }
//
}
}