Revision: 418
          http://svn.sourceforge.net/stripes/?rev=418&view=rev
Author:   tfenne
Date:     2006-09-25 19:39:52 -0700 (Mon, 25 Sep 2006)

Log Message:
-----------
Merge of r410:417 for various 1.4.x bug fixes.

Modified Paths:
--------------
    branches/1.4.x/stripes/src/net/sourceforge/stripes/action/FileBean.java
    
branches/1.4.x/stripes/src/net/sourceforge/stripes/action/RedirectResolution.java
    
branches/1.4.x/stripes/src/net/sourceforge/stripes/controller/DispatcherServlet.java
    branches/1.4.x/stripes/src/net/sourceforge/stripes/tag/InputHiddenTag.java
    branches/1.4.x/stripes/src/net/sourceforge/stripes/tag/WizardFieldsTag.java
    branches/1.4.x/stripes/src/net/sourceforge/stripes/util/CollectionUtil.java
    
branches/1.4.x/stripes/src/net/sourceforge/stripes/validation/SimpleError.java

Added Paths:
-----------
    branches/1.4.x/tests/src/net/sourceforge/stripes/action/
    branches/1.4.x/tests/src/net/sourceforge/stripes/action/FileBeanTests.java
    
branches/1.4.x/tests/src/net/sourceforge/stripes/util/CollectionUtilTest.java

Removed Paths:
-------------
    branches/1.4.x/tests/src/net/sourceforge/stripes/action/FileBeanTests.java

Modified: 
branches/1.4.x/stripes/src/net/sourceforge/stripes/action/FileBean.java
===================================================================
--- branches/1.4.x/stripes/src/net/sourceforge/stripes/action/FileBean.java     
2006-09-26 02:36:42 UTC (rev 417)
+++ branches/1.4.x/stripes/src/net/sourceforge/stripes/action/FileBean.java     
2006-09-26 02:39:52 UTC (rev 418)
@@ -14,10 +14,7 @@
  */
 package net.sourceforge.stripes.action;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.FileInputStream;
+import java.io.*;
 
 /**
  * <p>Represents a file that was submitted as part of an HTTP POST request.  
Provides methods for
@@ -97,8 +94,10 @@
     }
 
     /**
-     * Saves the uploaded file to the location on disk represented by File.  
This is currently
-     * implemented as a simple rename of the underlying file that was created 
during upload.
+     * Saves the uploaded file to the location on disk represented by File.  
First attemps a
+     * simple rename of the underlying file that was created during upload as 
this is the
+     * most efficient route. If the rename fails an attempt is made to copy 
the file bit
+     * by bit to the new File and then the temporary file is removed.
      *
      * @param toFile a File object representing a location
      * @throws IOException if the save will fail for a reason that we can 
detect up front, for
@@ -119,22 +118,50 @@
                     + this.file.getAbsolutePath() + " - writability is 
required to move the file.");
         }
 
+        File parent = toFile.getAbsoluteFile().getParentFile();
         if (toFile.exists() && !toFile.canWrite()) {
             throw new IOException("Cannot overwrite existing file at "+ 
toFile.getAbsolutePath());
         }
-        else if (!toFile.exists() && 
!toFile.getAbsoluteFile().getParentFile().canWrite()) {
+        else if (!parent.exists() && !parent.mkdirs()) {
+            throw new IOException("Parent directory of specified file does not 
exist and cannot " +
+                " be created. File location supplied: " + 
toFile.getAbsolutePath());
+        }
+        else if (!toFile.exists() && !parent.canWrite()) {
             throw new IOException("Cannot create new file at location: " + 
toFile.getAbsolutePath());
         }
 
         this.saved = this.file.renameTo(toFile);
 
+        // If the rename didn't work, try copying the darn thing bit by bit
         if (this.saved == false) {
-            throw new IOException("Tried to save file [" + 
this.file.getAbsolutePath() + "] to file ["
-            + toFile.getAbsolutePath() + "but got a false from 
File.renameTo(File).");
+            saveViaCopy(toFile);
         }
     }
 
     /**
+     * Attempts to save the uploaded file to the specified file by performing 
a stream
+     * based copy. This is only used when a rename cannot be executed, e.g. 
because the
+     * target file is on a different file system than the temporary file.
+     *
+     * @param toFile the file to save to
+     */
+    protected void saveViaCopy(File toFile) throws IOException {
+        BufferedOutputStream out = new BufferedOutputStream(new 
FileOutputStream(toFile));
+        BufferedInputStream   in = new BufferedInputStream(new 
FileInputStream(this.file));
+
+        int b;
+        while ((b = in.read()) != -1) {
+            out.write(b);
+        }
+
+        in.close();
+        out.close();
+
+        this.file.delete();
+        this.saved = true;
+    }
+
+    /**
      * Deletes the temporary file associated with this file upload if one 
still exists.  If save()
      * has already been called then there is no temporary file any more, and 
this is a no-op.
      *

Modified: 
branches/1.4.x/stripes/src/net/sourceforge/stripes/action/RedirectResolution.java
===================================================================
--- 
branches/1.4.x/stripes/src/net/sourceforge/stripes/action/RedirectResolution.java
   2006-09-26 02:36:42 UTC (rev 417)
+++ 
branches/1.4.x/stripes/src/net/sourceforge/stripes/action/RedirectResolution.java
   2006-09-26 02:39:52 UTC (rev 418)
@@ -153,7 +153,7 @@
 
         // Prepend the context path if required
         String url = getUrl();
-        if (this.prependContext) {
+        if ( this.prependContext && !"/".equals(request.getContextPath()) ) {
             url = request.getContextPath() + url;
         }
 

Modified: 
branches/1.4.x/stripes/src/net/sourceforge/stripes/controller/DispatcherServlet.java
===================================================================
--- 
branches/1.4.x/stripes/src/net/sourceforge/stripes/controller/DispatcherServlet.java
        2006-09-26 02:36:42 UTC (rev 417)
+++ 
branches/1.4.x/stripes/src/net/sourceforge/stripes/controller/DispatcherServlet.java
        2006-09-26 02:39:52 UTC (rev 418)
@@ -131,8 +131,8 @@
 
 
             // Resolve the ActionBean, and if an interceptor returns a 
resolution, bail now
+            saveActionBean(request);
             Resolution resolution = resolveActionBean(ctx);
-            saveActionBean(request);
 
             if (resolution == null) {
                 resolution = resolveHandler(ctx);

Modified: 
branches/1.4.x/stripes/src/net/sourceforge/stripes/tag/InputHiddenTag.java
===================================================================
--- branches/1.4.x/stripes/src/net/sourceforge/stripes/tag/InputHiddenTag.java  
2006-09-26 02:36:42 UTC (rev 417)
+++ branches/1.4.x/stripes/src/net/sourceforge/stripes/tag/InputHiddenTag.java  
2006-09-26 02:39:52 UTC (rev 418)
@@ -94,24 +94,26 @@
         Object valueOrValues = getOverrideValueOrValues();
 
         // Figure out how many times to write it out
-        if (valueOrValues != null) {
-            if (valueOrValues.getClass().isArray()) {
-                for (Object value : (Object[]) valueOrValues) {
-                    getAttributes().put("value", format(value));
-                    writeSingletonTag(getPageContext().getOut(), "input");
-                }
+        if (valueOrValues == null) {
+            getAttributes().put("value", "");
+            writeSingletonTag(getPageContext().getOut(), "input");
+        }
+        else if (valueOrValues.getClass().isArray()) {
+            for (Object value : (Object[]) valueOrValues) {
+                getAttributes().put("value", format(value));
+                writeSingletonTag(getPageContext().getOut(), "input");
             }
-            else if (valueOrValues instanceof Collection) {
-                for (Object value : (Collection) valueOrValues) {
-                    getAttributes().put("value", format(value));
-                    writeSingletonTag(getPageContext().getOut(), "input");
-                }
-            }
-            else {
-                getAttributes().put("value", format(valueOrValues));
+        }
+        else if (valueOrValues instanceof Collection) {
+            for (Object value : (Collection) valueOrValues) {
+                getAttributes().put("value", format(value));
                 writeSingletonTag(getPageContext().getOut(), "input");
             }
         }
+        else {
+            getAttributes().put("value", format(valueOrValues));
+            writeSingletonTag(getPageContext().getOut(), "input");
+        }
 
         // Clear out the value from the attributes
         getAttributes().remove("value");

Modified: 
branches/1.4.x/stripes/src/net/sourceforge/stripes/tag/WizardFieldsTag.java
===================================================================
--- branches/1.4.x/stripes/src/net/sourceforge/stripes/tag/WizardFieldsTag.java 
2006-09-26 02:36:42 UTC (rev 417)
+++ branches/1.4.x/stripes/src/net/sourceforge/stripes/tag/WizardFieldsTag.java 
2006-09-26 02:39:52 UTC (rev 418)
@@ -14,14 +14,15 @@
  */
 package net.sourceforge.stripes.tag;
 
+import net.sourceforge.stripes.action.ActionBean;
 import net.sourceforge.stripes.controller.StripesConstants;
-import net.sourceforge.stripes.action.ActionBean;
 import net.sourceforge.stripes.exception.StripesJspException;
+import net.sourceforge.stripes.util.CollectionUtil;
 
 import javax.servlet.jsp.JspException;
+import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
-import java.util.HashSet;
-import java.util.Enumeration;
 
 /**
  * <p>Examines the request and include hidden fields for all parameters that 
have do
@@ -63,6 +64,7 @@
         excludes.addAll( form.getRegisteredFields() );
         excludes.add( StripesConstants.URL_KEY_SOURCE_PAGE );
         excludes.add( StripesConstants.URL_KEY_FIELDS_PRESENT );
+        excludes.add( StripesConstants.URL_KEY_EVENT_NAME );
 
         // Use the submitted action bean to eliminate any event related 
parameters
         ActionBean submittedActionBean = (ActionBean)
@@ -90,11 +92,12 @@
             hidden.setParent( getParent() );
 
             // Loop through the request parameters and output the values
-            Enumeration<String> parameterNames = 
getPageContext().getRequest().getParameterNames();
-            while ( parameterNames.hasMoreElements() ) {
-                String name = parameterNames.nextElement();
+            Map<String,String[]> params = 
getPageContext().getRequest().getParameterMap();
+            for (Map.Entry<String,String[]> entry : params.entrySet()) {
+                String name = entry.getKey();
+                String[] values = entry.getValue();
 
-                if ( !excludes.contains(name) ) {
+                if ( !excludes.contains(name) && !CollectionUtil.empty(values) 
 ) {
                     hidden.setName(name);
                     try {
                         hidden.doStartTag();

Modified: 
branches/1.4.x/stripes/src/net/sourceforge/stripes/util/CollectionUtil.java
===================================================================
--- branches/1.4.x/stripes/src/net/sourceforge/stripes/util/CollectionUtil.java 
2006-09-26 02:36:42 UTC (rev 417)
+++ branches/1.4.x/stripes/src/net/sourceforge/stripes/util/CollectionUtil.java 
2006-09-26 02:39:52 UTC (rev 418)
@@ -41,4 +41,18 @@
 
         return false;
     }
+
+    /**
+     * Checks to see if the array contains any values that are non-null non 
empty-string values.
+     * If it does, returns false.  Returns true for null arrays and zero 
length arrays, as well
+     * as for arrays consisting only of nulls and empty strings.
+     */
+    public static boolean empty(String[] arr) {
+        if (arr == null || arr.length == 0) return true;
+        for (String s : arr) {
+            if (s != null && !"".equals(s)) return false;
+        }
+
+        return true;
+    }
 }

Modified: 
branches/1.4.x/stripes/src/net/sourceforge/stripes/validation/SimpleError.java
===================================================================
--- 
branches/1.4.x/stripes/src/net/sourceforge/stripes/validation/SimpleError.java  
    2006-09-26 02:36:42 UTC (rev 417)
+++ 
branches/1.4.x/stripes/src/net/sourceforge/stripes/validation/SimpleError.java  
    2006-09-26 02:39:52 UTC (rev 418)
@@ -153,31 +153,24 @@
         return actionPath;
     }
 
-    /** Generated equals method that checks all fields for equality. */
+    /** Generated equals method that ensures the message, field, parameters 
and action path are all equal. */
     public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        if (!super.equals(o)) return false;
 
         final SimpleError that = (SimpleError) o;
 
-        if (actionPath != null ? !actionPath.equals(that.actionPath) : 
that.actionPath != null) {
-            return false;
-        }
-        if (fieldNameKey != null ? !fieldNameKey.equals(that.fieldNameKey) : 
that.fieldNameKey != null) {
-            return false;
-        }
+        if (actionPath != null ? !actionPath.equals(that.actionPath) : 
that.actionPath != null) return false;
+        if (fieldNameKey != null ? !fieldNameKey.equals(that.fieldNameKey) : 
that.fieldNameKey != null) return false;
 
         return true;
     }
 
-    /** Generated hashCode() method. */
+    /** Hashcode based on the message, field name key, action path and 
parameters. */
     public int hashCode() {
         int result = super.hashCode();
-        result = (fieldNameKey != null ? fieldNameKey.hashCode() : 0);
+        result = 29 * result + (fieldNameKey != null ? fieldNameKey.hashCode() 
: 0);
         result = 29 * result + (actionPath != null ? actionPath.hashCode() : 
0);
         return result;
     }

Copied: branches/1.4.x/tests/src/net/sourceforge/stripes/action (from rev 416, 
trunk/tests/src/net/sourceforge/stripes/action)

Deleted: 
branches/1.4.x/tests/src/net/sourceforge/stripes/action/FileBeanTests.java
===================================================================
--- trunk/tests/src/net/sourceforge/stripes/action/FileBeanTests.java   
2006-09-26 02:30:23 UTC (rev 416)
+++ branches/1.4.x/tests/src/net/sourceforge/stripes/action/FileBeanTests.java  
2006-09-26 02:39:52 UTC (rev 418)
@@ -1,105 +0,0 @@
-package net.sourceforge.stripes.action;
-
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.AfterMethod;
-import org.testng.Assert;
-
-import java.io.*;
-
-/**
- * Basic set of tests for the FileBean object.
- *
- * @author Tim Fennell
- */
-public class FileBeanTests {
-    public static final String[] LINES = {"Hello World!", "How have you 
been?"};
-    File from, to;
-
-    @BeforeMethod(alwaysRun=true)
-    public void setupFiles() throws IOException {
-        // The from file
-        this.from = File.createTempFile("foo", "bar");
-        FileWriter out = new FileWriter(this.from);
-        out.write(LINES[0]);
-        out.write('\n');
-        out.write(LINES[1]);
-        out.write('\n');
-        out.close();
-
-        // A to file
-        this.to = new File(System.getProperty("java.io.tmpdir"), "foo-" + 
System.currentTimeMillis());
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void cleanupFiles() {
-        if (this.from != null && this.from.exists()) this.from.delete();
-        if (this.to != null && this.to.exists()) this.to.delete();
-    }
-
-    /** Helper method to assert contents of post-copy file. */
-    private void assertContents(File toFile) throws IOException {
-        BufferedReader in = new BufferedReader(new FileReader(toFile));
-        Assert.assertEquals(in.readLine(), LINES[0]);
-        Assert.assertEquals(in.readLine(), LINES[1]);
-        Assert.assertNull(in.readLine());
-    }
-
-    @Test(groups="fast")
-    public void testBasicSave() throws Exception {
-        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
-
-        bean.save(this.to);
-        Assert.assertTrue(this.to.exists());
-        Assert.assertFalse(this.from.exists());
-        assertContents(this.to);
-    }
-
-    @Test(groups="fast")
-    public void testSaveByCopy() throws Exception {
-        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
-
-        bean.saveViaCopy(this.to);
-        Assert.assertTrue(this.to.exists());
-        Assert.assertFalse(this.from.exists());
-        assertContents(this.to);
-    }
-
-    @Test(groups="fast")
-    public void testSaveOverExistingFile() throws Exception {
-        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
-
-        Assert.assertTrue(this.to.createNewFile());
-        bean.save(this.to);
-        Assert.assertTrue(this.to.exists());
-        Assert.assertFalse(this.from.exists());
-        assertContents(this.to);
-    }
-
-    @Test(groups="fast")
-    public void testSaveOverExistingFileWithContents() throws Exception {
-        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
-
-        Assert.assertTrue(this.to.createNewFile());
-        BufferedWriter out = new BufferedWriter(new FileWriter(this.to));
-        out.write("This is not what we should read back after the save!\n");
-        out.write("If we get this text back we're in trouble!\n");
-        out.close();
-
-        bean.save(this.to);
-        Assert.assertTrue(this.to.exists());
-        Assert.assertFalse(this.from.exists());
-        assertContents(this.to);
-    }
-
-    @Test(groups="fast")
-    public void testIntoDirectoryThatDoesNotExistYet() throws Exception {
-        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
-        this.to = new File(this.to, "somechild.txt");
-
-        bean.save(this.to);
-        Assert.assertTrue(this.to.exists());
-        Assert.assertFalse(this.from.exists());
-        assertContents(this.to);
-    }
-}

Copied: 
branches/1.4.x/tests/src/net/sourceforge/stripes/action/FileBeanTests.java 
(from rev 416, 
trunk/tests/src/net/sourceforge/stripes/action/FileBeanTests.java)
===================================================================
--- branches/1.4.x/tests/src/net/sourceforge/stripes/action/FileBeanTests.java  
                        (rev 0)
+++ branches/1.4.x/tests/src/net/sourceforge/stripes/action/FileBeanTests.java  
2006-09-26 02:39:52 UTC (rev 418)
@@ -0,0 +1,105 @@
+package net.sourceforge.stripes.action;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.AfterMethod;
+import org.testng.Assert;
+
+import java.io.*;
+
+/**
+ * Basic set of tests for the FileBean object.
+ *
+ * @author Tim Fennell
+ */
+public class FileBeanTests {
+    public static final String[] LINES = {"Hello World!", "How have you 
been?"};
+    File from, to;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setupFiles() throws IOException {
+        // The from file
+        this.from = File.createTempFile("foo", "bar");
+        FileWriter out = new FileWriter(this.from);
+        out.write(LINES[0]);
+        out.write('\n');
+        out.write(LINES[1]);
+        out.write('\n');
+        out.close();
+
+        // A to file
+        this.to = new File(System.getProperty("java.io.tmpdir"), "foo-" + 
System.currentTimeMillis());
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void cleanupFiles() {
+        if (this.from != null && this.from.exists()) this.from.delete();
+        if (this.to != null && this.to.exists()) this.to.delete();
+    }
+
+    /** Helper method to assert contents of post-copy file. */
+    private void assertContents(File toFile) throws IOException {
+        BufferedReader in = new BufferedReader(new FileReader(toFile));
+        Assert.assertEquals(in.readLine(), LINES[0]);
+        Assert.assertEquals(in.readLine(), LINES[1]);
+        Assert.assertNull(in.readLine());
+    }
+
+    @Test(groups="fast")
+    public void testBasicSave() throws Exception {
+        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
+
+        bean.save(this.to);
+        Assert.assertTrue(this.to.exists());
+        Assert.assertFalse(this.from.exists());
+        assertContents(this.to);
+    }
+
+    @Test(groups="fast")
+    public void testSaveByCopy() throws Exception {
+        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
+
+        bean.saveViaCopy(this.to);
+        Assert.assertTrue(this.to.exists());
+        Assert.assertFalse(this.from.exists());
+        assertContents(this.to);
+    }
+
+    @Test(groups="fast")
+    public void testSaveOverExistingFile() throws Exception {
+        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
+
+        Assert.assertTrue(this.to.createNewFile());
+        bean.save(this.to);
+        Assert.assertTrue(this.to.exists());
+        Assert.assertFalse(this.from.exists());
+        assertContents(this.to);
+    }
+
+    @Test(groups="fast")
+    public void testSaveOverExistingFileWithContents() throws Exception {
+        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
+
+        Assert.assertTrue(this.to.createNewFile());
+        BufferedWriter out = new BufferedWriter(new FileWriter(this.to));
+        out.write("This is not what we should read back after the save!\n");
+        out.write("If we get this text back we're in trouble!\n");
+        out.close();
+
+        bean.save(this.to);
+        Assert.assertTrue(this.to.exists());
+        Assert.assertFalse(this.from.exists());
+        assertContents(this.to);
+    }
+
+    @Test(groups="fast")
+    public void testIntoDirectoryThatDoesNotExistYet() throws Exception {
+        FileBean bean = new FileBean(from, "text/plain", "somefile.txt");
+        this.to = new File(this.to, "somechild.txt");
+
+        bean.save(this.to);
+        Assert.assertTrue(this.to.exists());
+        Assert.assertFalse(this.from.exists());
+        assertContents(this.to);
+    }
+}

Copied: 
branches/1.4.x/tests/src/net/sourceforge/stripes/util/CollectionUtilTest.java 
(from rev 416, 
trunk/tests/src/net/sourceforge/stripes/util/CollectionUtilTest.java)
===================================================================
--- 
branches/1.4.x/tests/src/net/sourceforge/stripes/util/CollectionUtilTest.java   
                            (rev 0)
+++ 
branches/1.4.x/tests/src/net/sourceforge/stripes/util/CollectionUtilTest.java   
    2006-09-26 02:39:52 UTC (rev 418)
@@ -0,0 +1,46 @@
+package net.sourceforge.stripes.util;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * Tests for the CollectionUtil class
+ *
+ * @author Tim Fennell
+ */
+public class CollectionUtilTest {
+    @Test(groups="fast")
+    public void testEmptyOnNullCollection() {
+        Assert.assertTrue(CollectionUtil.empty(null));
+    }
+
+    @Test(groups="fast")
+    public void testEmptyOnCollectionOfNulls() {
+        Assert.assertTrue(CollectionUtil.empty(new String[] {null, null, 
null}));
+    }
+
+    @Test(groups="fast")
+    public void testEmptyZeroLengthCollection() {
+        Assert.assertTrue(CollectionUtil.empty(new String[] {}));
+    }
+
+    @Test(groups="fast")
+    public void testEmptyOnCollectionOfEmptyStrings() {
+        Assert.assertTrue(CollectionUtil.empty(new String[] {"", null, ""}));
+    }
+
+    @Test(groups="fast")
+    public void testEmptyOnNonEmptyCollection1() {
+        Assert.assertFalse(CollectionUtil.empty(new String[] {"", null, 
"foo"}));
+    }
+
+    @Test(groups="fast")
+    public void testEmptyOnNonEmptyCollection2() {
+        Assert.assertFalse(CollectionUtil.empty(new String[] {"bar"}));
+    }
+
+    @Test(groups="fast")
+    public void testEmptyOnNonEmptyCollection3() {
+        Assert.assertFalse(CollectionUtil.empty(new String[] {"bar", "splat", 
"foo"}));
+    }
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to