/*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* "The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations under
* the License.
*
* The Original Code is ICEfaces 1.5 open source software code, released
* November 5, 2006. The Initial Developer of the Original Code is ICEsoft
* Technologies Canada, Corp. Portions created by ICEsoft are Copyright (C)
* 2004-2006 ICEsoft Technologies Canada, Corp. All Rights Reserved.
*
* Contributor(s): _____________________.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"
* License), in which case the provisions of the LGPL License are
* applicable instead of those above. If you wish to allow use of your
* version of this file only under the terms of the LGPL License and not to
* allow others to use your version of this file under the MPL, indicate
* your decision by deleting the provisions above and replace them with
* the notice and other provisions required by the LGPL License. If you do
* not delete the provisions above, a recipient may use your version of
* this file under either the MPL or the LGPL License."
*
*/
package com.icesoft.faces.component.inputfile;
import com.icesoft.faces.component.CSS_DEFAULT;
import com.icesoft.faces.component.ext.taglib.Util;
import com.icesoft.faces.component.style.OutputStyle;
import com.icesoft.faces.context.BridgeFacesContext;
import com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer;
import com.icesoft.faces.utils.MessageUtils;
import com.icesoft.faces.webapp.http.servlet.FileUploadComponent;
import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
import java.util.ArrayList;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.util.Streams;
import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ExternalContext;
import javax.faces.el.MethodBinding;
import javax.faces.el.ValueBinding;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.faces.event.FacesListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.Writer;
import java.util.EventObject;
import java.util.Iterator;
/**
* InputFile is a JSF component class representing an ICEfaces inputFile.
*/
public class InputFile extends UICommand implements Serializable, FileUploadComponent {
public static final int DEFAULT = 0;
public static final int UPLOADING = 1;
public static final int SAVED = 2;
public static final int INVALID = 3;
public static final int SIZE_LIMIT_EXCEEDED = 4;
public static final int UNKNOWN_SIZE = 5;
public static final int INVALID_NAME_PATTERN = 6;
public static final String INVALID_FILE_MESSAGE_ID = "com.icesoft.faces.component.inputfile.INVALID_FILE";
public static final String INVALID_NAME_PATTERN_MESSAGE_ID = "com.icesoft.faces.component.inputfile.INVALID_NAME_PATTERN";
public static final String SIZE_LIMIT_EXCEEDED_MESSAGE_ID = "com.icesoft.faces.component.inputfile.SIZE_LIMIT_EXCEEDED";
public static final String UNKNOWN_SIZE_MESSAGE_ID = "com.icesoft.faces.component.inputfile.UNKNOWN_SIZE";
public static final String FILE_UPLOAD_PREFIX = "fileUpload";
private Boolean disabled;
private String style;
private String styleClass;
private String label;
private String enabledOnUserRole;
private String renderedOnUserRole;
private String title;
private int height = 30;
private int width = 500;
private int inputTextSize = 35;
private String inputTextClass;
private String fileNamePattern;
private boolean uniqueFolder = true;
private String downloadFolder;
private Throwable uploadException;
private int status = DEFAULT;
private FileInfo fileInfo = new FileInfo();
private int progress = 0;
private File file;
private long sizeMax;
private MethodBinding progressListener;
/**
*
Return the value of the COMPONENT_TYPE of this
* component.
*/
public String getComponentType() {
return "com.icesoft.faces.File";
}
/**
*
Return the value of the RENDERER_TYPE of this
* component.
*/
public String getRendererType() {
return "com.icesoft.faces.Upload";
}
/**
*
Return the value of the COMPONENT_FAMILY of this
* component.
*/
public String getFamily() {
return "com.icesoft.faces.File";
}
public void upload(FileItemStream stream, String defaultFolder, long maxSize, BridgeFacesContext bfc) throws IOException {
this.uploadException = null;
this.status = UPLOADING;
this.sizeMax = maxSize;
FacesContext context = FacesContext.getCurrentInstance();
String folder = getDownloadFolder();
folder = folder == null ? defaultFolder : folder;
String namePattern = getFileNamePattern().trim();
String fileName = stream.getName();
// IE gives us the whole path on the client, but we just
// want the client end file name, not the path
if(fileName != null && fileName.length() > 0) {
File tempFileName = new File(fileName);
fileName = tempFileName.getName();
}
fileInfo.setFileName(fileName);
fileInfo.setContentType(stream.getContentType());
try {
if (fileName != null && fileName.trim().matches(namePattern)) {
File folderFile = new File(folder);
if(!folderFile.exists())
folderFile.mkdirs();
// ngriffin@liferay.com: Partial fix for http://jira.icefaces.org/browse/ICE-1601
this.file = new File(folder, fileName);
ValueBinding vb = getValueBinding("file");
if (vb != null) {
try
{
vb.setValue(context, getFile());
}
catch (Exception exception)
{
exception.printStackTrace();
throw new IOException(exception.getMessage());
}
}
OutputStream output = new FileOutputStream(file);
Streams.copy(stream.openStream(), output, true);
status = SAVED;
fileInfo.setPhysicalPath(file.getAbsolutePath());
notifyDone(bfc);
} else {
fileInfo.reset();
file = null;
status = INVALID_NAME_PATTERN;
context.addMessage(null, MessageUtils.getMessage(context, INVALID_NAME_PATTERN_MESSAGE_ID, new Object[] { fileName, namePattern }));
notifyDone(bfc);
}
} catch (FileUploadBase.FileUploadIOException uploadException) {
this.uploadException = uploadException.getCause();
try {
throw this.uploadException;
} catch (FileUploadBase.FileSizeLimitExceededException e) {
status = SIZE_LIMIT_EXCEEDED;
} catch (FileUploadBase.UnknownSizeException e) {
status = UNKNOWN_SIZE;
} catch (FileUploadBase.InvalidContentTypeException e) {
status = INVALID;
} catch (Throwable t) {
status = INVALID;
}
fileInfo.setException(uploadException);
file.delete();
notifyDone(bfc);
throw uploadException;
}
catch(IOException e) { // Eg: If creating the saved file fails
this.uploadException = e;
status = INVALID;
fileInfo.setException(e);
file.delete();
notifyDone(bfc);
throw e;
}
PersistentFacesState.getInstance().renderLater();
}
protected void notifyDone(BridgeFacesContext bfc) {
ActionEvent event = new ActionEvent(this);
bfc.setCurrentInstance();
// ngriffin@liferay.com: Action binding not being called without this...
queueEvent(event);
//this is true for JSF 1.1 only
MethodBinding actionListener = getActionListener();
if(actionListener != null) {
System.err.println("!@#$ JSF 1.1 actionListener=" + actionListener.toString());
actionListener.invoke(
FacesContext.getCurrentInstance(),
new Object[] {event} );
}
//this is true for JSF 1.2 only
ActionListener[] actionListeners = getActionListeners();
for (int i=0; i< actionListeners.length; i++) {
System.err.println("!@#$ JSF 1.2");
actionListeners[i].processAction(event);
}
// Execute the action listener method binding (if one exists)
MethodBinding action = getAction();
if(action != null) {
action.invoke(FacesContext.getCurrentInstance(), null);
}
if(fileInfo != null)
fileInfo.reset();
}
// ngriffin@liferay.com: http://jira.icefaces.org/browse/ICE-1605
private static ArrayList findOutputStyleComponents(UIComponent parent) {
ArrayList returnValue = null;
Iterator children = parent.getChildren().iterator();
UIComponent childComponent = null;
while (children.hasNext()) {
childComponent = (UIComponent) children.next();
if (childComponent instanceof OutputStyle) {
if (returnValue == null)
{
returnValue = new ArrayList();
}
System.err.println("!@#$ InputFile.findOutputStyleComponents() FOUND ONE!");
returnValue.add(childComponent);
}
else
{
ArrayList outputStyleComponents = findOutputStyleComponents(childComponent);
if (outputStyleComponents != null)
{
System.err.println("!@#$ InputFile.findOutputStyleComponents() FOUND ONE OR MORE size=" + outputStyleComponents.size());
if (returnValue == null)
{
returnValue = outputStyleComponents;
}
else
{
returnValue.add(outputStyleComponents);
}
}
}
}
return returnValue;
}
public void renderIFrame(Writer writer, BridgeFacesContext context) throws IOException {
String srv = getUploadServletPath(context);
// ngriffin@liferay.com: http://jira.icefaces.org/browse/ICE-1603
writer.write("");
// ngriffin@liferay.com: http://jira.icefaces.org/browse/ICE-1605
ArrayList outputStyleComponents = findOutputStyleComponents(context.getViewRoot());
if (outputStyleComponents != null)
{
writer.write("");
for (int i = 0; i < outputStyleComponents.size(); i++)
{
OutputStyle outputStyle = (OutputStyle) outputStyleComponents.get(i);
String href = outputStyle.getHref();
if ((href != null) && (href.length() > 0))
{
href = DomBasicRenderer.getResourceURL(context, href);
writer.write("");
}
}
writer.write("");
}
writer.write("");
writer.write("");
}
private String getUploadServletPath(BridgeFacesContext context) {
String requestContextPath = null;
if(context != null) {
ExternalContext externalContext = context.getExternalContext();
if(externalContext != null) {
requestContextPath = externalContext.getRequestContextPath();
}
}
if(requestContextPath == null || requestContextPath.length() == 0)
return "./uploadHtml";
else
return requestContextPath + "/uploadHtml";
}
public Throwable getUploadException() {
return uploadException;
}
/**
*
* Set the value of the label property.
*/
public void setLabel(String label) {
this.label = label;
}
/**
*
* Set the value of the uniqueFolder property.
*/
public void setUniqueFolder(boolean uniqueFolder) {
if (uniqueFolder != this.uniqueFolder) {
this.uniqueFolder = uniqueFolder;
}
}
/**
*
* Return the value of the uniqueFolder property.
*/
public boolean isUniqueFolder() {
ValueBinding vb = getValueBinding("uniqueFolder");
if (vb != null) {
return (Boolean.TRUE.equals(vb.getValue(getFacesContext())));
}
return true;
}
/**
*
* Return the value of the label property.
*/
public String getLabel() {
if (label != null) {
return label;
}
ValueBinding vb = getValueBinding("label");
return vb != null ? (String) vb.getValue(getFacesContext()) : "Upload";
}
/**
*