package pt.ist.renderers; import java.io.IOException; import java.io.UnsupportedEncodingException; import org.apache.commons.beanutils.PropertyUtils; import pt.ist.renderers.components.HtmlComponent; import pt.ist.renderers.components.HtmlForm; import pt.ist.renderers.components.HtmlInputFile; import pt.ist.renderers.components.HtmlSimpleValueComponent; import pt.ist.renderers.components.controllers.HtmlController; import pt.ist.renderers.components.converters.ConversionException; import pt.ist.renderers.components.converters.Converter; import pt.ist.renderers.components.state.IViewState; import pt.ist.renderers.layouts.Layout; import pt.ist.renderers.model.MetaObject; import pt.ist.renderers.model.MetaSlot; import pt.ist.renderers.model.MetaSlotKey; import pt.ist.renderers.plugin.RenderersRequestProcessorImpl; import pt.ist.renderers.servlets.commons.UploadedFile; /** * This renderer creates a file input field that allows the user to submit a * file. The renderer will set the slot with an output stream that represents * the file. * *
* Example:
*
* @author cfgi
*/
public class FileInputRenderer extends InputRenderer {
private String size;
private String fileNameSlot;
private String fileSizeSlot;
private String fileContentTypeSlot;
public String getSize() {
return this.size;
}
/**
* Selects the size of the file input field.
*
* @property
*/
public void setSize(String size) {
this.size = size;
}
public String getFileContentTypeSlot() {
return this.fileContentTypeSlot;
}
/**
* When this property is specified the renderer will set the given slot with
* the content type of the file. The slot must have the string type.
*
* @property
*/
public void setFileContentTypeSlot(String fileContentTypeSlot) {
this.fileContentTypeSlot = fileContentTypeSlot;
}
public String getFileNameSlot() {
return this.fileNameSlot;
}
/**
* When this property is specified the renderer will set the given slot with
* the name of the file as given by the user. The slot must have the string
* type.
*
* @property
*/
public void setFileNameSlot(String fileNameSlot) {
this.fileNameSlot = fileNameSlot;
}
public String getFileSizeSlot() {
return this.fileSizeSlot;
}
/**
* When this property is specified the renderer will set the given slot with
* the size of the file in bytes. The slot must be have the
* long
type.
*
* @property
*/
public void setFileSizeSlot(String fileSizeSlot) {
this.fileSizeSlot = fileSizeSlot;
}
@Override
protected Layout getLayout(Object object, Class type) {
return new Layout() {
@Override
public HtmlComponent createComponent(Object object, Class type) {
getInputContext().getForm().setEncoding(HtmlForm.FORM_DATA);
HtmlInputFile file = new HtmlInputFile();
file.setTargetSlot((MetaSlotKey) getInputContext().getMetaObject().getKey());
file.setController(new UpdateFilePropertiesController(((MetaSlot) getInputContext().getMetaObject())
.getMetaObject(), getFileNameSlot(), getFileSizeSlot(), getFileContentTypeSlot()));
file.setConverter(new FileConverter(file));
return file;
}
@Override
public void applyStyle(HtmlComponent component) {
super.applyStyle(component);
((HtmlInputFile) component).setSize(getSize());
}
};
}
private static class UpdateFilePropertiesController extends HtmlController {
private MetaObject object;
private String fileNameSlot;
private String fileSizeSlot;
private String fileContentTypeSlot;
public UpdateFilePropertiesController(MetaObject object, String fileNameSlot, String fileSizeSlot,
String fileContentTypeSlot) {
this.object = object;
this.fileNameSlot = fileNameSlot;
this.fileSizeSlot = fileSizeSlot;
this.fileContentTypeSlot = fileContentTypeSlot;
}
@Override
public void execute(IViewState viewState) {
HtmlSimpleValueComponent component = (HtmlSimpleValueComponent) getControlledComponent();
String name = component.getName();
UploadedFile file = RenderersRequestProcessorImpl.getUploadedFile(name);
if (file != null) { // if has file
Object object = this.object.getObject();
try {
String currentEncoding = RenderersRequestProcessorImpl.getCurrentEncoding();
setPropertyIgnoringErrors(object, this.fileNameSlot, currentEncoding != null ? new String(file.getName()
.getBytes(), currentEncoding) : new String(file.getName().getBytes()));
} catch (UnsupportedEncodingException e) {
// best effort name setting
setPropertyIgnoringErrors(object, this.fileNameSlot, file.getName());
e.printStackTrace();
}
setPropertyIgnoringErrors(object, this.fileSizeSlot, file.getSize());
setPropertyIgnoringErrors(object, this.fileContentTypeSlot, file.getContentType());
}
}
private void setPropertyIgnoringErrors(Object object, String property, Object value) {
if (property == null) {
return;
}
try {
PropertyUtils.setProperty(object, property, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static class FileConverter extends Converter {
private HtmlInputFile component;
public FileConverter(HtmlInputFile file) {
this.component = file;
}
@Override
public Object convert(Class type, Object value) {
String name = this.component.getName();
UploadedFile file = RenderersRequestProcessorImpl.getUploadedFile(name);
if (file == null) {
return null;
} else {
try {
return file.getInputStream();
} catch (IOException e) {
throw new ConversionException("renderers.converter.file.obtain", e, true, (Object[]) null);
}
}
}
}
}