Ported to v14_Maintenance branch - 350359: FileUploadReceiver does not pass filename extension
https://bugs.eclipse.org/bugs/show_bug.cgi?id=350359
diff --git a/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/DiskFileUploadReceiver.java b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/DiskFileUploadReceiver.java
index a127149..e34feee 100644
--- a/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/DiskFileUploadReceiver.java
+++ b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/DiskFileUploadReceiver.java
@@ -21,11 +21,13 @@
  * A file upload receiver that stores received files on disk.
  */
 public class DiskFileUploadReceiver extends FileUploadReceiver {
+  
+  private static final String DEFAULT_TARGET_FILE_NAME = "upload.tmp";
 
   private File targetFile;
 
-  public void receive( InputStream dataStream ) throws IOException {
-    File targetFile = createTargetFile();
+  public void receive( InputStream dataStream, IFileUploadDetails details ) throws IOException {
+    File targetFile = createTargetFile( details );
     FileOutputStream outputStream = new FileOutputStream( targetFile );
     try {
       copy( dataStream, outputStream );
@@ -47,10 +49,25 @@
   /**
    * Creates a file to save the received data to. Subclasses may override.
    *
+   * @param details the details of the uploaded file like file name, content-type and size
    * @return the file to store the data in
    */
-  protected File createTargetFile() throws IOException {
-    return File.createTempFile( "upload.", ".tmp" );
+  protected File createTargetFile( IFileUploadDetails details ) throws IOException {
+    String fileName = DEFAULT_TARGET_FILE_NAME;
+    if( details != null && details.getFileName() != null ) {
+      fileName = details.getFileName();
+    }
+    return File.createTempFile( createPrefix( fileName ), createSuffix( fileName ) );
+  }
+
+  private String createPrefix( String fileName ) {
+    int dotIndex = fileName.lastIndexOf( '.' );
+    return dotIndex == -1 ? fileName : fileName.substring( 0, dotIndex + 1 );
+  }
+
+  private String createSuffix( String fileName ) {
+    int dotIndex = fileName.lastIndexOf( '.' );
+    return dotIndex == -1 ? null : fileName.substring( dotIndex );
   }
 
   private static void copy( InputStream inputStream, OutputStream outputStream )
diff --git a/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadDetails.java b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadDetails.java
new file mode 100644
index 0000000..b6b10f0
--- /dev/null
+++ b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadDetails.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2011 EclipseSource and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    EclipseSource - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rap.rwt.supplemental.fileupload;
+
+
+/**
+ * This class provides information on a file upload.
+ */
+public final class FileUploadDetails implements IFileUploadDetails {
+
+  private final String fileName;
+  private final String contentType;
+  private final long contentLength;
+
+  public FileUploadDetails( String fileName, String contentType, long contentLength ) {
+    this.fileName = fileName;
+    this.contentType = contentType;
+    this.contentLength = contentLength;
+  }
+
+  public String getFileName() {
+    return fileName;
+  }
+
+  public String getContentType() {
+    return contentType;
+  }
+
+  public long getContentLength() {
+    return contentLength;
+  }
+}
diff --git a/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadReceiver.java b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadReceiver.java
index 76970b2..ed31a83 100644
--- a/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadReceiver.java
+++ b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadReceiver.java
@@ -22,9 +22,11 @@
 
   /**
    * Reads and processes all data from the provided input stream.
-   * 
+   *
    * @param dataStream the stream to read from
+   * @param details the details of the uploaded file like file name, content-type and size
    * @throws IOException if an input / output error occurs
    */
-  public abstract void receive( InputStream dataStream ) throws IOException;
+  public abstract void receive( InputStream dataStream, IFileUploadDetails details )
+    throws IOException;
 }
diff --git a/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/IFileUploadDetails.java b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/IFileUploadDetails.java
new file mode 100644
index 0000000..508f120
--- /dev/null
+++ b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/IFileUploadDetails.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2011 EclipseSource and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    EclipseSource - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.rap.rwt.supplemental.fileupload;
+
+
+public interface IFileUploadDetails {
+
+  /**
+   * The content type as transmitted by the uploading client.
+   *
+   * @return the content type or <code>null</code> if unknown
+   */
+  String getContentType();
+
+  /**
+   * The total number of bytes which are expected in total, as transmitted by the uploading client.
+   * May be unknown.
+   *
+   * @return the content length in bytes or -1 if unknown
+   */
+  long getContentLength();
+
+  /**
+   * The original file name of the uploaded file, as transmitted by the client. If a path was
+   * included in the request, it is stripped off.
+   *
+   * @return the plain file name without any path segments
+   */
+  String getFileName();
+}
diff --git a/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/internal/FileUploadProcessor.java b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/internal/FileUploadProcessor.java
index f791c76..53df2dc 100644
--- a/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/internal/FileUploadProcessor.java
+++ b/bundles/org.eclipse.rap.rwt.supplemental.fileupload/src/org/eclipse/rap/rwt/supplemental/fileupload/internal/FileUploadProcessor.java
@@ -22,8 +22,10 @@
 import org.apache.commons.fileupload.disk.DiskFileItem;
 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.eclipse.rap.rwt.supplemental.fileupload.FileUploadDetails;
 import org.eclipse.rap.rwt.supplemental.fileupload.FileUploadHandler;
 import org.eclipse.rap.rwt.supplemental.fileupload.FileUploadReceiver;
+import org.eclipse.rap.rwt.supplemental.fileupload.IFileUploadDetails;
 
 
 final class FileUploadProcessor {
@@ -42,10 +44,14 @@
     try {
       DiskFileItem fileItem = readUploadedFileItem( request );
       if( fileItem != null ) {
-        tracker.setContentType( fileItem.getContentType() );
-        tracker.setFileName( stripFileName( fileItem.getName() ) );
+        String fileName = stripFileName( fileItem.getName() );
+        String contentType = fileItem.getContentType();
+        long contentLength = fileItem.getSize();
+        tracker.setFileName( fileName );
+        tracker.setContentType( contentType );
         FileUploadReceiver receiver = handler.getReceiver();
-        receiver.receive( fileItem.getInputStream() );
+        IFileUploadDetails details = new FileUploadDetails( fileName, contentType, contentLength );
+        receiver.receive( fileItem.getInputStream(), details );
         tracker.handleFinished();
       } else {
         String errorMessage = "No file upload data found in request";
diff --git a/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/DiskFileUploadReceiver_Test.java b/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/DiskFileUploadReceiver_Test.java
index bd0d35d..8054ab7 100644
--- a/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/DiskFileUploadReceiver_Test.java
+++ b/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/DiskFileUploadReceiver_Test.java
@@ -39,17 +39,20 @@
   public void testCreateTargetFile() throws IOException {
     DiskFileUploadReceiver receiver = new DiskFileUploadReceiver();
 
-    createdFile = receiver.createTargetFile();
+    IFileUploadDetails details = new FileUploadDetails( "foo.bar", "text/plain", 5 );
+    createdFile = receiver.createTargetFile( details );
 
     assertTrue( createdFile.exists() );
-    assertTrue( createdFile.getAbsolutePath().endsWith( ".tmp" ) );
+    assertTrue( createdFile.getName().startsWith( "foo." ) );
+    assertTrue( createdFile.getName().endsWith( ".bar" ) );
   }
 
   public void testCreatedTargetFilesDiffer() throws IOException {
     DiskFileUploadReceiver receiver = new DiskFileUploadReceiver();
 
-    createdFile = receiver.createTargetFile();
-    File createdFile2 = receiver.createTargetFile();
+    IFileUploadDetails details = new FileUploadDetails( "foo.bar", "text/plain", 5 );
+    createdFile = receiver.createTargetFile( details );
+    File createdFile2 = receiver.createTargetFile( details );
     createdFile2.deleteOnExit();
 
     assertFalse( createdFile.getAbsolutePath().equals( createdFile2.getAbsolutePath() ) );
@@ -59,11 +62,26 @@
     DiskFileUploadReceiver receiver = new DiskFileUploadReceiver();
     String content = "Hello world!";
 
-    receiver.receive( new ByteArrayInputStream( content.getBytes() ) );
+    IFileUploadDetails details = new FileUploadDetails( "foo.bar", "text/plain", content.length() );
+    receiver.receive( new ByteArrayInputStream( content.getBytes() ), details );
     createdFile = receiver.getTargetFile();
 
     assertNotNull( createdFile );
     assertTrue( createdFile.exists() );
     assertEquals( content, FileUploadTestUtil.getFileContents( createdFile ) );
   }
+
+  public void testReceiveWithNullDetails() throws IOException {
+    DiskFileUploadReceiver receiver = new DiskFileUploadReceiver();
+    String content = "Hello world!";
+
+    receiver.receive( new ByteArrayInputStream( content.getBytes() ), null );
+    createdFile = receiver.getTargetFile();
+
+    assertNotNull( createdFile );
+    assertTrue( createdFile.exists() );
+    assertTrue( createdFile.getName().startsWith( "upload." ) );
+    assertTrue( createdFile.getName().endsWith( ".tmp" ) );
+    assertEquals( content, FileUploadTestUtil.getFileContents( createdFile ) );
+  }
 }
diff --git a/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadHandler_Test.java b/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadHandler_Test.java
index e54ec4b..2dbe4d0 100644
--- a/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadHandler_Test.java
+++ b/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/FileUploadHandler_Test.java
@@ -170,7 +170,7 @@
 
   public void testUploadWithException() throws Exception {
     FileUploadReceiver receiver = new FileUploadReceiver() {
-      public void receive( InputStream dataStream ) throws IOException {
+      public void receive( InputStream dataStream, IFileUploadDetails details ) throws IOException {
         throw new IOException( "the error message" );
       }
     };
diff --git a/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/test/TestFileUploadReceiver.java b/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/test/TestFileUploadReceiver.java
index a28b564..efcdb49 100644
--- a/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/test/TestFileUploadReceiver.java
+++ b/tests/org.eclipse.rap.rwt.supplemental.fileupload.test/src/org/eclipse/rap/rwt/supplemental/fileupload/test/TestFileUploadReceiver.java
@@ -1,11 +1,12 @@
 /*******************************************************************************
- * Copyright (c) 2011 EclipseSource and others. All rights reserved.
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution, 
- * and is available at http://www.eclipse.org/legal/epl-v10.html
+ * Copyright (c) 2011 EclipseSource and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
- *   EclipseSource - initial API and implementation
+ *    EclipseSource - initial API and implementation
  ******************************************************************************/
 package org.eclipse.rap.rwt.supplemental.fileupload.test;
 
@@ -14,6 +15,7 @@
 import java.io.InputStream;
 
 import org.eclipse.rap.rwt.supplemental.fileupload.FileUploadReceiver;
+import org.eclipse.rap.rwt.supplemental.fileupload.IFileUploadDetails;
 
 
 public class TestFileUploadReceiver extends FileUploadReceiver {
@@ -21,7 +23,7 @@
   long total = 0;
   private byte[] uploadedContent;
   
-  public void receive( InputStream dataStream ) throws IOException {
+  public void receive( InputStream dataStream, IFileUploadDetails details ) throws IOException {
 
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     byte[] buffer = new byte[ 4096 ];