cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject 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/...
Date Thu, 03 Nov 2005 14:00:48 GMT
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



Mime
View raw message