blob: 2f474379dcc3f02a406e8eb75a6beddaf97529ae [file] [log] [blame]
package org.apache.turbine.services.upload;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Turbine" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Turbine", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.turbine.Turbine;
import org.apache.turbine.services.InitializationException;
import org.apache.turbine.services.TurbineBaseService;
import org.apache.turbine.util.TurbineException;
import org.apache.turbine.util.parser.ParameterParser;
/**
* <p> This class is an implementation of {@link UploadService}.
*
* <p> Files will be stored in temporary disk storage on in memory,
* depending on request size, and will be available from the {@link
* org.apache.turbine.util.ParameterParser} as {@link
* org.apache.turbine.util.upload.FileItem}s.
*
* <p>This implementation of {@link UploadService} handles multiple
* files per single html widget, sent using multipar/mixed encoding
* type, as specified by RFC 1867. Use {@link
* org.apache.turbine.util.ParameterParser#getFileItems(String)} to
* acquire an array of {@link
* org.apache.turbine.util.upload.FileItem}s associated with given
* html widget.
*
* @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
* @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
* @version $Id$
*/
public class TurbineUploadService
extends TurbineBaseService
implements UploadService
{
/** Logging */
private static Log log = LogFactory.getLog(TurbineUploadService.class);
/** A File Upload object for the actual uploading */
protected DiskFileUpload fileUpload = null;
/** Auto Upload yes? */
private boolean automatic;
/**
* Initializes the service.
*
* This method processes the repository path, to make it relative to the
* web application root, if neccessary
*/
public void init()
throws InitializationException
{
Configuration conf = getConfiguration();
String repoPath = conf.getString(
UploadService.REPOSITORY_KEY,
UploadService.REPOSITORY_DEFAULT);
if (!repoPath.startsWith("/"))
{
// If our temporary directory is in the application
// space, try to create it. If this fails, throw
// an exception.
String testPath = Turbine.getRealPath(repoPath);
File testDir = new File(testPath);
if (!testDir.exists())
{
if (!testDir.mkdirs())
{
throw new InitializationException(
"Could not create target directory!");
}
}
repoPath = testPath;
conf.setProperty(UploadService.REPOSITORY_KEY, repoPath);
}
log.debug("Upload Path is now " + repoPath);
long sizeMax = conf.getLong(
UploadService.SIZE_MAX_KEY,
UploadService.SIZE_MAX_DEFAULT);
log.debug("Max Size " + sizeMax);
int sizeThreshold = conf.getInt(
UploadService.SIZE_THRESHOLD_KEY,
UploadService.SIZE_THRESHOLD_DEFAULT);
log.debug("Threshold Size " + sizeThreshold);
automatic = conf.getBoolean(
UploadService.AUTOMATIC_KEY,
UploadService.AUTOMATIC_DEFAULT);
log.debug("Auto Upload " + automatic);
fileUpload = new DiskFileUpload();
fileUpload.setSizeMax(sizeMax);
fileUpload.setSizeThreshold(sizeThreshold);
fileUpload.setRepositoryPath(repoPath);
setInit(true);
}
/**
* <p> Retrieves the value of <code>size.max</code> property of the
* {@link org.apache.turbine.services.upload.UploadService}.
*
* @return The maximum upload size.
*/
public long getSizeMax()
{
return fileUpload.getSizeMax();
}
/**
* <p> Retrieves the value of <code>size.threshold</code> property of
* {@link org.apache.turbine.services.upload.UploadService}.
*
* @return The threshold beyond which files are written directly to disk.
*/
public int getSizeThreshold()
{
return fileUpload.getSizeThreshold();
}
/**
* Retrieves the value of the 'automatic' property of {@link
* UploadService}. This reports whether the Parameter parser
* should allow "automatic" uploads if it is submitted to
* Turbine.
*
* @return The value of 'automatic' property of {@link
* UploadService}.
*/
public boolean getAutomatic()
{
return automatic;
}
/**
* <p> Retrieves the value of the <code>repository</code> property of
* {@link org.apache.turbine.services.upload.UploadService}.
*
* @return The repository.
*/
public String getRepository()
{
return fileUpload.getRepositoryPath();
}
/**
* <p> Processes an <a href="http://rf.cx/rfc1867.html">RFC
* 1867</a> compliant <code>multipart/form-data</code> stream.
*
* @param req The servlet request to be parsed.
* @param params The ParameterParser instance to insert form
* fields into.
* @param path The location where the files should be stored.
* @exception TurbineException Problems reading/parsing the
* request or storing the uploaded file(s).
*/
public void parseRequest(HttpServletRequest req,
ParameterParser params,
String path)
throws TurbineException
{
String contentType = req.getHeader(CONTENT_TYPE);
if (!contentType.startsWith(MULTIPART_FORM_DATA))
{
throw new TurbineException("the request doesn't contain a " +
MULTIPART_FORM_DATA + " stream");
}
int requestSize = req.getContentLength();
if (requestSize == -1)
{
throw new TurbineException("the request was rejected because " +
"it's size is unknown");
}
if (requestSize > getSizeMax())
{
throw new TurbineException("the request was rejected because " +
"it's size exceeds allowed range");
}
try
{
List fileList = fileUpload
.parseRequest(req,
getSizeThreshold(),
getSizeMax(),
path);
if (fileList != null)
{
for (Iterator it = fileList.iterator(); it.hasNext();)
{
FileItem fi = (FileItem) it.next();
if (fi.isFormField())
{
log.debug("Found an simple form field: " + fi.getFieldName() +", adding value " + fi.getString());
String value = null;
try
{
value = fi.getString(params.getCharacterEncoding());
}
catch (UnsupportedEncodingException e)
{
log.error(params.getCharacterEncoding()
+ " encoding is not supported."
+ "Used the default when reading form data.");
value = fi.getString();
}
params.append(fi.getFieldName(), value);
}
else
{
log.debug("Found an uploaded file: " + fi.getFieldName());
log.debug("It has " + fi.getSize() + " Bytes and is " + (fi.isInMemory() ? "" : "not ") + "in Memory");
log.debug("Adding FileItem as " + fi.getFieldName() + " to the params");
params.append(fi.getFieldName(), fi);
}
}
}
}
catch (FileUploadException e)
{
throw new TurbineException(e);
}
}
}