/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.server.headlessclient; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import org.apache.wicket.IPageMap; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.markup.html.CSSPackageResource; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.upload.FileUpload; import org.apache.wicket.markup.html.form.upload.MultiFileUploadField; import org.apache.wicket.markup.html.internal.HtmlHeaderContainer; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.IWrapModel; import org.apache.wicket.model.Model; import org.apache.wicket.protocol.http.WebRequest; import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest; import org.apache.wicket.util.upload.DiskFileItem; import org.apache.wicket.util.upload.DiskFileItemFactory; import org.apache.wicket.util.upload.FileItem; import org.apache.wicket.util.upload.FileUploadException; import com.servoy.j2db.IApplication; import com.servoy.j2db.plugins.IMediaUploadCallback; import com.servoy.j2db.plugins.IUploadData; import com.servoy.j2db.scripting.info.WEBCONSTANTS; import com.servoy.j2db.server.headlessclient.dataui.RecordItemModel; import com.servoy.j2db.server.headlessclient.dataui.WebDataImgMediaField; import com.servoy.j2db.ui.IMediaFieldConstants; import com.servoy.j2db.util.Debug; import com.servoy.j2db.util.Settings; import com.servoy.j2db.util.Utils; /** * @author jcompagner * */ public class MediaUploadPage extends WebPage { private static final long serialVersionUID = 1L; private final SingleFileUpload fuf; private final MultiFileUploadField mfuf; /** * @param pageMap * @param model * @param dataProviderID */ @SuppressWarnings("nls") public MediaUploadPage(IPageMap pageMap, final RecordItemModel model, final WebDataImgMediaField field, final IApplication application) { super(pageMap); add(new PageContributor(application, "contribution")); mfuf = null; fuf = new SingleFileUpload("panel", application); Form form = new Form("form") { private static final long serialVersionUID = 1L; private boolean close = false; @Override protected void onSubmit() { FileUpload fu = fuf.getFileUpload(); if (fu != null) { // use the wrap model so that form variables also work. IWrapModel wrappedModel = model.wrapOnInheritance(field); wrappedModel.setObject(fu.getBytes()); field.getStylePropertyChanges().setChanged(); model.setValue(field, field.getDataProviderID() + IMediaFieldConstants.FILENAME, fu.getClientFileName()); String contentType = fu.getContentType(); model.setValue(field, field.getDataProviderID() + IMediaFieldConstants.MIMETYPE, contentType); } close = true; } /** * @see org.apache.wicket.Component#renderHead(org.apache.wicket.markup.html.internal.HtmlHeaderContainer) */ @Override public void renderHead(HtmlHeaderContainer container) { super.renderHead(container); if (close) { container.getHeaderResponse().renderOnLoadJavascript("window.opener.triggerAjaxUpdate();"); } } }; form.add(fuf); form.setMultiPart(true); add(form); FeedbackPanel panel = new FeedbackPanel("feedback"); //$NON-NLS-1$ add(panel); add(CSSPackageResource.getHeaderContribution( "/servoy-webclient/templates/" + application.getClientProperty(WEBCONSTANTS.WEBCLIENT_TEMPLATES_DIR) + "/servoy_web_client_default.css")); } @SuppressWarnings({ "nls", "unchecked" }) public MediaUploadPage(IPageMap pageMap, final IMediaUploadCallback callback, boolean multiSelect, final IApplication application) { super(pageMap); add(new PageContributor(application, "contribution")); Form form = new Form("form") { private static final long serialVersionUID = 1L; private boolean close = false; @Override protected void onSubmit() { close = true; if (fuf != null) { final FileUpload fu = fuf.getFileUpload(); if (fu != null) { IUploadData ud = new FileUploadData(fu); callback.uploadComplete(new IUploadData[] { ud }); } else { callback.uploadComplete(new IUploadData[0]); } } else if (mfuf != null) { Collection<FileUpload> uploads = mfuf.getModelObject(); if (uploads != null) { IUploadData[] data = new IUploadData[uploads.size()]; int counter = 0; for (FileUpload fileUpload : uploads) { data[counter++] = new FileUploadData(fileUpload); } callback.uploadComplete(data); } else { callback.uploadComplete(new IUploadData[0]); } } callback.onSubmit(); if (fuf != null) { remove(fuf); } else if (mfuf != null) { remove(mfuf); } add(new Label("panel", new Model<String>(application.getI18NMessage("servoy.filechooser.upload.finished")))); } @Override public void renderHead(HtmlHeaderContainer container) { super.renderHead(container); if (close) { container.getHeaderResponse().renderOnLoadJavascript("window.parent.triggerAjaxUpdate();"); } } @Override protected boolean handleMultiPart() { // Change the request to a multipart web request that is able to work with multiple file uploads for the same field nmae // so parameters are parsed out correctly as well try { final WebRequest req = ((WebRequest)getRequest()); MultipartServletWebRequest multipart; try { Settings settings = Settings.getInstance(); File fileUploadDir = null; String uploadDir = settings.getProperty("servoy.ng_web_client.temp.uploadir"); if (uploadDir != null) { fileUploadDir = new File(uploadDir); if (!fileUploadDir.exists() && !fileUploadDir.mkdirs()) { fileUploadDir = null; Debug.error("Couldn't use the property 'servoy.ng_web_client.temp.uploadir' value: '" + uploadDir + "', directory could not be created or doesn't exists"); } } int tempFileThreshold = Utils.getAsInteger(settings.getProperty("servoy.ng_web_client.tempfile.threshold", "50"), false) * 1000; multipart = new MultipartServletWebRequest(req.getHttpServletRequest(), getMaxSize(), new DiskFileItemFactory(tempFileThreshold, fileUploadDir) { private final HashSet<String> fieldNames = new HashSet<String>(); @Override public FileItem createItem(String fieldName, String contentType, boolean isFormField, String fileName) { String adjustedFieldName = fieldName; int i = 1; while (fieldNames.contains(adjustedFieldName)) { adjustedFieldName = fieldName + "_additionalFile_" + (i++); } String timestampStr = req.getParameter("last_modified_" + fieldName + "_" + fileName); long timestamp = System.currentTimeMillis(); if (timestampStr != null) { try { timestamp = Long.parseLong(timestampStr); } catch (NumberFormatException ex) { timestamp = System.currentTimeMillis(); } } fieldNames.add(adjustedFieldName); return new ServoyDiskFileItem(adjustedFieldName, contentType, isFormField, fileName, getSizeThreshold(), getRepository(), timestamp); } }); } catch (FileUploadException e) { throw new WicketRuntimeException(e); } multipart.setRequestParameters(req.getRequestParameters()); getRequestCycle().setRequest(multipart); return true; } catch (WicketRuntimeException wre) { if (wre.getCause() == null || !(wre.getCause() instanceof FileUploadException)) { throw wre; } FileUploadException e = (FileUploadException)wre.getCause(); // Create model with exception and maximum size values final Map<String, Object> model = new HashMap<String, Object>(); model.put("exception", e); model.put("maxSize", getMaxSize()); onFileUploadException((FileUploadException)wre.getCause(), model); // don't process the form if there is a FileUploadException return false; } } }; if (multiSelect) { fuf = null; IModel<Collection<FileUpload>> model = new Model(new ArrayList()); mfuf = new MultiFileUpload("panel", model, application); form.add(mfuf); } else { mfuf = null; fuf = new SingleFileUpload("panel", application); form.add(fuf); } form.add(new Label("uploadtitle", new Model<String>(application.getI18NMessage("servoy.filechooser.upload.title")))); form.setMultiPart(true); add(form); FeedbackPanel panel = new FeedbackPanel("feedback"); add(panel); add(CSSPackageResource.getHeaderContribution( "/servoy-webclient/templates/" + application.getClientProperty(WEBCONSTANTS.WEBCLIENT_TEMPLATES_DIR) + "/servoy_web_client_default.css")); } public static class ServoyDiskFileItem extends DiskFileItem { long timestamp = 0; public ServoyDiskFileItem(String fieldName, String contentType, boolean isFormField, String fileName, int sizeThreshold, File repository, long timestamp) { super(fieldName, contentType, isFormField, fileName, sizeThreshold, repository); this.timestamp = timestamp; } public long getLastModified() { return timestamp; } } public static class ServoyFileUpload extends FileUpload { FileItem diskItem = null; public ServoyFileUpload(FileItem item) { super(item); diskItem = item; } public long lastModified() { if (diskItem instanceof ServoyDiskFileItem) { return ((ServoyDiskFileItem)diskItem).getLastModified(); } return System.currentTimeMillis(); } /** * @return */ public File getFile() { if (diskItem instanceof DiskFileItem) { return ((DiskFileItem)diskItem).getStoreLocation(); } return null; } } private static final class FileUploadData implements IUploadData { private final FileUpload fu; private FileUploadData(FileUpload fu) { this.fu = fu; } public String getName() { String name = fu.getClientFileName(); name = name.replace('\\', '/'); String[] tokenized = name.split("/"); //$NON-NLS-1$ return tokenized[tokenized.length - 1]; } public String getContentType() { return fu.getContentType(); } public byte[] getBytes() { return fu.getBytes(); } /** * @see com.servoy.j2db.plugins.IUploadData#getFile() */ public File getFile() { if (fu instanceof ServoyFileUpload) { return ((ServoyFileUpload)fu).getFile(); } return null; } /* * (non-Javadoc) * * @see com.servoy.j2db.plugins.IUploadData#getInputStream() */ public InputStream getInputStream() throws IOException { return fu.getInputStream(); } @Override public long lastModified() { if (fu instanceof ServoyFileUpload) { return ((ServoyFileUpload)fu).lastModified(); } return System.currentTimeMillis(); } } }