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());
+    }
+}


Reply via email to