diff --git a/.classpath b/.classpath
index 9c7e0033..d7c40778 100644
--- a/.classpath
+++ b/.classpath
@@ -1,9 +1,189 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.project b/.project
index 1388c7f6..1a99c044 100644
--- a/.project
+++ b/.project
@@ -1,23 +1,17 @@
-
- s3
- NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.maven.ide.eclipse.maven2Builder
-
-
-
-
-
- org.maven.ide.eclipse.maven2Nature
- org.eclipse.jdt.core.javanature
-
-
+ s3
+ NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+ org.maven.ide.eclipse.maven2Builder
+
+
+
+ org.maven.ide.eclipse.maven2Nature
+ org.eclipse.jdt.core.javanature
+
+
\ No newline at end of file
diff --git a/src/main/java/hudson/plugins/s3/Destination.java b/src/main/java/hudson/plugins/s3/Destination.java
new file mode 100644
index 00000000..8b73a54a
--- /dev/null
+++ b/src/main/java/hudson/plugins/s3/Destination.java
@@ -0,0 +1,39 @@
+package hudson.plugins.s3;
+
+
+/**
+ * Provides a way to construct a destination bucket name and object name based
+ * on the bucket name provided by the user.
+ *
+ * The convention implemented here is that a / in a bucket name is used to
+ * construct a structure in the object name. That is, a put of file.txt to bucket name
+ * of "mybucket/v1" will cause the object "v1/file.txt" to be created in the mybucket.
+ *
+ */
+public class Destination {
+ public final String bucketName;
+ public final String objectName;
+
+ public Destination(final String userBucketName, final String fileName) {
+
+ if (userBucketName == null || fileName == null)
+ throw new IllegalArgumentException("Not defined for null parameters: "+userBucketName+","+fileName);
+
+ final String[] bucketNameArray = userBucketName.split("/", 2);
+
+ bucketName = bucketNameArray[0];
+
+ if (bucketNameArray.length > 1) {
+ objectName = bucketNameArray[1] + "/" + fileName;
+ } else {
+ objectName = fileName;
+ }
+ }
+
+@Override
+ public String toString() {
+ return "Destination [bucketName="+bucketName+", objectName="+objectName+"]";
+ }
+
+
+}
diff --git a/src/main/java/hudson/plugins/s3/S3Profile.java b/src/main/java/hudson/plugins/s3/S3Profile.java
index e60fbcd1..46221ae5 100644
--- a/src/main/java/hudson/plugins/s3/S3Profile.java
+++ b/src/main/java/hudson/plugins/s3/S3Profile.java
@@ -1,14 +1,15 @@
package hudson.plugins.s3;
-import com.amazonaws.auth.BasicAWSCredentials;
-import com.amazonaws.services.s3.AmazonS3Client;
import hudson.FilePath;
-import org.kohsuke.stapler.DataBoundConstructor;
-import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
+import org.kohsuke.stapler.DataBoundConstructor;
+
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.services.s3.AmazonS3Client;
+
public class S3Profile {
private String name;
private String accessKey;
@@ -60,21 +61,23 @@ public AmazonS3Client getClient() {
public void check() throws Exception {
getClient().listBuckets();
}
-
+
+
+
public void upload(String bucketName, FilePath filePath) throws IOException, InterruptedException {
if (filePath.isDirectory()) {
throw new IOException(filePath + " is a directory");
}
- String[] bucketNameArray = bucketName.split("/", 2);
- String objectPath = filePath.getName();
- if (bucketNameArray.length > 1) {
- objectPath = bucketNameArray[1] + "/" + objectPath;
- }
+
+ final Destination dest = new Destination(bucketName,filePath.getName());
+
try {
- getClient().putObject(bucketNameArray[0], objectPath, filePath.read(), null);
+ getClient().putObject(dest.bucketName, dest.objectName, filePath.read(), /*metadata=*/null);
} catch (Exception e) {
- throw new IOException("put " + objectPath + " to bucket " + bucketNameArray[0] + ": " + e);
+ throw new IOException("put " + dest + ": " + e);
}
-
}
+
+
+
}
diff --git a/src/test/java/hudson/plugins/s3/BucketnameTest.java b/src/test/java/hudson/plugins/s3/BucketnameTest.java
new file mode 100644
index 00000000..0d61df10
--- /dev/null
+++ b/src/test/java/hudson/plugins/s3/BucketnameTest.java
@@ -0,0 +1,30 @@
+package hudson.plugins.s3;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class BucketnameTest {
+
+ @Test
+ public void testAnythingAfterSlashInBucketNameIsPrependedToObjectName() {
+
+ // Assertions based on the behaviour of toString is maybe fragile but I think
+ // reasonably readable.
+
+ assertEquals( "Destination [bucketName=my-bucket-name, objectName=test.txt]",
+ new Destination("my-bucket-name", "test.txt").toString() );
+
+ assertEquals( "Destination [bucketName=my-bucket-name, objectName=foo/test.txt]",
+ new Destination("my-bucket-name/foo", "test.txt").toString() );
+
+ assertEquals( "Destination [bucketName=my-bucket-name, objectName=foo/baz/test.txt]",
+ new Destination("my-bucket-name/foo/baz", "test.txt").toString() );
+
+ // Unclear if this is the desired behaviour or not:
+ assertEquals( "Destination [bucketName=my-bucket-name, objectName=/test.txt]",
+ new Destination("my-bucket-name/", "test.txt").toString() );
+
+ }
+
+}