Author: wesw Date: Wed Jun 3 21:30:06 2009 New Revision: 781587 URL: http://svn.apache.org/viewvc?rev=781587&view=rev Log: first commit, wanted to get it in before leaving, still need to add a struts-plugin.xml file that wires the beans together and then build an action that demonstrates ajax usage with a progress bar
Added: struts/sandbox/trunk/struts2-fileupload-plugin/ struts/sandbox/trunk/struts2-fileupload-plugin/pom.xml struts/sandbox/trunk/struts2-fileupload-plugin/src/ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/BasicProgressListener.java struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/DiskFileItemFactoryWrapper.java struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/EnhancedJakartaMultiPartRequest.java struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileItemFactoryWrapper.java struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileUploadConstants.java struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatus.java struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatusHolder.java struts/sandbox/trunk/struts2-fileupload-plugin/src/main/resources/ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/BasicProgressListenerTest.java struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusHolderTest.java struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusTest.java struts/sandbox/trunk/struts2-fileupload-plugin/src/test/resources/ Added: struts/sandbox/trunk/struts2-fileupload-plugin/pom.xml URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/pom.xml?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/pom.xml (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/pom.xml Wed Jun 3 21:30:06 2009 @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<!-- + $Id$ + + 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. +--> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.struts</groupId> + <artifactId>struts2-plugins</artifactId> + <version>2.1.7-SNAPSHOT</version> + </parent> + <groupId>struts2-fileupload-plugin</groupId> + <artifactId>struts2-fileupload-plugin</artifactId> + <version>1.0-SNAPSHOT</version> + <name>Struts 2 Advanced File Upload Plugin</name> + <packaging>jar</packaging> + <dependencies> + <dependency> + <groupId>commons-fileupload</groupId> + <artifactId>commons-fileupload</artifactId> + <version>1.2.1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.struts</groupId> + <artifactId>struts2-core</artifactId> + <version>2.1.7-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.4</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <version>2.4</version> + <scope>provided</scope> + </dependency> + <!-- I need the following for the mock objects to work --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring</artifactId> + <version>2.5.6</version> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <defaultGoal>install</defaultGoal> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-idea-plugin</artifactId> + <configuration> + <jdkName>1.5</jdkName> + <exclude>target,test-output,.clover</exclude> + <useFullNames>false</useFullNames> + </configuration> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.5</source> + <target>1.5</target> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/BasicProgressListener.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/BasicProgressListener.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/BasicProgressListener.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/BasicProgressListener.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,80 @@ +/* + * $Id$ + * + * 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. + */ + +package org.apache.struts2.fileupload; + +import org.apache.commons.fileupload.ProgressListener; +import org.apache.struts2.ServletActionContext; +import com.opensymphony.xwork2.inject.Inject; + +/** + * Just a simple ProgressListener for Jakarta FileUpload. It will store + * file progress in a HashMap that gets cleaned out once in a while. + * The HashMap will key the upload status off of the HttpSession.getId(), + * which means that you can't have multiple uploads going to the same + * server from different browser windows or tabs. + * + * @author Wes W + */ +public class BasicProgressListener implements ProgressListener { + + private int updateFrequency = 2048; // magic number for a default + private UploadStatusHolder holder = new UploadStatusHolder(); + private long lastUpdate = -1L; // + + /** + * + * @param updateFrequency + */ + @Inject(FileUploadConstants.LISTENER_UPDATE_FREQUENCY) + public void setUpdateFrequency(String updateFrequency) { + try { + this.updateFrequency = Integer.parseInt(updateFrequency); + } + catch (NumberFormatException nfe) { + // come on people, how hard is it to specify an integer + // if you flubbed it up, you can get the default + } + } + + /** + * + * @param bytesRead + * @param contentLength + * @param item + */ + public void update(long bytesRead, long contentLength, int item) { + if ( bytesRead / updateFrequency > lastUpdate) { + lastUpdate = bytesRead / updateFrequency; + if (lastUpdate == 0 ) { + // we could get stuck here if we leave it + lastUpdate = 1L; + } + // I wonder if this will ever NPE + String sessionId = ServletActionContext.getRequest().getSession(true).getId(); + UploadStatus status = new UploadStatus(); + status.setBytesRead(bytesRead); + status.setContentLength(contentLength); + status.setItem(item); + holder.addUploadStatus(sessionId, status); + } + } +} Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/DiskFileItemFactoryWrapper.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/DiskFileItemFactoryWrapper.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/DiskFileItemFactoryWrapper.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/DiskFileItemFactoryWrapper.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,120 @@ +/* + * $Id$ + * + * 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. + */ +package org.apache.struts2.fileupload; + +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.FileItemFactory; +import com.opensymphony.xwork2.inject.Inject; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * This class basically wraps the DiskFileItemFactory which is the + * default FileItemFactory for Jakarta FileUpload. The threshold + * setting specifies how large a file can get before it gets flushed + * from memory onto disk. + * + * TODO: Someone mentioned that google app engine won't let you + * write to the filesystem. It should be documented that you could + * potentially set the threshold to match your max upload size and then + * keep all files in memory. I don't know if it will work, since the + * MultiPartRequest interface insists that Files be used and I don't + * know what will happen, but it is worth trying. + * + * @author Wes W + */ +public class DiskFileItemFactoryWrapper implements FileItemFactoryWrapper { + + protected DiskFileItemFactory factory; + + /** + * + * @param sizeThreshold + * @param repositoryPath + */ + public DiskFileItemFactoryWrapper( + @Inject(FileUploadConstants.SIZE_THRESHOLD) + String sizeThreshold, + @Inject(FileUploadConstants.FILE_REPOSITORY_PATH) + String repositoryPath ) { + + int threshold ; + try { + threshold = Integer.parseInt(sizeThreshold); + } + catch (NumberFormatException nfe) { + // how hard is it to specify a valid integer? + } + finally { + threshold = 256; // I guess this is a magic number + } + + File repoPath = convertStringToFile(repositoryPath); + + factory = new DiskFileItemFactory(threshold, repoPath); + } + + /** + * + * @return + */ + public FileItemFactory getFileItemFactory() { + return factory; + } + + /** + * + * @param threshold + */ + public void setSizeThreshold(int threshold) { + this.factory.setSizeThreshold(threshold); + } + + /** + * + * @param repo + */ + public void setRepositoryPath(String repo) { + this.factory.setRepository(convertStringToFile(repo)); + } + + private File convertStringToFile(String path) { + File repoPath = new File(path); + if (repoPath == null || !repoPath.isDirectory()) { + File tempFile = null; + try { + tempFile = File.createTempFile("",""); + } + catch (IOException ioe) { + // I guess we're just sort of screwed, punt + repoPath = null; + } + if (tempFile != null ) { + repoPath = tempFile.getParentFile(); + tempFile.delete(); + } + } + return repoPath; + } + +} Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/EnhancedJakartaMultiPartRequest.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/EnhancedJakartaMultiPartRequest.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/EnhancedJakartaMultiPartRequest.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/EnhancedJakartaMultiPartRequest.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,189 @@ +/* + * $Id$ + * + * 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. + */ +package org.apache.struts2.fileupload; + +import org.apache.struts2.dispatcher.multipart.MultiPartRequest; +import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest; +import org.apache.commons.fileupload.ProgressListener; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.FileUpload; +import org.apache.commons.fileupload.RequestContext; +import org.apache.commons.fileupload.portlet.PortletFileUpload; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.ArrayList; + +import com.opensymphony.xwork2.util.logging.Logger; +import com.opensymphony.xwork2.util.logging.LoggerFactory; +import com.opensymphony.xwork2.inject.Inject; + +/** + * Using Jakarta Commons File Upload, handle multipart requests. This class + * acts mostly the same as the original JakartaMultiPartRequest. + * + * @author WesW + */ +public class EnhancedJakartaMultiPartRequest + extends JakartaMultiPartRequest + implements MultiPartRequest { + + static final Logger LOG = LoggerFactory.getLogger(MultiPartRequest.class); + + protected ProgressListener progressListener; + protected FileItemFactory fileItemFactory; + protected boolean portletUpload; + + /** + * + * @param progressListener + */ + @Inject(FileUploadConstants.PROGRESS_LISTENER) + public void setProgressListener(ProgressListener progressListener) { + this.progressListener = progressListener; + } + + /** + * + * @param fileItemFactory + */ + @Inject(FileUploadConstants.FILE_ITEM_FACTORY) + public void setFileItemFactory(FileItemFactory fileItemFactory) { + this.fileItemFactory = fileItemFactory; + } + + /** + * + * @param portletUpload + */ + @Inject(FileUploadConstants.IS_PORTLET) + public void setPortletUpload(String portletUpload) { + this.portletUpload = "true".equalsIgnoreCase(portletUpload); + } + + /** + * + * @param request + * @param saveDir + * @throws IOException + */ + public void parse(HttpServletRequest request, String saveDir) throws IOException { + // Parse the request mostly copy/paste from JakartaMuliPartRequest + try { + + FileUpload upload ; + if (portletUpload) { + upload = new PortletFileUpload(fileItemFactory); + } + else { + upload = new ServletFileUpload(fileItemFactory); + } + + upload.setSizeMax(maxSize); + upload.setProgressListener(progressListener); + + List items = upload.parseRequest(createRequestContext(request)); + + for (Object item1 : items) { + FileItem item = (FileItem) item1; + if (LOG.isDebugEnabled()) LOG.debug("Found item " + item.getFieldName()); + if (item.isFormField()) { + LOG.debug("Item is a normal form field"); + List<String> values; + if (params.get(item.getFieldName()) != null) { + values = params.get(item.getFieldName()); + } else { + values = new ArrayList<String>(); + } + + // note: see http://jira.opensymphony.com/browse/WW-633 + // basically, in some cases the charset may be null, so + // we're just going to try to "other" method (no idea if this + // will work) + String charset = request.getCharacterEncoding(); + if (charset != null) { + values.add(item.getString(charset)); + } else { + values.add(item.getString()); + } + params.put(item.getFieldName(), values); + } else { + LOG.debug("Item is a file upload"); + + // Skip file uploads that don't have a file name - meaning that no file was selected. + if (item.getName() == null || item.getName().trim().length() < 1) { + LOG.debug("No file has been uploaded for the field: " + item.getFieldName()); + continue; + } + + List<FileItem> values; + if (files.get(item.getFieldName()) != null) { + values = files.get(item.getFieldName()); + } else { + values = new ArrayList<FileItem>(); + } + + values.add(item); + files.put(item.getFieldName(), values); + } + } + } catch (FileUploadException e) { + LOG.warn("Unable to parse request", e); + errors.add(e.getMessage()); + } + } + + /** + * Creates a RequestContext needed by Jakarta Commons Upload. + * (copy/pasta from JakartaMultiPartRequest) + * + * @param req the request. + * @return a new request context. + */ + private RequestContext createRequestContext(final HttpServletRequest req) { + return new RequestContext() { + public String getCharacterEncoding() { + return req.getCharacterEncoding(); + } + + public String getContentType() { + return req.getContentType(); + } + + public int getContentLength() { + return req.getContentLength(); + } + + public InputStream getInputStream() throws IOException { + InputStream in = req.getInputStream(); + if (in == null) { + throw new IOException("Missing content in the request"); + } + return req.getInputStream(); + } + }; + } +} Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileItemFactoryWrapper.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileItemFactoryWrapper.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileItemFactoryWrapper.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileItemFactoryWrapper.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,35 @@ +/* + * $Id$ + * + * 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. + */ +package org.apache.struts2.fileupload; + +import org.apache.commons.fileupload.FileItemFactory; + +/** + * Quick interface to allow DiskFileItemFactoryWrapper to be + * wired in or replaced. + * + * @author Wes W + */ +public interface FileItemFactoryWrapper { + + public FileItemFactory getFileItemFactory(); + +} Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileUploadConstants.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileUploadConstants.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileUploadConstants.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/FileUploadConstants.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,65 @@ +/* + * $Id$ + * + * 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. + */ +package org.apache.struts2.fileupload; + +/** + * Holder for constants + * + * @author Wes Wannemacher + */ +public final class FileUploadConstants { + + /** + * + */ + public static final String PROGRESS_LISTENER = "struts.fileuploadplugin.progressListener"; + + /** + * + */ + public static final String FILE_ITEM_FACTORY = "struts.fileuploadplugin.fileitemfactory"; + + /** + * + */ + public static final String SIZE_THRESHOLD = "struts.fileuploadplugin.sizethreshold"; + + /** + * + */ + public static final String FILE_REPOSITORY_PATH = "struts.fileuploadplugin.repositorypath"; + + /** + * + */ + public static final String IS_PORTLET = "struts.fileuploadplugin.isportletupload"; + + /** + * + */ + public static final String LISTENER_UPDATE_FREQUENCY = "struts.fileuploadplugin.listenerupdatefrequency"; + + /** + * + */ + public static final String TIME_TO_KEEP_STATUS = "struts.fileupload.timetokeepstatus"; + +} Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatus.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatus.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatus.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatus.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,110 @@ +/* + * $Id$ + * + * 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. + */ +package org.apache.struts2.fileupload; + +import java.util.Calendar; + +/** + * POJO for holding the status of a running upload. Instance access + * time is recorded to allow for simple cleanup. + * + * @author Wes W + */ +public class UploadStatus { + + private long lastAccess ; + private long bytesRead ; + private long contentLength ; + private long item ; + + /** + * + */ + public UploadStatus() { + updateLastAccess() ; + bytesRead = 0; + contentLength = 0; + item = 0; + } + + /** + * + */ + public long getLastAccess() { + return lastAccess; + } + + /** + * + */ + public long getBytesRead() { + updateLastAccess(); + return bytesRead; + } + + /** + * + */ + public void setBytesRead(long bytesRead) { + updateLastAccess(); + this.bytesRead = bytesRead; + } + + /** + * + */ + public long getContentLength() { + updateLastAccess(); + return contentLength; + } + + /** + * + */ + public void setContentLength(long contentLength) { + updateLastAccess(); + this.contentLength = contentLength; + } + + /** + * + */ + public long getItem() { + updateLastAccess(); + return item; + } + + /** + * + */ + public void setItem(long item) { + updateLastAccess(); + this.item = item; + } + + /** + * + */ + private void updateLastAccess() { + lastAccess = Calendar.getInstance().getTimeInMillis() / 1000 ; + } + +} Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatusHolder.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatusHolder.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatusHolder.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/main/java/org/apache/struts2/fileupload/UploadStatusHolder.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,91 @@ +/* + * $Id$ + * + * 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. + */ +package org.apache.struts2.fileupload; + +import com.opensymphony.xwork2.inject.Inject; + +import java.util.Map; +import java.util.HashMap; +import java.util.Calendar; +import java.util.ArrayList; +import java.util.List; + +/** + * The UploadStatusHolder simply holds UploadStatuses. It will + * clean them up if an UploadStatus has not been accessed within + * the configured amount of time (in seconds). + * + * @author Wes W + */ +public class UploadStatusHolder { + + private int secondsToKeep = 600 ; //default to ten minutes + public static Map<String,UploadStatus> statuses = new HashMap<String,UploadStatus>(); + + private long lastRun = 0; // keep track so we aren't cleaning up all the time + + /** + * + * @param secondsToKeep + */ + @Inject(FileUploadConstants.TIME_TO_KEEP_STATUS) + public void setSecondsToKeep(String secondsToKeep) { + try { + this.secondsToKeep = Integer.parseInt(secondsToKeep); + } + catch (NumberFormatException nfe) { + // come on people, how hard is it to specify an integer + // if you flubbed it up, you can get the default + } + } + + /** + * + * @param key + * @param status + */ + public void addUploadStatus(String key, UploadStatus status ) { + statuses.put(key,status); + } + + /** + * + * @param key + * @return + */ + public UploadStatus getUploadStatus(String key) { + long now = Calendar.getInstance().getTimeInMillis() / 1000 ; + if ( now - lastRun > secondsToKeep) { + // time to clean up + List<String> keys2del = new ArrayList<String>(); + for (String cleanUpKey : statuses.keySet()) { + if ( now - statuses.get(cleanUpKey).getLastAccess() > secondsToKeep ) { + keys2del.add(cleanUpKey); + } + } + for (String key2del : keys2del) { + statuses.remove(key2del); + } + } + + return statuses.get(key); + } +} Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/BasicProgressListenerTest.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/BasicProgressListenerTest.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/BasicProgressListenerTest.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/BasicProgressListenerTest.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,117 @@ +/* + * $Id$ + * + * 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. + */ + +package org.apache.struts2.fileupload; + +import org.junit.Test; +import org.junit.Before; +import static org.junit.Assert.assertTrue; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.StrutsStatics; +import org.springframework.mock.web.MockServletContext; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import com.opensymphony.xwork2.ActionContext; + +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.HashMap; + +/** + * Unit test for BasicProgressListener + * + * @author Wes W + */ +public class BasicProgressListenerTest implements StrutsStatics { + + ActionContext actionContext; + // ServletActionContext servletActionContext; + private MockServletContext servletContext; + private HttpServletRequest request; + private HttpServletResponse response; + + /** + * + */ + @Before + public void setUp() { + Map extraContext = new HashMap(); + + servletContext = new MockServletContext(); + + request = new MockHttpServletRequest(); + response = new MockHttpServletResponse(); + + extraContext.put(HTTP_REQUEST, request); + extraContext.put(HTTP_RESPONSE, response); + extraContext.put(SERVLET_CONTEXT, servletContext); + + actionContext = new ActionContext(extraContext); + ServletActionContext.setContext(actionContext); + } + + /** + * + */ + @Test + public void testUpdate() { + BasicProgressListener listener = new BasicProgressListener(); + listener.setUpdateFrequency("1"); + listener.update(10L,10L,1); + + UploadStatusHolder holder = new UploadStatusHolder(); + + String key = request.getSession().getId(); + System.err.println("key - " + key); + + UploadStatus status = holder.getUploadStatus(key ); + + assertTrue(status.getBytesRead() == 10L); + assertTrue(status.getContentLength() == 10L); + assertTrue(status.getItem() == 1); + } + + /** + * + */ + @Test + public void testDontUpdate() { + BasicProgressListener listener = new BasicProgressListener(); + // listener.setUpdateFrequency("1000"); // let default of 2048 take over + listener.update(10L,10L,1); + listener.update(100L,100L,1); + + UploadStatusHolder holder = new UploadStatusHolder(); + + String key = request.getSession().getId(); + System.err.println("key - " + key); + + UploadStatus status = holder.getUploadStatus(key ); + + assertTrue(status.getBytesRead() == 10L); + assertTrue(status.getContentLength() == 10L); + assertTrue(status.getItem() == 1); + + } +} \ No newline at end of file Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusHolderTest.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusHolderTest.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusHolderTest.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusHolderTest.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,70 @@ +/* + * $Id$ + * + * 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. + */ +package org.apache.struts2.fileupload; + +import org.junit.Test; +import static org.junit.Assert.assertTrue; + +/** + * Unit Test for UploadStatusHolder + * + * @author Wes W + */ +public class UploadStatusHolderTest { + + /** + * + */ + @Test + public void testStatusHolding() { + UploadStatusHolder holder1 = new UploadStatusHolder(); + UploadStatus status1 = new UploadStatus(); + status1.setBytesRead(1L); + status1.setContentLength(1L); + status1.setItem(1L); + holder1.addUploadStatus("status1",status1); + + UploadStatusHolder holder2 = new UploadStatusHolder(); + UploadStatus status2 = holder2.getUploadStatus("status1"); + + assertTrue(status1.getBytesRead() == status2.getBytesRead()); + assertTrue(status1.getContentLength() == status2.getContentLength()); + assertTrue(status1.getItem() == status2.getItem()); + } + + /** + * + * @throws Exception + */ + @Test + public void testStatusHoldingGetsRemoved() throws Exception { + UploadStatusHolder holder1 = new UploadStatusHolder(); + holder1.setSecondsToKeep("1"); + UploadStatus status1 = new UploadStatus(); + status1.setBytesRead(1L); + status1.setContentLength(1L); + status1.setItem(1L); + holder1.addUploadStatus("status1",status1); + Thread.sleep(5000L); + UploadStatus status2 = holder1.getUploadStatus("status1"); + assertTrue(status2 == null); + } +} Added: struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusTest.java URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusTest.java?rev=781587&view=auto ============================================================================== --- struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusTest.java (added) +++ struts/sandbox/trunk/struts2-fileupload-plugin/src/test/java/org/apache/struts2/fileupload/UploadStatusTest.java Wed Jun 3 21:30:06 2009 @@ -0,0 +1,50 @@ +/* + * $Id$ + * + * 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. + */ +package org.apache.struts2.fileupload; + +import org.junit.Test; +import static org.junit.Assert.assertTrue; + +/** + * Unit Test for UploadStatus + * + * @author Wes W + */ +public class UploadStatusTest { + + /** + * + * @throws Exception + */ + @Test + public void testLastAccessChange() throws Exception { + UploadStatus stat = new UploadStatus() ; + long firstAccess = stat.getLastAccess(); + stat.setBytesRead(1L); + stat.setContentLength(1L); + stat.setItem(1L); + Thread.sleep(5000L); + assertTrue(1 == stat.getBytesRead()); + assertTrue(1 == stat.getContentLength()); + assertTrue(1 == stat.getItem()); + assertTrue(firstAccess < stat.getLastAccess()); + } +}