package org.apache.fulcrum.upload;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.portlet.ActionRequest;
import javax.servlet.http.HttpServletRequest;

import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.portlet.PortletFileUpload;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * <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
 * <code>org.apache.fulcrum.util.parser.ParameterParser</code> as
 * <code>org.apache.commons.fileupload.FileItem</code> objects.
 *
 * <p>
 * This implementation of {@link UploadService} handles multiple files per
 * single html form, sent using multipart/form-data encoding type, as specified
 * by RFC 1867. Use
 * <code>org.apache.fulcrum.parser.ParameterParser#getFileItems(String)</code> to
 * acquire an array of <code>org.apache.commons.fileupload.FileItem</code> objects
 * associated with given html form.
 *
 * @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:jvanzyl@apache.org">Jason van Zyl</a>
 * @version $Id$
 */
public class DefaultUploadService extends AbstractLogEnabled
		implements UploadService, Initializable, Configurable, Contextualizable {
	/** A File Item Factory object for the actual uploading */
	private DiskFileItemFactory itemFactory;

	private int sizeThreshold;
	private int sizeMax;

	private String repositoryPath;
	private String headerEncoding;

	/**
	 * The application root
	 */
	private String applicationRoot;

	/**
	 * The maximum allowed upload size
	 */
	@Override
	public long getSizeMax() {
		return sizeMax;
	}

	/**
	 * The threshold beyond which files are written directly to disk.
	 */
	@Override
	public long getSizeThreshold() {
		return itemFactory.getSizeThreshold();
	}

	/**
	 * The location used to temporarily store files that are larger than the size
	 * threshold.
	 */
	@Override
	public String getRepository() {
		return itemFactory.getRepository().getAbsolutePath();
	}

	/**
	 * @return Returns the headerEncoding.
	 */
	@Override
	public String getHeaderEncoding() {
		return headerEncoding;
	}

	/**
	 * <p>
	 * Parses a <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
	 * <code>multipart/form-data</code> stream.
	 * </p>
	 *
	 * @param req The servlet request to be parsed.
	 * @throws ServiceException Problems reading/parsing the request or storing the
	 *                          uploaded file(s).
	 */
	@Override
	public List<FileItem> parseRequest(HttpServletRequest req) throws ServiceException {
		return parseRequest(req, this.sizeMax, this.itemFactory);
	}

	/**
	 * <p>
	 * Parses a <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
	 * <code>multipart/form-data</code> stream.
	 * </p>
	 *
	 * @param req  The servlet request to be parsed.
	 * @param path The location where the files should be stored.
	 * @throws ServiceException Problems reading/parsing the request or storing the
	 *                          uploaded file(s).
	 */
	@Override
	public List<FileItem> parseRequest(HttpServletRequest req, String path) throws ServiceException {
		return parseRequest(req, this.sizeThreshold, this.sizeMax, path);
	}

	/**
	 * <p>
	 * Parses a <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
	 * <code>multipart/form-data</code> stream.
	 * </p>
	 *
	 * @param req           The servlet request to be parsed.
	 * @param sizeThreshold the max size in bytes to be stored in memory
	 * @param sizeMax       the maximum allowed upload size in bytes
	 * @param path          The location where the files should be stored.
	 * @return list of file items
	 * @throws ServiceException Problems reading/parsing the request or storing the
	 *                          uploaded file(s).
	 */
	@Override
	public List<FileItem> parseRequest(HttpServletRequest req, int sizeThreshold, int sizeMax, String path)
			throws ServiceException {
		return parseRequest(req, sizeMax, new DiskFileItemFactory(sizeThreshold, new File(path)));
	}

	/**
	 * <p>
	 * Parses a <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
	 * <code>multipart/form-data</code> stream.
	 * </p>
	 *
	 * @param req     The servlet request to be parsed.
	 * @param sizeMax the maximum allowed upload size in bytes
	 * @param factory the file item factory to use
	 * @return list of file items
	 * @throws ServiceException Problems reading/parsing the request or storing the
	 *                          uploaded file(s).
	 */
	protected List<FileItem> parseRequest(HttpServletRequest req, int sizeMax, DiskFileItemFactory factory)
			throws ServiceException {
		try {
			ServletFileUpload fileUpload = new ServletFileUpload(factory);
			fileUpload.setSizeMax(sizeMax);
			fileUpload.setHeaderEncoding(headerEncoding);
			return fileUpload.parseRequest(req);
		} catch (FileUploadException e) {
			throw new ServiceException(UploadService.ROLE, e.getMessage(), e);
		}
	}

	/**
	 * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
	 * compliant <code>multipart/form-data</code> stream.
	 *
	 * @param req The servlet request to be parsed.
	 *
	 * @return An iterator to instances of <code>FileItemStream</code> parsed from
	 *         the request, in the order that they were transmitted.
	 *
	 * @throws ServiceException if there are problems reading/parsing the request or
	 *                          storing files. This may also be a network error
	 *                          while communicating with the client or a problem
	 *                          while storing the uploaded content.
	 */
	@Override
	public FileItemIterator getItemIterator(HttpServletRequest req) throws ServiceException {
		ServletFileUpload upload = new ServletFileUpload();
		try {
			return upload.getItemIterator(req);
		} catch (FileUploadException e) {
			throw new ServiceException(UploadService.ROLE, e.getMessage(), e);
		} catch (IOException e) {
			throw new ServiceException(UploadService.ROLE, e.getMessage(), e);
		}
	}

	/**
	 * <p>
	 * Parses a <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
	 * <code>multipart/form-data</code> stream.
	 * </p>
	 *
	 * @param req The portlet request to be parsed.
	 * @throws ServiceException Problems reading/parsing the request or storing the
	 *                          uploaded file(s).
	 */
	@Override
	public List<FileItem> parseRequest(ActionRequest req) throws ServiceException {
		return parseRequest(req, this.sizeMax, this.itemFactory);
	}

	/**
	 * <p>
	 * Parses a <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
	 * <code>multipart/form-data</code> stream.
	 * </p>
	 *
	 * @param req  The portlet request to be parsed.
	 * @param path The location where the files should be stored.
	 * @throws ServiceException Problems reading/parsing the request or storing the
	 *                          uploaded file(s).
	 */
	@Override
	public List<FileItem> parseRequest(ActionRequest req, String path) throws ServiceException {
		return parseRequest(req, this.sizeThreshold, this.sizeMax, path);
	}

	/**
	 * <p>
	 * Parses a <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
	 * <code>multipart/form-data</code> stream.
	 * </p>
	 *
	 * @param req           The portlet request to be parsed.
	 * @param sizeThreshold the max size in bytes to be stored in memory
	 * @param sizeMax       the maximum allowed upload size in bytes
	 * @param path          The location where the files should be stored.
	 * @throws ServiceException Problems reading/parsing the request or storing the
	 *                          uploaded file(s).
	 */
	@Override
	public List<FileItem> parseRequest(ActionRequest req, int sizeThreshold, int sizeMax, String path)
			throws ServiceException {
		return parseRequest(req, sizeMax, new DiskFileItemFactory(sizeThreshold, new File(path)));
	}

	/**
	 * <p>
	 * Parses a <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
	 * <code>multipart/form-data</code> stream.
	 * </p>
	 *
	 * @param req     The portlet request to be parsed.
	 * @param sizeMax the maximum allowed upload size in bytes
	 * @param factory the file item factory to use
	 * @return The list of FileItem parts uploaded
	 * @throws ServiceException Problems reading/parsing the request or storing the
	 *                          uploaded file(s).
	 */
	protected List<FileItem> parseRequest(ActionRequest req, int sizeMax, DiskFileItemFactory factory)
			throws ServiceException {
		try {
			PortletFileUpload fileUpload = new PortletFileUpload(factory);
			fileUpload.setSizeMax(sizeMax);
			fileUpload.setHeaderEncoding(headerEncoding);
			return fileUpload.parseRequest(req);
		} catch (FileUploadException e) {
			throw new ServiceException(UploadService.ROLE, e.getMessage(), e);
		}
	}

	/**
	 * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>
	 * compliant <code>multipart/form-data</code> stream.
	 *
	 * @param req The portlet request to be parsed.
	 *
	 * @return An iterator to instances of <code>FileItemStream</code> parsed from
	 *         the request, in the order that they were transmitted.
	 *
	 * @throws ServiceException if there are problems reading/parsing the request or
	 *                          storing files. This may also be a network error
	 *                          while communicating with the client or a problem
	 *                          while storing the uploaded content.
	 */
	@Override
	public FileItemIterator getItemIterator(ActionRequest req) throws ServiceException {
		PortletFileUpload upload = new PortletFileUpload();
		try {
			return upload.getItemIterator(req);
		} catch (FileUploadException e) {
			throw new ServiceException(UploadService.ROLE, e.getMessage(), e);
		} catch (IOException e) {
			throw new ServiceException(UploadService.ROLE, e.getMessage(), e);
		}
	}

	/**
	 * Utility method that determines whether the request contains multipart
	 * content.
	 *
	 * @param req The servlet request to be evaluated. Must be non-null.
	 *
	 * @return <code>true</code> if the request is multipart; <code>false</code>
	 *         otherwise.
	 */
	@Override
	public boolean isMultipart(HttpServletRequest req) {
		return ServletFileUpload.isMultipartContent(req);
	}

	/**
	 * Utility method that determines whether the request contains multipart
	 * content.
	 *
	 * @param req The portlet request to be evaluated. Must be non-null.
	 *
	 * @return <code>true</code> if the request is multipart; <code>false</code>
	 *         otherwise.
	 */
	@Override
	public boolean isMultipart(ActionRequest req) {
		return PortletFileUpload.isMultipartContent(req);
	}

	/**
	 * @see org.apache.fulcrum.ServiceBroker#getRealPath(String)
	 */
	private String getRealPath(String path) {
		String absolutePath = null;
		if (applicationRoot == null) {
			absolutePath = new File(path).getAbsolutePath();
		} else {
			absolutePath = new File(applicationRoot, path).getAbsolutePath();
		}

		return absolutePath;
	}

	// ---------------- Avalon Lifecycle Methods ---------------------
	/**
	 * Avalon component lifecycle method
	 */
	@Override
	public void configure(Configuration conf) {
		repositoryPath = conf.getAttribute(UploadService.REPOSITORY_KEY, UploadService.REPOSITORY_DEFAULT);

		headerEncoding = conf.getAttribute(UploadService.HEADER_ENCODING_KEY, UploadService.HEADER_ENCODING_DEFAULT);

		sizeMax = conf.getAttributeAsInteger(UploadService.SIZE_MAX_KEY, UploadService.SIZE_MAX_DEFAULT);

		sizeThreshold = conf.getAttributeAsInteger(UploadService.SIZE_THRESHOLD_KEY,
				UploadService.SIZE_THRESHOLD_DEFAULT);
	}

	/**
	 * Avalon component lifecycle method
	 *
	 * Initializes the service.
	 *
	 * This method processes the repository path, to make it relative to the web
	 * application root, if necessary
	 */
	@Override
	public void initialize() throws Exception {
		// test for the existence of the path within the webapp directory.
		// if it does not exist, assume the path was to be used as is.
		String testPath = getRealPath(repositoryPath);
		File testDir = new File(testPath);
		if (testDir.exists()) {
			repositoryPath = testPath;
		}

		getLogger().debug("Upload Service: REPOSITORY_KEY => " + repositoryPath);

		itemFactory = new DiskFileItemFactory(sizeThreshold, new File(repositoryPath));
	}

	/**
	 * Avalon component lifecycle method
	 */
	@Override
	public void contextualize(Context context) throws ContextException {
		this.applicationRoot = context.get("urn:avalon:home").toString();
	}
}
