You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by jh...@apache.org on 2005/11/03 15:00:48 UTC
svn commit: r330548 [53/132] - in
/cocoon/whiteboard/maven2/cocoon-flat-layout: ./ cocoon-ajax-block/
cocoon-ajax-block/api/ cocoon-ajax-block/api/src/
cocoon-ajax-block/api/src/main/ cocoon-ajax-block/api/src/main/java/
cocoon-ajax-block/api/src/main/...
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/CocoonServlet.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/CocoonServlet.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/CocoonServlet.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/CocoonServlet.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,925 @@
+/*
+ * 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.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.SocketException;
+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.Cocoon;
+import org.apache.cocoon.ConnectionResetException;
+import org.apache.cocoon.Constants;
+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.
+ *
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ * (Apache Software Foundation)
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @author <a href="mailto:nicolaken@apache.org">Nicola Ken Barozzi</a>
+ * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * @author <a href="mailto:leo.sutic@inspireinfrastructure.com">Leo Sutic</a>
+ * @version $Id: CocoonServlet.java 325955 2005-10-17 18:44:53Z vgritsenko $
+ */
+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>Cocoon</code> instance
+ */
+ protected Cocoon cocoon;
+
+ /**
+ * 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.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 {
+ 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.cocoon = 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.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) {
+ 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.cocoon.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 = 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;
+// }
+// }
+//
+ }
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/CocoonServlet.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/SettingsHelper.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/SettingsHelper.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/SettingsHelper.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/SettingsHelper.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,228 @@
+/*
+ * 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.servlet;
+
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletConfig;
+
+import org.apache.cocoon.core.MutableSettings;
+import org.apache.cocoon.util.StringUtils;
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang.SystemUtils;
+
+/**
+ * This helper class initializes the {@link MutableSettings} object from the servlet
+ * configuration.
+ *
+ * @version SVN $Id: SettingsHelper.java 312930 2005-10-11 18:13:35Z cziegeler $
+ */
+public class SettingsHelper {
+
+ private SettingsHelper() {
+ // no instantiation
+ }
+
+ public static void fill(MutableSettings s, ServletConfig config) {
+ String value;
+
+ handleForceProperty(getInitParameter(config, "force-property"), s);
+
+ value = getInitParameter(config, "configurations");
+ if ( value != null ) {
+ s.setConfiguration(value);
+ } else if ( s.getConfiguration() == null ) {
+ s.setConfiguration("/WEB-INF/cocoon.xconf");
+ }
+
+ // upto 2.1.x the logging configuration was named "logkit-config"
+ // we still support this, but provide a new unbiased name as well
+ value = getInitParameter(config, "logkit-config");
+ if ( value != null ) {
+ s.setLoggingConfiguration("context:/" + value);
+ } else {
+ value = getInitParameter(config, "logging-config");
+ if ( value != null ) {
+ s.setLoggingConfiguration("context:/" + value);
+ }
+ }
+
+ value = getInitParameter(config, "servlet-logger");
+ if ( value != null ) {
+ s.setEnvironmentLogger(value);
+ }
+
+ value = getInitParameter(config, "cocoon-logger");
+ if ( value != null ) {
+ s.setCocoonLogger(value);
+ }
+
+ value = getInitParameter(config, "log-level");
+ if ( value != null ) {
+ s.setBootstrapLogLevel(value);
+ }
+
+ value = getInitParameter(config, "logger-class");
+ if ( value != null ) {
+ s.setLoggerManagerClassName(value);
+ }
+
+ s.setReloadingEnabled(getInitParameterAsBoolean(config, "allow-reload", s.isReloadingEnabled(null)));
+
+ handleLoadClass(getInitParameter(config, "load-class"), s);
+
+ s.setEnableUploads(getInitParameterAsBoolean(config, "enable-uploads", s.isEnableUploads()));
+
+ value = getInitParameter(config, "upload-directory");
+ if ( value != null ) {
+ s.setUploadDirectory(value);
+ }
+
+ s.setAutosaveUploads(getInitParameterAsBoolean(config, "autosave-uploads", s.isAutosaveUploads()));
+
+ value = getInitParameter(config, "overwrite-uploads");
+ if ( value != null ) {
+ s.setOverwriteUploads(config.getInitParameter(value));
+ }
+
+ s.setMaxUploadSize(getInitParameterAsInteger(config, "upload-max-size", s.getMaxUploadSize()));
+
+ value = getInitParameter(config, "cache-directory");
+ if ( value != null ) {
+ s.setCacheDirectory(value);
+ }
+
+ value = getInitParameter(config, "work-directory");
+ if ( value != null ) {
+ s.setWorkDirectory(value);
+ }
+
+ handleExtraClassPath(config.getInitParameter("extra-classpath"), s);
+
+ value = getInitParameter(config, "parent-service-manager");
+ if ( value != null ) {
+ s.setParentServiceManagerClassName(value);
+ }
+
+ value = getInitParameter(config, "show-time");
+ if ( value != null && value.equalsIgnoreCase("hide") ) {
+ s.setShowTime(true);
+ s.setHideShowTime(true);
+ } else {
+ s.setShowTime(getInitParameterAsBoolean(config, "show-time", false));
+ s.setHideShowTime(false);
+ }
+
+ s.setShowCocoonVersion(getInitParameterAsBoolean(config, "show-cocoon-version", s.isShowVersion()));
+
+ s.setManageExceptions(getInitParameterAsBoolean(config, "manage-exceptions", s.isManageExceptions()));
+
+ value = getInitParameter(config, "form-encoding");
+ if ( value != null ) {
+ s.setFormEncoding(value);
+ }
+ }
+
+ /** Convenience method to access boolean servlet parameters */
+ protected static boolean getInitParameterAsBoolean(ServletConfig config, String name, boolean defaultValue) {
+ String value = getInitParameter(config, name);
+ if (value == null) {
+ return defaultValue;
+ }
+
+ return BooleanUtils.toBoolean(value);
+ }
+
+ protected static int getInitParameterAsInteger(ServletConfig config, String name, int defaultValue) {
+ String value = getInitParameter(config, name);
+ if (value == null) {
+ return defaultValue;
+ }
+ return Integer.parseInt(value);
+ }
+
+ private static void handleLoadClass(String param, MutableSettings s) {
+ if ( param == null ) {
+ return;
+ }
+ StringTokenizer tokenizer = new StringTokenizer(param, " \t\r\n\f;,", false);
+ while (tokenizer.hasMoreTokens()) {
+ final String value = tokenizer.nextToken().trim();
+ s.addToLoadClasses(value);
+ }
+ }
+
+ /**
+ * 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 static void handleForceProperty(String forceSystemProperty, MutableSettings s) {
+ if (forceSystemProperty != null) {
+ StringTokenizer tokenizer = new StringTokenizer(forceSystemProperty, " \t\r\n\f;,", false);
+
+ while (tokenizer.hasMoreTokens()) {
+ final String property = tokenizer.nextToken().trim();
+ if (property.indexOf('=') == -1) {
+ continue;
+ }
+ try {
+ String key = property.substring(0, property.indexOf('='));
+ String value = property.substring(property.indexOf('=') + 1);
+ if (value.indexOf("${") != -1) {
+ value = StringUtils.replaceToken(value);
+ }
+ s.addToForceProperties(key, value);
+ } catch (Exception e) {
+ // Do not throw an exception, because it is not a fatal error.
+ }
+ }
+ }
+ }
+
+ /**
+ * Retreives the "extra-classpath" attribute, that needs to be
+ * added to the class path.
+ */
+ private static void handleExtraClassPath(String extraClassPath, MutableSettings settings) {
+ if (extraClassPath != null) {
+ StringTokenizer st = new StringTokenizer(extraClassPath, SystemUtils.PATH_SEPARATOR, false);
+ while (st.hasMoreTokens()) {
+ String s = st.nextToken();
+ settings.addToExtraClasspaths(s);
+ }
+ }
+ }
+
+ /**
+ * Get an initialisation parameter. The value is trimmed, and null is returned if the trimmed value
+ * is empty.
+ */
+ private static String getInitParameter(ServletConfig config, String name) {
+ String result = config.getInitParameter(name);
+ if (result != null) {
+ result = result.trim();
+ if (result.length() == 0) {
+ result = null;
+ }
+ }
+
+ return result;
+ }
+
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/SettingsHelper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartException.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartException.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartException.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartException.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1999-2004 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.multipart;
+
+/**
+ * Exception thrown when on a parse error such as
+ * a malformed stream.
+ *
+ * @author <a href="mailto:j.tervoorde@home.nl">Jeroen ter Voorde</a>
+ * @version CVS $Id: MultipartException.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public class MultipartException extends Exception {
+
+ /**
+ * Constructor MultipartException
+ */
+ public MultipartException() {
+ super();
+ }
+
+ /**
+ * Constructor MultipartException
+ *
+ * @param text
+ */
+ public MultipartException(String text) {
+ super(text);
+ }
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartHttpServletRequest.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartHttpServletRequest.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartHttpServletRequest.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartHttpServletRequest.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,163 @@
+/*
+ * Copyright 1999-2004 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.multipart;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+/**
+ * Servlet request wrapper for multipart parser.
+ *
+ * @author <a href="mailto:j.tervoorde@home.nl">Jeroen ter Voorde</a>
+ * @author Stefano Mazzocchi
+ * @version CVS $Id: MultipartHttpServletRequest.java 179066 2005-05-30 14:43:29Z sylvain $
+ */
+public class MultipartHttpServletRequest extends HttpServletRequestWrapper {
+
+ /** The submitted parts */
+ private Hashtable values;
+
+ /**
+ * Create this wrapper around the given request and including the given
+ * parts.
+ */
+ public MultipartHttpServletRequest(HttpServletRequest request, Hashtable values) {
+ super(request);
+ this.values = values;
+ }
+
+ /**
+ * Cleanup eventually uploaded parts that were saved on disk
+ */
+ public void cleanup() throws IOException {
+ Enumeration e = getParameterNames();
+ while (e.hasMoreElements()) {
+ Object o = get( (String)e.nextElement() );
+ if (o instanceof Part) {
+ Part part = (Part)o;
+ if (part.disposeWithRequest()) {
+ part.dispose();
+ }
+ }
+ }
+ }
+
+ /**
+ * Method get
+ *
+ * @param name
+ *
+ */
+ public Object get(String name) {
+ Object result = null;
+
+ if (values != null) {
+ result = values.get(name);
+
+ if (result instanceof Vector) {
+ if (((Vector) result).size() == 1) {
+ return ((Vector) result).elementAt(0);
+ }
+ return result;
+ }
+ } else {
+ String[] array = this.getRequest().getParameterValues(name);
+ Vector vec = new Vector();
+
+ if (array != null) {
+ for (int i = 0; i < array.length; i++) {
+ vec.addElement(array[i]);
+ }
+
+ if (vec.size() == 1) {
+ result = vec.elementAt(0);
+ } else {
+ result = vec;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Method getParameterNames
+ *
+ */
+ public Enumeration getParameterNames() {
+ if (values != null) {
+ return values.keys();
+ }
+ return this.getRequest().getParameterNames();
+ }
+
+ /**
+ * Method getParameter
+ *
+ * @param name
+ *
+ */
+ public String getParameter(String name) {
+ if (values != null) {
+ Object value = get(name);
+ String result = null;
+
+ if (value != null) {
+ if (value instanceof Vector) {
+ value = ((Vector) value).elementAt(0);
+ }
+
+ result = value.toString();
+ }
+ return result;
+ } else {
+ return super.getParameter(name);
+ }
+ }
+
+ /**
+ * Method getParameterValues
+ *
+ * @param name
+ *
+ */
+ public String[] getParameterValues(String name) {
+ if (values != null) {
+ Object value = get(name);
+
+ if (value != null) {
+ if (value instanceof Vector) {
+ String[] results = new String[((Vector)value).size()];
+ for (int i=0;i<((Vector)value).size();i++) {
+ results[i] = ((Vector)value).elementAt(i).toString();
+ }
+ return results;
+
+ }
+ return new String[]{value.toString()};
+ }
+
+ return null;
+ }
+ return this.getRequest().getParameterValues(name);
+ }
+
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartHttpServletRequest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartParser.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartParser.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartParser.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartParser.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,393 @@
+/*
+ * Copyright 1999-2004 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.multipart;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PushbackInputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.cocoon.util.NullOutputStream;
+
+/**
+ * This class is used to implement a multipart request wrapper.
+ * It will parse the http post stream and and fill it's hashtable with values.
+ *
+ * The hashtable will contain:
+ * Vector: inline part values
+ * FilePart: file part
+ *
+ * @author <a href="mailto:j.tervoorde@home.nl">Jeroen ter Voorde</a>
+ * @version CVS $Id: MultipartParser.java 280948 2005-09-14 21:48:24Z sylvain $
+ */
+public class MultipartParser {
+
+ private final static int FILE_BUFFER_SIZE = 4096;
+
+ private static final int MAX_BOUNDARY_SIZE = 128;
+
+ private boolean saveUploadedFilesToDisk;
+
+ private File uploadDirectory = null;
+
+ private boolean allowOverwrite;
+
+ private boolean silentlyRename;
+
+ private int maxUploadSize;
+
+ private String characterEncoding;
+
+ private Hashtable parts;
+
+ private boolean oversized = false;
+
+ private int contentLength;
+
+ /**
+ * Constructor, parses given request
+ *
+ * @param saveUploadedFilesToDisk Write fileparts to the uploadDirectory. If true the corresponding object
+ * in the hashtable will contain a FilePartFile, if false a FilePartArray
+ * @param uploadDirectory The directory to write to if saveUploadedFilesToDisk is true.
+ * @param allowOverwrite Allow existing files to be overwritten.
+ * @param silentlyRename If file exists rename file (using filename+number).
+ * @param maxUploadSize The maximum content length accepted.
+ * @param characterEncoding The character encoding to be used.
+ */
+ public MultipartParser(boolean saveUploadedFilesToDisk,
+ File uploadDirectory,
+ boolean allowOverwrite,
+ boolean silentlyRename,
+ int maxUploadSize,
+ String characterEncoding)
+ {
+ this.saveUploadedFilesToDisk = saveUploadedFilesToDisk;
+ this.uploadDirectory = uploadDirectory;
+ this.allowOverwrite = allowOverwrite;
+ this.silentlyRename = silentlyRename;
+ this.maxUploadSize = maxUploadSize;
+ this.characterEncoding = characterEncoding;
+ }
+
+ private void parseParts(int contentLength, String contentType, InputStream requestStream)
+ throws IOException, MultipartException {
+ this.contentLength = contentLength;
+ if (contentLength > this.maxUploadSize) {
+ this.oversized = true;
+ }
+
+ BufferedInputStream bufferedStream = new BufferedInputStream(requestStream);
+ PushbackInputStream pushbackStream = new PushbackInputStream(bufferedStream, MAX_BOUNDARY_SIZE);
+ TokenStream stream = new TokenStream(pushbackStream);
+
+ parseMultiPart(stream, getBoundary(contentType));
+
+ }
+
+ public Hashtable getParts(int contentLength, String contentType, InputStream requestStream)
+ throws IOException, MultipartException {
+ this.parts = new Hashtable();
+ parseParts(contentLength, contentType, requestStream);
+ return this.parts;
+ }
+
+ public Hashtable getParts(HttpServletRequest request) throws IOException, MultipartException {
+ this.parts = new Hashtable();
+
+ // Copy all parameters coming from the request URI to the parts table.
+ // This happens when a form's action attribute has some parameters
+ Enumeration names = request.getParameterNames();
+ while(names.hasMoreElements()) {
+ String name = (String)names.nextElement();
+ String[] values = request.getParameterValues(name);
+ Vector v = new Vector(values.length);
+ for (int i = 0; i < values.length; i++) {
+ v.add(values[i]);
+ }
+ this.parts.put(name, v);
+ }
+ parseParts(request.getContentLength(), request.getContentType(), request.getInputStream());
+ return this.parts;
+ }
+
+ /**
+ * Parse a multipart block
+ *
+ * @param ts
+ * @param boundary
+ *
+ * @throws IOException
+ * @throws MultipartException
+ */
+ private void parseMultiPart(TokenStream ts, String boundary)
+ throws IOException, MultipartException {
+
+ ts.setBoundary(boundary.getBytes());
+ ts.read(); // read first boundary away
+ ts.setBoundary(("\r\n" + boundary).getBytes());
+
+ while (ts.getState() == TokenStream.STATE_NEXTPART) {
+ ts.nextPart();
+ parsePart(ts);
+ }
+
+ if (ts.getState() != TokenStream.STATE_ENDMULTIPART) { // sanity check
+ throw new MultipartException("Malformed stream");
+ }
+ }
+
+ /**
+ * Parse a single part
+ *
+ * @param ts
+ *
+ * @throws IOException
+ * @throws MultipartException
+ */
+ private void parsePart(TokenStream ts)
+ throws IOException, MultipartException {
+
+ Hashtable headers = new Hashtable();
+ headers = readHeaders(ts);
+ try {
+ if (headers.containsKey("filename")) {
+ if (!"".equals(headers.get("filename"))) {
+ parseFilePart(ts, headers);
+ } else {
+ // IE6 sends an empty part with filename="" for
+ // empty upload fields. Just parse away the part
+ byte[] buf = new byte[32];
+ while(ts.getState() == TokenStream.STATE_READING)
+ ts.read(buf);
+ }
+ } else if (((String) headers.get("content-disposition"))
+ .toLowerCase().equals("form-data")) {
+ parseInlinePart(ts, headers);
+ }
+
+ // FIXME: multipart/mixed parts are untested.
+ else if (((String) headers.get("content-disposition")).toLowerCase()
+ .indexOf("multipart") > -1) {
+ parseMultiPart(new TokenStream(ts, MAX_BOUNDARY_SIZE),
+ "--" + (String) headers.get("boundary"));
+ ts.read(); // read past boundary
+ } else {
+ throw new MultipartException("Unknown part type");
+ }
+ } catch (IOException e) {
+ throw new MultipartException("Malformed stream: " + e.getMessage());
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ throw new MultipartException("Malformed header");
+ }
+ }
+
+ /**
+ * Parse a file part
+ *
+ * @param in
+ * @param headers
+ *
+ * @throws IOException
+ * @throws MultipartException
+ */
+ private void parseFilePart(TokenStream in, Hashtable headers)
+ throws IOException, MultipartException {
+
+ byte[] buf = new byte[FILE_BUFFER_SIZE];
+ OutputStream out;
+ File file = null;
+
+ if (oversized) {
+ out = new NullOutputStream();
+ } else if (!saveUploadedFilesToDisk) {
+ out = new ByteArrayOutputStream();
+ } else {
+ String fileName = (String) headers.get("filename");
+ if(File.separatorChar == '\\')
+ fileName = fileName.replace('/','\\');
+ else
+ fileName = fileName.replace('\\','/');
+
+ String filePath = uploadDirectory.getPath() + File.separator;
+ fileName = new File(fileName).getName();
+ file = new File(filePath + fileName);
+
+ if (!allowOverwrite && !file.createNewFile()) {
+ if (silentlyRename) {
+ int c = 0;
+ do {
+ file = new File(filePath + c++ + "_" + fileName);
+ } while (!file.createNewFile());
+ } else {
+ throw new MultipartException("Duplicate file '" + file.getName()
+ + "' in '" + file.getParent() + "'");
+ }
+ }
+
+ out = new FileOutputStream(file);
+ }
+
+ int length = 0; // Track length for OversizedPart
+ try {
+ int read = 0;
+ while (in.getState() == TokenStream.STATE_READING) {
+ // read data
+ read = in.read(buf);
+ length += read;
+ out.write(buf, 0, read);
+ }
+ } catch (IOException ioe) {
+ // don't let incomplete file uploads pile up in the upload dir.
+ // this usually happens with aborted form submits containing very large files.
+ out.close();
+ out = null;
+ if ( file!=null ) file.delete();
+ throw ioe;
+ } finally {
+ if ( out!=null ) out.close();
+ }
+
+ String name = (String)headers.get("name");
+ if (oversized) {
+ this.parts.put(name, new RejectedPart(headers, length, this.contentLength, this.maxUploadSize));
+ } else if (file == null) {
+ byte[] bytes = ((ByteArrayOutputStream) out).toByteArray();
+ this.parts.put(name, new PartInMemory(headers, new ByteArrayInputStream(bytes), bytes.length));
+ } else {
+ this.parts.put(name, new PartOnDisk(headers, file));
+ }
+ }
+
+ /**
+ * Parse an inline part
+ *
+ * @param in
+ * @param headers
+ *
+ * @throws IOException
+ */
+ private void parseInlinePart(TokenStream in, Hashtable headers)
+ throws IOException {
+
+ // Buffer incoming bytes for proper string decoding (there can be multibyte chars)
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ while (in.getState() == TokenStream.STATE_READING) {
+ int c = in.read();
+ if (c != -1) bos.write(c);
+ }
+
+ String field = (String) headers.get("name");
+ Vector v = (Vector) this.parts.get(field);
+
+ if (v == null) {
+ v = new Vector();
+ this.parts.put(field, v);
+ }
+
+ v.add(new String(bos.toByteArray(), this.characterEncoding));
+ }
+
+ /**
+ * Read part headers
+ *
+ * @param in
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ private Hashtable readHeaders(TokenStream in) throws IOException {
+
+ Hashtable headers = new Hashtable();
+ String hdrline = readln(in);
+
+ while (!"".equals(hdrline)) {
+ StringTokenizer tokenizer = new StringTokenizer(hdrline);
+
+ headers.put(tokenizer.nextToken(" :").toLowerCase(),
+ tokenizer.nextToken(" :;"));
+
+ // The extra tokenizer.hasMoreTokens() in headers.put
+ // handles the filename="" case IE6 submits for an empty
+ // upload field.
+ while (tokenizer.hasMoreTokens()) {
+ headers.put(tokenizer.nextToken(" ;=\""),
+ tokenizer.hasMoreTokens()?tokenizer.nextToken("=\""):"");
+ }
+
+ hdrline = readln(in);
+ }
+
+ return headers;
+ }
+
+ /**
+ * Get boundary from contentheader
+ *
+ * @param hdr
+ *
+ * @return
+ */
+ private String getBoundary(String hdr) {
+
+ int start = hdr.toLowerCase().indexOf("boundary=");
+ if (start > -1) {
+ return "--" + hdr.substring(start + 9);
+ }
+ return null;
+ }
+
+ /**
+ * Read string until newline or end of stream
+ *
+ * @param in
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ private String readln(TokenStream in) throws IOException {
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ int b = in.read();
+
+ while ((b != -1) && (b != '\r')) {
+ bos.write(b);
+ b = in.read();
+ }
+
+ if (b == '\r') {
+ in.read(); // read '\n'
+ }
+
+ return new String(bos.toByteArray(), this.characterEncoding);
+ }
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/MultipartParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/Part.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/Part.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/Part.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/Part.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,155 @@
+/*
+ * Copyright 1999-2004 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.multipart;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+import org.apache.avalon.excalibur.io.IOUtil;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.excalibur.source.ModifiableSource;
+
+
+/**
+ * This abstract class represents a file part parsed from a http post stream. The concrete
+ * class, {@link PartOnDisk} or {@link PartInMemory} that is used depends on the upload configuration
+ * in <code>web.xml</code>.
+ * <p>
+ * If uploaded data size exceeds the maximum allowed upload size (also specified in <code>web.xml</code>),
+ * then an {@link RejectedPart} is used, from which no data can be obtained, but which gives some
+ * information on the rejected uploads.
+ *
+ * @author <a href="mailto:j.tervoorde@home.nl">Jeroen ter Voorde</a>
+ * @version CVS $Id: Part.java 280948 2005-09-14 21:48:24Z sylvain $
+ */
+public abstract class Part implements Disposable {
+
+ private boolean disposeWithRequest = true;
+
+ /** Field headers */
+ protected Map headers;
+
+ protected Part(Map headers) {
+ this.headers = headers;
+ }
+
+ /**
+ * Returns the part headers
+ */
+ public Map getHeaders() {
+ return headers;
+ }
+
+ /**
+ * Returns the filename
+ */
+ public abstract String getFileName();
+
+ /**
+ * Returns the original filename
+ */
+ public String getUploadName(){
+ return (String) headers.get("filename");
+ }
+
+ /**
+ * Returns the length of the file content
+ */
+ public abstract int getSize();
+
+ /**
+ * Is this part a rejected part? Provided as an alternative to <code>instanceof RejectedPart</code>
+ * in places where it's not convenient such as flowscript.
+ *
+ * @return <code>true</code> if this part was rejected
+ */
+ public boolean isRejected() {
+ return false;
+ }
+
+ /**
+ * Returns the mime type (or null if unknown)
+ */
+ public String getMimeType() {
+ return (String) headers.get("content-type");
+ }
+
+ /**
+ * Do we want any temporary resource held by this part to be cleaned up when processing of
+ * the request that created it is finished? Default is <code>true</code>.
+ *
+ * @return <code>true</code> if the part should be disposed with the request.
+ */
+ public boolean disposeWithRequest() {
+ return this.disposeWithRequest;
+ }
+
+ /**
+ * Set the value of the <code>disposeWithRequest</code> flag (default is <code>true</code>).
+ *
+ * @param dispose <code>true</code> if the part should be disposed after request processing
+ */
+ public void setDisposeWithRequest(boolean dispose) {
+ this.disposeWithRequest = dispose;
+ }
+
+ /**
+ * Returns an InputStream containing the file data
+ * @throws Exception
+ */
+ public abstract InputStream getInputStream() throws IOException;
+
+ /**
+ * Convenience method to copy a part to a modifiable source.
+ *
+ * @param source the modifiable source to write to
+ * @throws IOException
+ * @since 2.1.8
+ */
+ public void copyToSource(ModifiableSource source) throws IOException {
+ InputStream is = getInputStream();
+ OutputStream os = source.getOutputStream();
+ IOUtil.copy(is, os);
+ is.close();
+ os.close();
+ }
+
+ /**
+ * Convenience method to copy a part to a file.
+ *
+ * @param filename name of the file to write to
+ * @throws IOException
+ * @since 2.1.8
+ */
+ public void copyToFile(String filename) throws IOException {
+ InputStream is = getInputStream();
+ OutputStream os = new FileOutputStream(filename);
+ IOUtil.copy(is, os);
+ is.close();
+ os.close();
+ }
+
+ /**
+ * Dispose any resources held by this part, such as a file or memory buffer.
+ * <p>
+ * Disposal occurs in all cases when the part is garbage collected, but calling it explicitely
+ * allows to cleanup resources more quickly.
+ */
+ public abstract void dispose();
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/Part.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartInMemory.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartInMemory.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartInMemory.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartInMemory.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1999-2004 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.multipart;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * This class represents a file part parsed from a http post stream.
+ *
+ * @author <a href="mailto:j.tervoorde@home.nl">Jeroen ter Voorde</a>
+ * @version CVS $Id: PartInMemory.java 280948 2005-09-14 21:48:24Z sylvain $
+ */
+public class PartInMemory extends Part {
+
+ private InputStream in;
+
+ private int size;
+
+ /**
+ * Constructor PartInMemory
+ *
+ * @param headers
+ * @param in
+ * @param size
+ */
+ public PartInMemory(Map headers, InputStream in, int size) {
+ super(headers);
+ this.in = in;
+ this.size = size;
+ }
+
+ /**
+ * Returns the filename
+ */
+ public String getFileName() {
+ return (String) headers.get("filename");
+ }
+
+ /**
+ * Returns the filesize in bytes
+ */
+ public int getSize() {
+ return this.size;
+ }
+
+ /**
+ * Returns a (ByteArray)InputStream containing the file data
+ *
+ * @throws Exception
+ */
+ public InputStream getInputStream() throws IOException {
+ if (this.in != null) {
+ return this.in;
+ } else {
+ throw new IllegalStateException("This part has already been disposed.");
+ }
+ }
+
+ /**
+ * Clean the byte array content buffer holding part data
+ */
+ public void dispose() {
+ this.in = null;
+ }
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartInMemory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartOnDisk.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartOnDisk.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartOnDisk.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartOnDisk.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,111 @@
+/*
+ * Copyright 1999-2004 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.multipart;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * This class represents a file part parsed from a http post stream.
+ *
+ * @author <a href="mailto:j.tervoorde@home.nl">Jeroen ter Voorde</a>
+ * @version CVS $Id: PartOnDisk.java 280948 2005-09-14 21:48:24Z sylvain $
+ */
+public class PartOnDisk extends Part {
+
+ /** Field file */
+ private File file = null;
+ private int size;
+
+ /**
+ * Constructor PartOnDisk
+ *
+ * @param headers
+ * @param file
+ */
+ protected PartOnDisk(Map headers, File file) {
+ super(headers);
+ this.file = file;
+
+ // Ensure the file will be deleted when we exit the JVM
+ this.file.deleteOnExit();
+
+ this.size = (int) file.length();
+ }
+
+ /**
+ * Returns the file name
+ */
+ public String getFileName() {
+ return file.getName();
+ }
+
+ /**
+ * Returns the file size in bytes
+ */
+ public int getSize() {
+ return this.size;
+ }
+
+ /**
+ * Returns the file
+ */
+ public File getFile() {
+ return file;
+ }
+
+ /**
+ * Returns a (ByteArray)InputStream containing the file data
+ *
+ * @throws Exception
+ */
+ public InputStream getInputStream() throws IOException {
+ if (this.file != null) {
+ return new FileInputStream(file);
+ }
+ throw new IllegalStateException("This part has already been disposed.");
+ }
+
+ /**
+ * Returns the filename
+ */
+ public String toString() {
+ return file.getPath();
+ }
+
+ /**
+ * Delete the underlying file.
+ */
+ public void dispose() {
+ if (this.file != null) {
+ this.file.delete();
+ this.file = null;
+ }
+ }
+
+ /**
+ * Ensures the underlying file has been deleted
+ */
+ public void finalize() throws Throwable {
+ // Ensure the file has been deleted
+ dispose();
+
+ super.finalize();
+ }
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/PartOnDisk.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/RejectedPart.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/RejectedPart.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/RejectedPart.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/RejectedPart.java Thu Nov 3 05:41:06 2005
@@ -0,0 +1,94 @@
+/*
+ * 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.multipart;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * An upload part that was rejected because request length exceeded the maximum upload size.
+ *
+ * @version $Id: RejectedPart.java 280948 2005-09-14 21:48:24Z sylvain $
+ * @since 2.1.8
+ */
+public class RejectedPart extends Part {
+
+ private int size;
+ public int contentLength;
+ public int maxContentLength;
+
+ public RejectedPart(Map headers, int partSize, int contentLength, int maxContentLength) {
+ super(headers);
+ this.size = partSize;
+ this.contentLength = contentLength;
+ this.maxContentLength = maxContentLength;
+ }
+
+ public String getFileName() {
+ return (String) headers.get("filename");
+ }
+
+ /**
+ * Get the size of this part.
+ *
+ * @return the size in bytes
+ */
+ public int getSize() {
+ return this.size;
+ }
+
+ /**
+ * Get the maximum allowed upload size. Not that this applies to the full request content length,
+ * including multipart boundaries and other form data values.
+ * <p>
+ * This means that an upload part can be rejected although it's individual size is (a bit) smaller
+ * than the maximum size. It is therefore advisable to use {@link #getContentLength()} to build
+ * error messages rather than {@link #getSize()}.
+ *
+ * @return the maximum content length in bytes
+ */
+ public int getMaxContentLength() {
+ return this.maxContentLength;
+ }
+
+ /**
+ * Get the content length of the request that cause this part to be rejected.
+ *
+ * @return the content length in bytes
+ */
+ public int getContentLength() {
+ return this.contentLength;
+ }
+ /**
+ * Always throw an <code>IOException</code> as this part was rejected.
+ */
+ public InputStream getInputStream() throws IOException {
+ throw new IOException("Multipart element '" + getFileName() + "' is too large (" +
+ this.size + " bytes) and was discarded.");
+ }
+
+ /**
+ * Always return <code>true</code>
+ */
+ public boolean isRejected() {
+ return true;
+ }
+
+ public void dispose() {
+ // nothing
+ }
+}
Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/servlet/multipart/RejectedPart.java
------------------------------------------------------------------------------
svn:eol-style = native