reorganized project structure to accomodate new cloud providers

git-svn-id: http://jclouds.googlecode.com/svn/trunk@813 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-05-20 20:55:45 +00:00
parent 8b3424eaad
commit c2c883558d
145 changed files with 0 additions and 18474 deletions

View File

@ -1,107 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$HeadURL$
$Revision$
$Date$
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.html
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.
====================================================================
-->
<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/maven-v4_0_0.xsd">
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-jets3t</artifactId>
<name>jclouds JetS3t Adapter</name>
<packaging>jar</packaging>
<description>JetS3t plug-in implemented by JClouds</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/extensions/jets3t</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/extensions/jets3t</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/extensions/jets3t</url>
</scm>
<properties>
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey>
</properties>
<dependencies>
<dependency>
<groupId>net.java.dev.jets3t</groupId>
<artifactId>jets3t</artifactId>
<version>0.7.1</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-gae</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-s3</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-s3</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<name>jets3t</name>
<id>jets3t</id>
<url>http://jets3t.s3.amazonaws.com/maven2</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>jclouds.aws.accesskeyid</name>
<value>${jclouds.aws.accesskeyid}</value>
</property>
<property>
<name>jclouds.aws.secretaccesskey</name>
<value>${jclouds.aws.secretaccesskey}</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,288 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.jets3t;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.S3ContextFactory;
import org.jclouds.util.Utils;
import org.jets3t.service.S3ObjectsChunk;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.acl.AccessControlList;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3BucketLoggingStatus;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.security.AWSCredentials;
import com.google.inject.Module;
/**
* A JetS3t S3Service implemented by JClouds
*
* @author Adrian Cole
*
*/
public class JCloudsS3Service extends S3Service {
private static final long serialVersionUID = 1L;
private final S3Context context;
private final S3Connection connection;
private final long requestTimeoutMilliseconds = 10000;
/**
* Initializes a JClouds context to S3.
*
* @param awsCredentials
* - credentials to access S3
* @param modules
* - Module that configures a FutureHttpClient, if not specified,
* default is URLFetchServiceClientModule
* @throws S3ServiceException
*/
protected JCloudsS3Service(AWSCredentials awsCredentials, Module... modules)
throws S3ServiceException {
super(awsCredentials);
if (modules == null || modules.length == 0)
modules = new Module[] { new org.jclouds.gae.config.URLFetchServiceClientModule() };
context = S3ContextFactory.createS3Context(awsCredentials
.getAccessKey(), awsCredentials.getSecretKey(), modules);
connection = context.getConnection();
}
@Override
public int checkBucketStatus(String bucketName) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
protected Map copyObjectImpl(String sourceBucketName,
String sourceObjectKey, String destinationBucketName,
String destinationObjectKey, AccessControlList acl,
Map destinationMetadata, Calendar ifModifiedSince,
Calendar ifUnmodifiedSince, String[] ifMatchTags,
String[] ifNoneMatchTags) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected S3Bucket createBucketImpl(String bucketName, String location,
AccessControlList acl) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @see S3Connection#deleteBucketIfEmpty(org.jclouds.aws.s3.domain.S3Bucket)
*/
@Override
protected void deleteBucketImpl(String bucketName)
throws S3ServiceException {
try {
connection.deleteBucketIfEmpty(bucketName).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3ServiceException> rethrowIfRuntimeOrSameType(e);
throw new S3ServiceException(
"error deleting bucket: " + bucketName, e);
}
}
/**
* {@inheritDoc}
*
* @see S3Connection#deleteObject(org.jclouds.aws.s3.domain.S3Bucket,
* String)
*/
@Override
protected void deleteObjectImpl(String bucketName, String objectKey)
throws S3ServiceException {
try {
connection.deleteObject(bucketName, objectKey).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3ServiceException> rethrowIfRuntimeOrSameType(e);
throw new S3ServiceException(String.format(
"error deleting object: %1$s:%2$s", bucketName, objectKey),
e);
}
}
@Override
protected AccessControlList getBucketAclImpl(String bucketName)
throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected String getBucketLocationImpl(String bucketName)
throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected S3BucketLoggingStatus getBucketLoggingStatusImpl(String bucketName)
throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected AccessControlList getObjectAclImpl(String bucketName,
String objectKey) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected S3Object getObjectDetailsImpl(String bucketName,
String objectKey, Calendar ifModifiedSince,
Calendar ifUnmodifiedSince, String[] ifMatchTags,
String[] ifNoneMatchTags) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected S3Object getObjectImpl(String bucketName, String objectKey,
Calendar ifModifiedSince, Calendar ifUnmodifiedSince,
String[] ifMatchTags, String[] ifNoneMatchTags,
Long byteRangeStart, Long byteRangeEnd) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
public boolean isBucketAccessible(String bucketName)
throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected boolean isRequesterPaysBucketImpl(String bucketName)
throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected S3Bucket[] listAllBucketsImpl() throws S3ServiceException {
try {
List<org.jclouds.aws.s3.domain.S3Bucket.Metadata> jcBucketList = connection
.listOwnedBuckets().get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
ArrayList<org.jets3t.service.model.S3Bucket> jsBucketList = new ArrayList<org.jets3t.service.model.S3Bucket>();
for (org.jclouds.aws.s3.domain.S3Bucket.Metadata jcBucket : jcBucketList) {
org.jets3t.service.model.S3Bucket jsBucket = new org.jets3t.service.model.S3Bucket(
jcBucket.getName());
jsBucket.setOwner(new org.jets3t.service.model.S3Owner(jcBucket
.getOwner().getId(), jcBucket.getOwner()
.getDisplayName()));
jsBucketList.add(jsBucket);
}
return (org.jets3t.service.model.S3Bucket[]) jsBucketList
.toArray(new org.jets3t.service.model.S3Bucket[jsBucketList
.size()]);
} catch (Exception e) {
Utils.<S3ServiceException> rethrowIfRuntimeOrSameType(e);
throw new S3ServiceException("error listing buckets", e);
}
}
@Override
protected S3ObjectsChunk listObjectsChunkedImpl(String bucketName,
String prefix, String delimiter, long maxListingLength,
String priorLastKey, boolean completeListing)
throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected S3Object[] listObjectsImpl(String bucketName, String prefix,
String delimiter, long maxListingLength) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected void putBucketAclImpl(String bucketName, AccessControlList acl)
throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected void putObjectAclImpl(String bucketName, String objectKey,
AccessControlList acl) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected S3Object putObjectImpl(String bucketName, S3Object object)
throws S3ServiceException {
// TODO Unimplemented
return null;
}
@Override
protected void setBucketLoggingStatusImpl(String bucketName,
S3BucketLoggingStatus status) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
@Override
protected void setRequesterPaysBucketImpl(String bucketName,
boolean requesterPays) throws S3ServiceException {
// TODO Unimplemented
throw new UnsupportedOperationException();
}
}

View File

@ -1,243 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.jets3t;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.security.AWSCredentials;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Tests to cover JCloudsS3Service
*
* @author Adrian Cole
*
*/
@Test
public class JCloudsS3ServiceTest extends S3IntegrationTest {
AWSCredentials credentials;
S3Service service;
@Override
protected boolean debugEnabled() {
return true;
}
/**
* overridden only to get access to the amazon credentials used for jets3t
* initialization.
*/
@Override
protected S3Context createS3Context(String AWSAccessKeyId,
String AWSSecretAccessKey) {
credentials = new AWSCredentials(AWSAccessKeyId, AWSSecretAccessKey);
return super.createS3Context(AWSAccessKeyId, AWSSecretAccessKey);
}
/**
* initialize a new JCloudsS3Service, but passing
* JavaUrlHttpFutureCommandClientModule(), as it is easier to debug in unit
* tests.
*
* @throws S3ServiceException
*/
@BeforeMethod
public void testJCloudsS3Service() throws S3ServiceException {
service = new JCloudsS3Service(credentials,
new JavaUrlHttpFutureCommandClientModule());
}
@Test
public void testCheckBucketStatusString() {
fail("Not yet implemented");
}
@Test
public void testCopyObjectImplStringStringStringStringAccessControlListMapCalendarCalendarStringArrayStringArray() {
fail("Not yet implemented");
}
@Test
public void testCreateBucketImplStringStringAccessControlList() {
fail("Not yet implemented");
}
@Test
public void testDeleteBucketImplString() throws S3ServiceException,
InterruptedException, ExecutionException, TimeoutException {
String bucketName = bucketPrefix + ".testDeleteBucketImplString";
service.deleteBucket(bucketName);
assert !client.bucketExists(bucketName).get(10, TimeUnit.SECONDS);
}
private void createBucket(String bucketName) throws InterruptedException,
ExecutionException, TimeoutException {
client.putBucketIfNotExists(bucketName).get(10, TimeUnit.SECONDS);
}
@Test
public void testDeleteObjectImplStringString() throws InterruptedException,
ExecutionException, TimeoutException, S3ServiceException {
String bucketName = bucketPrefix + ".testDeleteObjectImplStringString";
String objectKey = "key";
String objectValue = "test";
addNewObject(bucketName, objectKey, objectValue);
service.deleteObject(bucketName, objectKey);
assertEquals(client.headObject(bucketName, objectKey).get(10,
TimeUnit.SECONDS), org.jclouds.aws.s3.domain.S3Object.NOT_FOUND);
}
private void addNewObject(String name, String objectKey, String objectValue)
throws InterruptedException, ExecutionException, TimeoutException {
createBucket(name);
org.jclouds.aws.s3.domain.S3Object jcloudsObject = new org.jclouds.aws.s3.domain.S3Object(
objectKey);
jcloudsObject.setData(objectValue);
client.putObject(name, jcloudsObject).get(10, TimeUnit.SECONDS);
}
@Test
public void testGetBucketAclImplString() {
fail("Not yet implemented");
}
@Test
public void testGetBucketLocationImplString() {
fail("Not yet implemented");
}
@Test
public void testGetBucketLoggingStatusImplString() {
fail("Not yet implemented");
}
@Test
public void testGetObjectAclImplStringString() {
fail("Not yet implemented");
}
@Test
public void testGetObjectDetailsImplStringStringCalendarCalendarStringArrayStringArray() {
fail("Not yet implemented");
}
@Test
public void testGetObjectImplStringStringCalendarCalendarStringArrayStringArrayLongLong() {
fail("Not yet implemented");
}
@Test
public void testIsBucketAccessibleString() {
fail("Not yet implemented");
}
@Test
public void testIsRequesterPaysBucketImplString() {
fail("Not yet implemented");
}
@Test
public void testListAllBucketsImpl() throws InterruptedException,
ExecutionException, TimeoutException, S3ServiceException {
// Ensure there is at least 1 bucket in S3 account to list and compare.
String bucketName = bucketPrefix + ".testListAllBucketsImplString";
createBucket(bucketName);
S3Bucket[] jsBuckets = service.listAllBuckets();
List<org.jclouds.aws.s3.domain.S3Bucket.Metadata> jcBuckets = client
.listOwnedBuckets().get(10, TimeUnit.SECONDS);
assert jsBuckets.length == jcBuckets.size();
Iterator<org.jclouds.aws.s3.domain.S3Bucket.Metadata> jcBucketsIter = jcBuckets
.iterator();
for (S3Bucket jsBucket : jsBuckets) {
assert jcBucketsIter.hasNext();
org.jclouds.aws.s3.domain.S3Bucket.Metadata jcBucket = jcBucketsIter
.next();
assert jsBucket.getName().equals(jcBucket.getName());
assert jsBucket.getOwner().getId().equals(
jcBucket.getOwner().getId());
assert jsBucket.getOwner().getDisplayName().equals(
jcBucket.getOwner().getDisplayName());
}
client.deleteBucketIfEmpty(bucketName);
}
@Test
public void testListObjectsChunkedImplStringStringStringLongStringBoolean() {
fail("Not yet implemented");
}
@Test
public void testListObjectsImplStringStringStringLong() {
fail("Not yet implemented");
}
@Test
public void testPutBucketAclImplStringAccessControlList() {
fail("Not yet implemented");
}
@Test
public void testPutObjectAclImplStringStringAccessControlList() {
fail("Not yet implemented");
}
@Test
public void testPutObjectImplStringS3Object() {
fail("Not yet implemented");
}
@Test
public void testSetBucketLoggingStatusImplStringS3BucketLoggingStatus() {
fail("Not yet implemented");
}
@Test
public void testSetRequesterPaysBucketImplStringBoolean() {
fail("Not yet implemented");
}
}

View File

@ -1,134 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$HeadURL$
$Revision$
$Date$
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.html
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.
====================================================================
-->
<!--
Note that the code that these performance tests are evaluated against exist in src/main. The code in that
location was copied straight from Amazon's website. There have been small modifications to make unit testing
possible. That code exists with the following license:
This software code is made available "AS IS" without warranties of any
kind. You may copy, display, modify and redistribute the software
code either by itself or as incorporated into your code; provided that
you do not remove any proprietary notices. Your use of this software
code is at your own risk and you waive any claim against Amazon
Digital Services, Inc. or its affiliates with respect to your use of
this software code. (c) 2006 Amazon Digital Services, Inc. or its
affiliates.
-->
<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/maven-v4_0_0.xsd">
<parent>
<artifactId>jclouds-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jclouds-s3perftest</artifactId>
<name>Performance test verses Amazon samples implementation</name>
<packaging>jar</packaging>
<description>Performance test verses Amazon samples implementation</description>
<properties>
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-s3</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-s3</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-httpnio</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jets3t</groupId>
<artifactId>jets3t</artifactId>
<version>0.7.1</version>
</dependency>
</dependencies>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/s3core/perftest</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/s3core/perftest</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/s3core/perftest</url>
</scm>
<repositories>
<!-- For Amazon S3 artifacts -->
<repository>
<name>jets3t</name>
<id>jets3t</id>
<url>http://jets3t.s3.amazonaws.com/maven2</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>jclouds.aws.accesskeyid</name>
<value>${jclouds.aws.accesskeyid}</value>
</property>
<property>
<name>jclouds.aws.secretaccesskey</name>
<value>${jclouds.aws.secretaccesskey}</value>
</property>
</systemProperties>
<excludes>
<exclude>**/Jets3tPerformanceTest.java</exclude>
<exclude>**/AmazonPerformanceTest.java</exclude>
<exclude>**/S3UtilsTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,159 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006-2007 Amazon Digital Services, Inc. or its
// affiliates.
import java.util.Map;
import java.util.TreeMap;
import java.util.Arrays;
import com.amazon.s3.AWSAuthConnection;
import com.amazon.s3.CallingFormat;
import com.amazon.s3.QueryStringAuthGenerator;
import com.amazon.s3.S3Object;
public class S3Driver {
static final String awsAccessKeyId = "<INSERT YOUR AWS ACCESS KEY ID HERE>";
static final String awsSecretAccessKey = "<INSERT YOUR AWS SECRET ACCESS KEY HERE>";
// convert the bucket to lowercase for vanity domains
// the bucket name must be lowercase since DNS is case-insensitive
static final String bucketName = awsAccessKeyId.toLowerCase() + "-test-bucket";
static final String keyName = "test-key";
static final String copiedKeyName = "copy-of-" + keyName;
public static void main(String args[]) throws Exception {
if (awsAccessKeyId.startsWith("<INSERT")) {
System.err.println("Please examine S3Driver.java and update it with your credentials");
System.exit(-1);
}
AWSAuthConnection conn =
new AWSAuthConnection(awsAccessKeyId, awsSecretAccessKey);
QueryStringAuthGenerator generator =
new QueryStringAuthGenerator(awsAccessKeyId, awsSecretAccessKey);
// Check if the bucket exists. The high availability engineering of
// Amazon S3 is focused on get, put, list, and delete operations.
// Because bucket operations work against a centralized, global
// resource space, it is not appropriate to make bucket create or
// delete calls on the high availability code path of your application.
// It is better to create or delete buckets in a separate initialization
// or setup routine that you run less often.
if (!conn.checkBucketExists(bucketName))
{
System.out.println("----- creating bucket -----");
System.out.println(conn.createBucket(bucketName, AWSAuthConnection.LOCATION_DEFAULT, null).connection.getResponseMessage());
// sample creating an EU located bucket.
// (note path-style urls will not work with location-constrained buckets)
//System.out.println(conn.createBucket(bucketName, AWSAuthConnection.LOCATION_EU, null).connection.getResponseMessage());
}
System.out.println("----- listing bucket -----");
System.out.println(conn.listBucket(bucketName, null, null, null, null).entries);
System.out.println("----- bucket location -----");
System.out.println(conn.getBucketLocation(bucketName).getLocation());
System.out.println("----- putting object -----");
S3Object object = new S3Object("this is a test".getBytes(), null);
Map headers = new TreeMap();
headers.put("Content-Type", Arrays.asList(new String[] { "text/plain" }));
System.out.println(
conn.put(bucketName, keyName, object, headers).connection.getResponseMessage()
);
System.out.println("----- copying object -----");
// Straight Copy; destination key will be private.
conn.copy( bucketName, keyName, bucketName, copiedKeyName, null );
{
// Update the metadata; destination key will be private.
Map updateMetadata = new TreeMap();
updateMetadata.put("metadata-key", Arrays.asList("this will be the metadata in the copied key"));
conn.copy( bucketName, copiedKeyName, bucketName, copiedKeyName, updateMetadata, null );
}
System.out.println("----- listing bucket -----");
System.out.println(conn.listBucket(bucketName, null, null, null, null).entries);
System.out.println("----- getting object -----");
System.out.println(
new String(conn.get(bucketName, keyName, null).object.data)
);
System.out.println("----- query string auth example -----");
generator.setExpiresIn(60 * 1000);
System.out.println("Try this url in your web browser (it will only work for 60 seconds)\n");
System.out.println(generator.get(bucketName, keyName, null));
System.out.print("\npress enter> ");
System.in.read();
System.out.println("\nNow try just the url without the query string arguments. It should fail.\n");
System.out.println(generator.makeBareURL(bucketName, keyName));
System.out.print("\npress enter> ");
System.in.read();
System.out.println("----- putting object with metadata and public read acl -----");
Map metadata = new TreeMap();
metadata.put("blah", Arrays.asList(new String[] { "foo" }));
object = new S3Object("this is a publicly readable test".getBytes(), metadata);
headers = new TreeMap();
headers.put("x-amz-acl", Arrays.asList(new String[] { "public-read" }));
headers.put("Content-Type", Arrays.asList(new String[] { "text/plain" }));
System.out.println(
conn.put(bucketName, keyName + "-public", object, headers).connection.getResponseMessage()
);
System.out.println("----- anonymous read test -----");
System.out.println("\nYou should be able to try this in your browser\n");
System.out.println(generator.makeBareURL(bucketName, keyName + "-public"));
System.out.print("\npress enter> ");
System.in.read();
System.out.println("----- path style url example -----");
System.out.println("\nNon-location-constrained buckets can also be specified as part of the url path. (This was the original url style supported by S3.)");
System.out.println("\nTry this url out in your browser (it will only be valid for 60 seconds)\n");
generator.setCallingFormat(CallingFormat.getPathCallingFormat());
// could also have been done like this:
// generator = new QueryStringAuthGenerator(awsAccessKeyId, awsSecretAccessKey, true, Utils.DEFAULT_HOST, CallingFormat.getPathCallingFormat());
generator.setExpiresIn(60 * 1000);
System.out.println(generator.get(bucketName, keyName, null));
System.out.print("\npress enter> ");
System.in.read();
System.out.println("----- getting object's acl -----");
System.out.println(new String(conn.getACL(bucketName, keyName, null).object.data));
System.out.println("----- deleting objects -----");
System.out.println(
conn.delete(bucketName, copiedKeyName, null).connection.getResponseMessage()
);
System.out.println(
conn.delete(bucketName, keyName, null).connection.getResponseMessage()
);
System.out.println(
conn.delete(bucketName, keyName + "-public", null).connection.getResponseMessage()
);
System.out.println("----- listing bucket -----");
System.out.println(conn.listBucket(bucketName, null, null, null, null).entries);
System.out.println("----- listing all my buckets -----");
System.out.println(conn.listAllMyBuckets(null).entries);
System.out.println("----- deleting bucket -----");
System.out.println(
conn.deleteBucket(bucketName, null).connection.getResponseMessage()
);
}
}

View File

@ -1,633 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adriancole@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006-2007 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
/**
* An interface into the S3 system. It is initially configured with
* authentication and connection parameters and exposes methods to access and
* manipulate S3 data.
*/
public class AWSAuthConnection {
public static final String LOCATION_DEFAULT = null;
public static final String LOCATION_EU = "EU";
private String awsAccessKeyId;
private String awsSecretAccessKey;
private boolean isSecure;
private String server;
private int port;
private CallingFormat callingFormat;
public AWSAuthConnection(String awsAccessKeyId, String awsSecretAccessKey) {
this(awsAccessKeyId, awsSecretAccessKey, true);
}
public AWSAuthConnection(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure) {
this(awsAccessKeyId, awsSecretAccessKey, isSecure, Utils.DEFAULT_HOST);
}
public AWSAuthConnection(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure,
String server)
{
this(awsAccessKeyId, awsSecretAccessKey, isSecure, server,
isSecure ? Utils.SECURE_PORT : Utils.INSECURE_PORT);
}
public AWSAuthConnection(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure,
String server, int port) {
this(awsAccessKeyId, awsSecretAccessKey, isSecure, server, port, CallingFormat.getSubdomainCallingFormat());
}
public AWSAuthConnection(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure,
String server, CallingFormat format) {
this(awsAccessKeyId, awsSecretAccessKey, isSecure, server,
isSecure ? Utils.SECURE_PORT : Utils.INSECURE_PORT,
format);
}
/**
* Create a new interface to interact with S3 with the given credential and connection
* parameters
*
* @param awsAccessKeyId Your user key into AWS
* @param awsSecretAccessKey The secret string used to generate signatures for authentication.
* @param isSecure use SSL encryption
* @param server Which host to connect to. Usually, this will be s3.amazonaws.com
* @param port Which port to use.
* @param callingFormat Type of request Regular/Vanity or Pure Vanity domain
*/
public AWSAuthConnection(String awsAccessKeyId, String awsSecretAccessKey, boolean isSecure,
String server, int port, CallingFormat format)
{
this.awsAccessKeyId = awsAccessKeyId;
this.awsSecretAccessKey = awsSecretAccessKey;
this.isSecure = isSecure;
this.server = server;
this.port = port;
this.callingFormat = format;
}
/**
* Creates a new bucket.
* @param bucket The name of the bucket to create.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
* @param metadata A Map of String to List of Strings representing the s3
* metadata for this bucket (can be null).
* @deprecated use version that specifies location
*/
public Response createBucket(String bucket, Map headers)
throws MalformedURLException, IOException
{
return createBucket(bucket, null, headers);
}
/**
* Creates a new bucket.
* @param bucket The name of the bucket to create.
* @param location Desired location ("EU") (or null for default).
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
* @param metadata A Map of String to List of Strings representing the s3
* metadata for this bucket (can be null).
* @throws IllegalArgumentException on invalid location
*/
public Response createBucket(String bucket, String location, Map headers)
throws MalformedURLException, IOException
{
String body;
if (location == null) {
body = null;
} else if (LOCATION_EU.equals(location)) {
if (!callingFormat.supportsLocatedBuckets())
throw new IllegalArgumentException("Creating location-constrained bucket with unsupported calling-format");
body = "<CreateBucketConstraint><LocationConstraint>" + location + "</LocationConstraint></CreateBucketConstraint>";
} else
throw new IllegalArgumentException("Invalid Location: "+location);
// validate bucket name
if (!Utils.validateBucketName(bucket, callingFormat, location != null))
throw new IllegalArgumentException("Invalid S3Bucket Name: "+bucket);
HttpURLConnection request = makeRequest("PUT", bucket, "", null, headers);
if (body != null)
{
request.setDoOutput(true);
request.getOutputStream().write(body.getBytes("UTF-8"));
}
return new Response(request);
}
/**
* Check if the specified bucket exists (via a HEAD request)
* @param bucket The name of the bucket to check
* @return true if HEAD access returned success
*/
public boolean checkBucketExists(String bucket) throws MalformedURLException, IOException
{
HttpURLConnection response = makeRequest("HEAD", bucket, "", null, null);
int httpCode = response.getResponseCode();
return httpCode >= 200 && httpCode < 300;
}
/**
* Lists the contents of a bucket.
* @param bucket The name of the bucket to create.
* @param prefix All returned keys will start with this string (can be null).
* @param marker All returned keys will be lexographically greater than
* this string (can be null).
* @param maxKeys The maximum number of keys to return (can be null).
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public ListBucketResponse listBucket(String bucket, String prefix, String marker,
Integer maxKeys, Map headers)
throws MalformedURLException, IOException
{
return listBucket(bucket, prefix, marker, maxKeys, null, headers);
}
/**
* Lists the contents of a bucket.
* @param bucket The name of the bucket to list.
* @param prefix All returned keys will start with this string (can be null).
* @param marker All returned keys will be lexographically greater than
* this string (can be null).
* @param maxKeys The maximum number of keys to return (can be null).
* @param delimiter Keys that contain a string between the prefix and the first
* occurrence of the delimiter will be rolled up into a single element.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public ListBucketResponse listBucket(String bucket, String prefix, String marker,
Integer maxKeys, String delimiter, Map headers)
throws MalformedURLException, IOException
{
Map pathArgs = Utils.paramsForListOptions(prefix, marker, maxKeys, delimiter);
return new ListBucketResponse(makeRequest("GET", bucket, "", pathArgs, headers));
}
/**
* Deletes a bucket.
* @param bucket The name of the bucket to delete.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public Response deleteBucket(String bucket, Map headers)
throws MalformedURLException, IOException
{
return new Response(makeRequest("DELETE", bucket, "", null, headers));
}
/**
* Writes an object to S3.
* @param bucket The name of the bucket to which the object will be added.
* @param key The name of the key to use.
* @param object An S3Object containing the data to write.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public Response put(String bucket, String key, S3Object object, Map headers)
throws MalformedURLException, IOException
{
HttpURLConnection request =
makeRequest("PUT", bucket, Utils.urlencode(key), null, headers, object);
request.setDoOutput(true);
request.getOutputStream().write(object.data == null ? new byte[] {} : object.data);
return new Response(request);
}
/**
* Creates a copy of an existing S3 Object. In this signature, we will copy the
* existing metadata. The default access control policy is private; if you want
* to override it, please use x-amz-acl in the headers.
* @param sourceBucket The name of the bucket where the source object lives.
* @param sourceKey The name of the key to copy.
* @param destinationBucket The name of the bucket to which the object will be added.
* @param destinationKey The name of the key to use.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null). You may wish to set the x-amz-acl header appropriately.
*/
public Response copy( String sourceBucket, String sourceKey, String destinationBucket, String destinationKey, Map headers )
throws MalformedURLException, IOException
{
S3Object object = new S3Object(new byte[] {}, new HashMap());
headers = headers == null ? new HashMap() : new HashMap(headers);
headers.put("x-amz-copy-source", Arrays.asList( new String[] { sourceBucket + "/" + sourceKey } ) );
headers.put("x-amz-metadata-directive", Arrays.asList( new String[] { "COPY" } ) );
return verifyCopy( put( destinationBucket, destinationKey, object, headers ) );
}
/**
* Creates a copy of an existing S3 Object. In this signature, we will replace the
* existing metadata. The default access control policy is private; if you want
* to override it, please use x-amz-acl in the headers.
* @param sourceBucket The name of the bucket where the source object lives.
* @param sourceKey The name of the key to copy.
* @param destinationBucket The name of the bucket to which the object will be added.
* @param destinationKey The name of the key to use.
* @param metadata A Map of String to List of Strings representing the S3 metadata
* for the new object.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null). You may wish to set the x-amz-acl header appropriately.
*/
public Response copy( String sourceBucket, String sourceKey, String destinationBucket, String destinationKey, Map metadata, Map headers )
throws MalformedURLException, IOException
{
S3Object object = new S3Object(new byte[] {}, metadata);
headers = headers == null ? new HashMap() : new HashMap(headers);
headers.put("x-amz-copy-source", Arrays.asList( new String[] { sourceBucket + "/" + sourceKey } ) );
headers.put("x-amz-metadata-directive", Arrays.asList( new String[] { "REPLACE" } ) );
return verifyCopy( put( destinationBucket, destinationKey, object, headers ) );
}
/**
* Copy sometimes returns a successful response and starts to send whitespace
* characters to us. This method processes those whitespace characters and
* will throw an exception if the response is either unknown or an error.
* @param response Response object from the PUT request.
* @return The response with the input stream drained.
* @throws IOException If anything goes wrong.
*/
private Response verifyCopy( Response response ) throws IOException {
if (response.connection.getResponseCode() < 400) {
byte[] body = GetResponse.slurpInputStream(response.connection.getInputStream());
String message = new String( body );
if ( message.indexOf( "<Error" ) != -1 ) {
throw new IOException( message.substring( message.indexOf( "<Error" ) ) );
} else if ( message.indexOf( "</CopyObjectResult>" ) != -1 ) {
// It worked!
} else {
throw new IOException( "Unexpected response: " + message );
}
}
return response;
}
/**
* Reads an object from S3.
* @param bucket The name of the bucket where the object lives.
* @param key The name of the key to use.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public GetResponse get(String bucket, String key, Map headers)
throws MalformedURLException, IOException
{
return new GetResponse(makeRequest("GET", bucket, Utils.urlencode(key), null, headers));
}
/**
* Deletes an object from S3.
* @param bucket The name of the bucket where the object lives.
* @param key The name of the key to use.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public Response delete(String bucket, String key, Map headers)
throws MalformedURLException, IOException
{
return new Response(makeRequest("DELETE", bucket, Utils.urlencode(key), null, headers));
}
/**
* Get the requestPayment xml document for a given bucket
* @param bucket The name of the bucket
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public GetResponse getBucketRequestPayment(String bucket, Map headers)
throws MalformedURLException, IOException
{
Map pathArgs = new HashMap();
pathArgs.put("requestPayment", null);
return new GetResponse(makeRequest("GET", bucket, "", pathArgs, headers));
}
/**
* Write a new requestPayment xml document for a given bucket
* @param loggingXMLDoc The xml representation of the requestPayment configuration as a String
* @param bucket The name of the bucket
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public Response putBucketRequestPayment(String bucket, String requestPaymentXMLDoc, Map headers)
throws MalformedURLException, IOException
{
Map pathArgs = new HashMap();
pathArgs.put("requestPayment", null);
S3Object object = new S3Object(requestPaymentXMLDoc.getBytes(), null);
HttpURLConnection request = makeRequest("PUT", bucket, "", pathArgs, headers, object);
request.setDoOutput(true);
request.getOutputStream().write(object.data == null ? new byte[] {} : object.data);
return new Response(request);
}
/**
* Get the logging xml document for a given bucket
* @param bucket The name of the bucket
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public GetResponse getBucketLogging(String bucket, Map headers)
throws MalformedURLException, IOException
{
Map pathArgs = new HashMap();
pathArgs.put("logging", null);
return new GetResponse(makeRequest("GET", bucket, "", pathArgs, headers));
}
/**
* Write a new logging xml document for a given bucket
* @param loggingXMLDoc The xml representation of the logging configuration as a String
* @param bucket The name of the bucket
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public Response putBucketLogging(String bucket, String loggingXMLDoc, Map headers)
throws MalformedURLException, IOException
{
Map pathArgs = new HashMap();
pathArgs.put("logging", null);
S3Object object = new S3Object(loggingXMLDoc.getBytes(), null);
HttpURLConnection request = makeRequest("PUT", bucket, "", pathArgs, headers, object);
request.setDoOutput(true);
request.getOutputStream().write(object.data == null ? new byte[] {} : object.data);
return new Response(request);
}
/**
* Get the ACL for a given bucket
* @param bucket The name of the bucket where the object lives.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public GetResponse getBucketACL(String bucket, Map headers)
throws MalformedURLException, IOException
{
return getACL(bucket, "", headers);
}
/**
* Get the ACL for a given object (or bucket, if key is null).
* @param bucket The name of the bucket where the object lives.
* @param key The name of the key to use.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public GetResponse getACL(String bucket, String key, Map headers)
throws MalformedURLException, IOException
{
if (key == null) key = "";
Map pathArgs = new HashMap();
pathArgs.put("acl", null);
return new GetResponse(
makeRequest("GET", bucket, Utils.urlencode(key), pathArgs, headers)
);
}
/**
* Write a new ACL for a given bucket
* @param aclXMLDoc The xml representation of the ACL as a String
* @param bucket The name of the bucket where the object lives.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public Response putBucketACL(String bucket, String aclXMLDoc, Map headers)
throws MalformedURLException, IOException
{
return putACL(bucket, "", aclXMLDoc, headers);
}
/**
* Write a new ACL for a given object
* @param aclXMLDoc The xml representation of the ACL as a String
* @param bucket The name of the bucket where the object lives.
* @param key The name of the key to use.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public Response putACL(String bucket, String key, String aclXMLDoc, Map headers)
throws MalformedURLException, IOException
{
S3Object object = new S3Object(aclXMLDoc.getBytes(), null);
Map pathArgs = new HashMap();
pathArgs.put("acl", null);
HttpURLConnection request =
makeRequest("PUT", bucket, Utils.urlencode(key), pathArgs, headers, object);
request.setDoOutput(true);
request.getOutputStream().write(object.data == null ? new byte[] {} : object.data);
return new Response(request);
}
public LocationResponse getBucketLocation(String bucket)
throws MalformedURLException, IOException
{
Map pathArgs = new HashMap();
pathArgs.put("location", null);
return new LocationResponse(makeRequest("GET", bucket, "", pathArgs, null));
}
/**
* List all the buckets created by this account.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
public ListAllMyBucketsResponse listAllMyBuckets(Map headers)
throws MalformedURLException, IOException
{
return new ListAllMyBucketsResponse(makeRequest("GET", "", "", null, headers));
}
/**
* Make a new HttpURLConnection without passing an S3Object parameter.
* Use this method for key operations that do require arguments
* @param method The method to invoke
* @param bucketName the bucket this request is for
* @param key the key this request is for
* @param pathArgs the
* @param headers
* @return
* @throws MalformedURLException
* @throws IOException
*/
private HttpURLConnection makeRequest(String method, String bucketName, String key, Map pathArgs, Map headers)
throws MalformedURLException, IOException
{
return makeRequest(method, bucketName, key, pathArgs, headers, null);
}
/**
* Make a new HttpURLConnection.
* @param method The HTTP method to use (GET, PUT, DELETE)
* @param bucketName The bucket name this request affects
* @param key The key this request is for
* @param pathArgs parameters if any to be sent along this request
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
* @param object The S3Object that is to be written (can be null).
*/
private HttpURLConnection makeRequest(String method, String bucket, String key, Map pathArgs, Map headers,
S3Object object)
throws MalformedURLException, IOException
{
CallingFormat callingFormat = Utils.getCallingFormatForBucket( this.callingFormat, bucket );
if ( isSecure && callingFormat != CallingFormat.getPathCallingFormat() && bucket.indexOf( "." ) != -1 ) {
System.err.println( "You are making an SSL connection, however, the bucket contains periods and the wildcard certificate will not match by default. Please consider using HTTP." );
}
// build the domain based on the calling format
URL url = callingFormat.getURL(isSecure, server, this.port, bucket, key, pathArgs);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod(method);
// subdomain-style urls may encounter http redirects.
// Ensure that redirects are supported.
if (!connection.getInstanceFollowRedirects()
&& callingFormat.supportsLocatedBuckets())
throw new RuntimeException("HTTP redirect support required.");
addHeaders(connection, headers);
if (object != null) addMetadataHeaders(connection, object.metadata);
addAuthHeader(connection, method, bucket, key, pathArgs);
return connection;
}
/**
* Add the given headers to the HttpURLConnection.
* @param connection The HttpURLConnection to which the headers will be added.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
*/
private void addHeaders(HttpURLConnection connection, Map headers) {
addHeaders(connection, headers, "");
}
/**
* Add the given metadata fields to the HttpURLConnection.
* @param connection The HttpURLConnection to which the headers will be added.
* @param metadata A Map of String to List of Strings representing the s3
* metadata for this resource.
*/
private void addMetadataHeaders(HttpURLConnection connection, Map metadata) {
addHeaders(connection, metadata, Utils.METADATA_PREFIX);
}
/**
* Add the given headers to the HttpURLConnection with a prefix before the keys.
* @param connection The HttpURLConnection to which the headers will be added.
* @param headers A Map of String to List of Strings representing the http
* headers to pass (can be null).
* @param prefix The string to prepend to each key before adding it to the connection.
*/
private void addHeaders(HttpURLConnection connection, Map headers, String prefix) {
if (headers != null) {
for (Iterator i = headers.keySet().iterator(); i.hasNext(); ) {
String key = (String)i.next();
for (Iterator j = ((List)headers.get(key)).iterator(); j.hasNext(); ) {
String value = (String)j.next();
connection.addRequestProperty(prefix + key, value);
}
}
}
}
/**
* Add the appropriate Authorization header to the HttpURLConnection.
* @param connection The HttpURLConnection to which the header will be added.
* @param method The HTTP method to use (GET, PUT, DELETE)
* @param bucket the bucket name this request is for
* @param key the key this request is for
* @param pathArgs path arguments which are part of this request
*/
private void addAuthHeader(HttpURLConnection connection, String method, String bucket, String key, Map pathArgs) {
if (connection.getRequestProperty("Date") == null) {
connection.setRequestProperty("Date", httpDate());
}
if (connection.getRequestProperty("Content-Type") == null) {
connection.setRequestProperty("Content-Type", "");
}
String canonicalString =
Utils.makeCanonicalString(method, bucket, key, pathArgs, connection.getRequestProperties());
String encodedCanonical = Utils.encode(this.awsSecretAccessKey, canonicalString, false);
connection.setRequestProperty("Authorization",
"AWS " + this.awsAccessKeyId + ":" + encodedCanonical);
}
/**
* Generate an rfc822 date for use in the Date HTTP header.
*/
public static String httpDate() {
final String DateFormat = "EEE, dd MMM yyyy HH:mm:ss ";
SimpleDateFormat format = new SimpleDateFormat( DateFormat, Locale.US );
format.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
return format.format( new Date() ) + "GMT";
}
}

View File

@ -1,41 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.util.Date;
/**
* A class representing a single bucket. Returned as a component of ListAllMyBucketsResponse.
*/
public class Bucket {
/**
* The name of the bucket.
*/
public String name;
/**
* The bucket's creation date.
*/
public Date creationDate;
public Bucket() {
this.name = null;
this.creationDate = null;
}
public Bucket(String name, Date creationDate) {
this.name = name;
this.creationDate = creationDate;
}
public String toString() {
return this.name;
}
}

View File

@ -1,103 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006-2007 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
public abstract class CallingFormat {
protected static CallingFormat pathCallingFormat = new PathCallingFormat();
protected static CallingFormat subdomainCallingFormat = new SubdomainCallingFormat();
protected static CallingFormat vanityCallingFormat = new VanityCallingFormat();
public abstract boolean supportsLocatedBuckets();
public abstract String getEndpoint(String server, int port, String bucket);
public abstract String getPathBase(String bucket, String key);
public abstract URL getURL (boolean isSecure, String server, int port, String bucket, String key, Map pathArgs)
throws MalformedURLException;
public static CallingFormat getPathCallingFormat() {
return pathCallingFormat;
}
public static CallingFormat getSubdomainCallingFormat() {
return subdomainCallingFormat;
}
public static CallingFormat getVanityCallingFormat() {
return vanityCallingFormat;
}
static private class PathCallingFormat extends CallingFormat {
public boolean supportsLocatedBuckets() {
return false;
}
public String getPathBase(String bucket, String key) {
return isBucketSpecified(bucket) ? "/" + bucket + "/" + key : "/";
}
public String getEndpoint(String server, int port, String bucket) {
return server + ":" + port;
}
public URL getURL(boolean isSecure, String server, int port, String bucket, String key, Map pathArgs)
throws MalformedURLException {
String pathBase = isBucketSpecified(bucket) ? "/" + bucket + "/" + key : "/";
String pathArguments = Utils.convertPathArgsHashToString(pathArgs);
return new URL(isSecure ? "https": "http", server, port, pathBase + pathArguments);
}
private boolean isBucketSpecified(String bucket) {
if(bucket == null) return false;
if(bucket.length() == 0) return false;
return true;
}
}
static private class SubdomainCallingFormat extends CallingFormat {
public boolean supportsLocatedBuckets() {
return true;
}
public String getServer(String server, String bucket) {
return bucket + "." + server;
}
public String getEndpoint(String server, int port, String bucket) {
return getServer(server, bucket) + ":" + port ;
}
public String getPathBase(String bucket, String key) {
return "/" + key;
}
public URL getURL(boolean isSecure, String server, int port, String bucket, String key, Map pathArgs)
throws MalformedURLException {
if (bucket == null || bucket.length() == 0)
{
//The bucket is null, this is listAllBuckets request
String pathArguments = Utils.convertPathArgsHashToString(pathArgs);
return new URL(isSecure ? "https": "http", server, port, "/" + pathArguments);
} else {
String serverToUse = getServer(server, bucket);
String pathBase = getPathBase(bucket, key);
String pathArguments = Utils.convertPathArgsHashToString(pathArgs);
return new URL(isSecure ? "https": "http", serverToUse, port, pathBase + pathArguments);
}
}
}
static private class VanityCallingFormat extends SubdomainCallingFormat {
public String getServer(String server, String bucket) {
return bucket;
}
}
}

View File

@ -1,17 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
public class CommonPrefixEntry {
/**
* The prefix common to the delimited keys it represents
*/
public String prefix;
}

View File

@ -1,70 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.net.HttpURLConnection;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
/**
* A Response object returned from AWSAuthConnection.get(). Exposes the attribute object, which
* represents the retrieved object.
*/
public class GetResponse extends Response {
public S3Object object;
/**
* Pulls a representation of an S3Object out of the HttpURLConnection response.
*/
public GetResponse(HttpURLConnection connection) throws IOException {
super(connection);
if (connection.getResponseCode() < 400) {
Map metadata = extractMetadata(connection);
byte[] body = slurpInputStream(connection.getInputStream());
this.object = new S3Object(body, metadata);
}
}
/**
* Examines the response's header fields and returns a Map from String to List of Strings
* representing the object's metadata.
*/
private Map extractMetadata(HttpURLConnection connection) {
TreeMap metadata = new TreeMap();
Map headers = connection.getHeaderFields();
for (Iterator i = headers.keySet().iterator(); i.hasNext(); ) {
String key = (String)i.next();
if (key == null) continue;
if (key.startsWith(Utils.METADATA_PREFIX)) {
metadata.put(key.substring(Utils.METADATA_PREFIX.length()), headers.get(key));
}
}
return metadata;
}
/**
* Read the input stream and dump it all into a big byte array
*/
static byte[] slurpInputStream(InputStream stream) throws IOException {
final int chunkSize = 2048;
byte[] buf = new byte[chunkSize];
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(chunkSize);
int count;
while ((count=stream.read(buf)) != -1) byteStream.write(buf, 0, count);
return byteStream.toByteArray();
}
}

View File

@ -1,106 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.SimpleTimeZone;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* Returned by AWSAuthConnection.listAllMyBuckets().
*/
public class ListAllMyBucketsResponse extends Response {
/**
* A list of Bucket objects, one for each of this account's buckets. Will be null if
* the request fails.
*/
public List entries;
public ListAllMyBucketsResponse(HttpURLConnection connection) throws IOException {
super(connection);
if (connection.getResponseCode() < 400) {
try {
XMLReader xr = Utils.createXMLReader();;
ListAllMyBucketsHandler handler = new ListAllMyBucketsHandler();
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
xr.parse(new InputSource(connection.getInputStream()));
this.entries = handler.getEntries();
} catch (SAXException e) {
throw new RuntimeException("Unexpected error parsing ListAllMyBuckets xml", e);
}
}
}
static class ListAllMyBucketsHandler extends DefaultHandler {
private List entries = null;
private Bucket currBucket = null;
private StringBuffer currText = null;
private SimpleDateFormat iso8601Parser = null;
public ListAllMyBucketsHandler() {
super();
entries = new ArrayList();
this.iso8601Parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
this.iso8601Parser.setTimeZone(new SimpleTimeZone(0, "GMT"));
this.currText = new StringBuffer();
}
public void startDocument() {
// ignore
}
public void endDocument() {
// ignore
}
public void startElement(String uri, String name, String qName, Attributes attrs) {
if (name.equals("Bucket")) {
this.currBucket = new Bucket();
}
}
public void endElement(String uri, String name, String qName) {
if (name.equals("Bucket")) {
this.entries.add(this.currBucket);
} else if (name.equals("Name")) {
this.currBucket.name = this.currText.toString();
} else if (name.equals("CreationDate")) {
try {
this.currBucket.creationDate = this.iso8601Parser.parse(this.currText.toString());
} catch (ParseException e) {
throw new RuntimeException("Unexpected date format in list bucket output", e);
}
}
this.currText = new StringBuffer();
}
public void characters(char ch[], int start, int length) {
this.currText.append(ch, start, length);
}
public List getEntries() {
return this.entries;
}
}
}

View File

@ -1,243 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.SimpleTimeZone;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
/**
* Returned by AWSAuthConnection.listBucket()
*/
public class ListBucketResponse extends Response {
/**
* The name of the bucket being listed. Null if request fails.
*/
public String name = null;
/**
* The prefix echoed back from the request. Null if request fails.
*/
public String prefix = null;
/**
* The marker echoed back from the request. Null if request fails.
*/
public String marker = null;
/**
* The delimiter echoed back from the request. Null if not specified in
* the request, or if it fails.
*/
public String delimiter = null;
/**
* The maxKeys echoed back from the request if specified. 0 if request fails.
*/
public int maxKeys = 0;
/**
* Indicates if there are more results to the list. True if the current
* list results have been truncated. false if request fails.
*/
public boolean isTruncated = false;
/**
* Indicates what to use as a marker for subsequent list requests in the event
* that the results are truncated. Present only when a delimiter is specified.
* Null if request fails.
*/
public String nextMarker = null;
/**
* A List of ListEntry objects representing the objects in the given bucket.
* Null if the request fails.
*/
public List entries = null;
/**
* A List of CommonPrefixEntry objects representing the common prefixes of the
* keys that matched up to the delimiter. Null if the request fails.
*/
public List commonPrefixEntries = null;
public ListBucketResponse(HttpURLConnection connection) throws IOException {
super(connection);
if (connection.getResponseCode() < 400) {
try {
XMLReader xr = Utils.createXMLReader();
ListBucketHandler handler = new ListBucketHandler();
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
xr.parse(new InputSource(connection.getInputStream()));
this.name = handler.getName();
this.prefix = handler.getPrefix();
this.marker = handler.getMarker();
this.delimiter = handler.getDelimiter();
this.maxKeys = handler.getMaxKeys();
this.isTruncated = handler.getIsTruncated();
this.nextMarker = handler.getNextMarker();
this.entries = handler.getKeyEntries();
this.commonPrefixEntries = handler.getCommonPrefixEntries();
} catch (SAXException e) {
throw new RuntimeException("Unexpected error parsing ListBucket xml", e);
}
}
}
class ListBucketHandler extends DefaultHandler {
private String name = null;
private String prefix = null;
private String marker = null;
private String delimiter = null;
private int maxKeys = 0;
private boolean isTruncated = false;
private String nextMarker = null;
private boolean isEchoedPrefix = false;
private List keyEntries = null;
private ListEntry keyEntry = null;
private List commonPrefixEntries = null;
private CommonPrefixEntry commonPrefixEntry = null;
private StringBuffer currText = null;
private SimpleDateFormat iso8601Parser = null;
public ListBucketHandler() {
super();
keyEntries = new ArrayList();
commonPrefixEntries = new ArrayList();
this.iso8601Parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
this.iso8601Parser.setTimeZone(new SimpleTimeZone(0, "GMT"));
this.currText = new StringBuffer();
}
public void startDocument() {
this.isEchoedPrefix = true;
}
public void endDocument() {
// ignore
}
public void startElement(String uri, String name, String qName, Attributes attrs) {
if (name.equals("Contents")) {
this.keyEntry = new ListEntry();
} else if (name.equals("Owner")) {
this.keyEntry.owner = new Owner();
} else if (name.equals("CommonPrefixes")){
this.commonPrefixEntry = new CommonPrefixEntry();
}
}
public void endElement(String uri, String name, String qName) {
if (name.equals("Name")) {
this.name = this.currText.toString();
}
// this prefix is the one we echo back from the request
else if (name.equals("Prefix") && this.isEchoedPrefix) {
this.prefix = this.currText.toString();
this.isEchoedPrefix = false;
} else if (name.equals("Marker")) {
this.marker = this.currText.toString();
} else if (name.equals("MaxKeys")) {
this.maxKeys = Integer.parseInt(this.currText.toString());
} else if (name.equals("Delimiter")) {
this.delimiter = this.currText.toString();
} else if (name.equals("IsTruncated")) {
this.isTruncated = Boolean.valueOf(this.currText.toString());
} else if (name.equals("NextMarker")) {
this.nextMarker = this.currText.toString();
} else if (name.equals("Contents")) {
this.keyEntries.add(this.keyEntry);
} else if (name.equals("Key")) {
this.keyEntry.key = this.currText.toString();
} else if (name.equals("LastModified")) {
try {
this.keyEntry.lastModified = this.iso8601Parser.parse(this.currText.toString());
} catch (ParseException e) {
throw new RuntimeException("Unexpected date format in list bucket output", e);
}
} else if (name.equals("ETag")) {
this.keyEntry.eTag = this.currText.toString();
} else if (name.equals("Size")) {
this.keyEntry.size = Long.parseLong(this.currText.toString());
} else if (name.equals("StorageClass")) {
this.keyEntry.storageClass = this.currText.toString();
} else if (name.equals("ID")) {
this.keyEntry.owner.id = this.currText.toString();
} else if (name.equals("DisplayName")) {
this.keyEntry.owner.displayName = this.currText.toString();
} else if (name.equals("CommonPrefixes")) {
this.commonPrefixEntries.add(this.commonPrefixEntry);
}
// this is the common prefix for keys that match up to the delimiter
else if (name.equals("Prefix")) {
this.commonPrefixEntry.prefix = this.currText.toString();
}
if(this.currText.length() != 0)
this.currText = new StringBuffer();
}
public void characters(char ch[], int start, int length) {
this.currText.append(ch, start, length);
}
public String getName() {
return this.name;
}
public String getPrefix() {
return this.prefix;
}
public String getMarker() {
return this.marker;
}
public String getDelimiter() {
return this.delimiter;
}
public int getMaxKeys(){
return this.maxKeys;
}
public boolean getIsTruncated() {
return this.isTruncated;
}
public String getNextMarker() {
return this.nextMarker;
}
public List getKeyEntries() {
return this.keyEntries;
}
public List getCommonPrefixEntries() {
return this.commonPrefixEntries;
}
}
}

View File

@ -1,51 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.util.Date;
/**
* A structure representing a single object stored in S3. Returned as a part of ListBucketResponse.
*/
public class ListEntry {
/**
* The name of the object
*/
public String key;
/**
* The date at which the object was last modified.
*/
public Date lastModified;
/**
* The object's ETag, which can be used for conditional GETs.
*/
public String eTag;
/**
* The size of the object in bytes.
*/
public long size;
/**
* The object's storage class
*/
public String storageClass;
/**
* The object's owner
*/
public Owner owner;
public String toString() {
return key;
}
}

View File

@ -1,89 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006-2007 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.io.IOException;
import java.net.HttpURLConnection;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
/**
* A Response object returned from AWSAuthConnection.getBucketLocation().
* Parses the response XML and exposes the location constraint
* via the geteLocation() method.
*/
public class LocationResponse extends Response {
String location;
/**
* Parse the response to a ?location query.
*/
public LocationResponse(HttpURLConnection connection) throws IOException {
super(connection);
if (connection.getResponseCode() < 400) {
try {
XMLReader xr = Utils.createXMLReader();;
LocationResponseHandler handler = new LocationResponseHandler();
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
xr.parse(new InputSource(connection.getInputStream()));
this.location = handler.location;
} catch (SAXException e) {
throw new RuntimeException("Unexpected error parsing ListAllMyBuckets xml", e);
}
} else {
this.location = "<error>";
}
}
/**
* Report the location-constraint for a bucket.
* A value of null indicates an error;
* the empty string indicates no constraint;
* and any other value is an actual location constraint value.
*/
public String getLocation() {
return location;
}
/**
* Helper class to parse LocationConstraint response XML
*/
static class LocationResponseHandler extends DefaultHandler {
String location = null;
private StringBuffer currText = null;
public void startDocument() {
}
public void startElement(String uri, String name, String qName, Attributes attrs) {
if (name.equals("LocationConstraint")) {
this.currText = new StringBuffer();
}
}
public void endElement(String uri, String name, String qName) {
if (name.equals("LocationConstraint")) {
location = this.currText.toString();
this.currText = null;
}
}
public void characters(char ch[], int start, int length) {
if (currText != null)
this.currText.append(ch, start, length);
}
}
}

View File

@ -1,18 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
/**
* A structure representing the owner of an object, used as a part of ListEntry.
*/
public class Owner {
public String id;
public String displayName;
}

View File

@ -1,264 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006-2007 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* This class mimics the behavior of AWSAuthConnection, except instead of actually performing
* the operation, QueryStringAuthGenerator will return URLs with query string parameters that
* can be used to do the same thing. These parameters include an expiration date, so that
* if you hand them off to someone else, they will only work for a limited amount of time.
*/
public class QueryStringAuthGenerator {
private String awsAccessKeyId;
private String awsSecretAccessKey;
private boolean isSecure;
private String server;
private int port;
private CallingFormat callingFormat;
private Long expiresIn = null;
private Long expires = null;
// by default, expire in 1 minute.
private static final Long DEFAULT_EXPIRES_IN = new Long(60 * 1000);
public QueryStringAuthGenerator(String awsAccessKeyId, String awsSecretAccessKey) {
this(awsAccessKeyId, awsSecretAccessKey, true);
}
public QueryStringAuthGenerator(String awsAccessKeyId, String awsSecretAccessKey,
boolean isSecure)
{
this(awsAccessKeyId, awsSecretAccessKey, isSecure, Utils.DEFAULT_HOST);
}
public QueryStringAuthGenerator(String awsAccessKeyId, String awsSecretAccessKey,
boolean isSecure, String server)
{
this(awsAccessKeyId, awsSecretAccessKey, isSecure, server,
isSecure ? Utils.SECURE_PORT : Utils.INSECURE_PORT);
}
public QueryStringAuthGenerator(String awsAccessKeyId, String awsSecretAccessKey,
boolean isSecure, String server, int port)
{
this(awsAccessKeyId, awsSecretAccessKey, isSecure, server,
port, CallingFormat.getSubdomainCallingFormat());
}
public QueryStringAuthGenerator(String awsAccessKeyId, String awsSecretAccessKey,
boolean isSecure, String server, CallingFormat callingFormat)
{
this(awsAccessKeyId, awsSecretAccessKey, isSecure, server,
isSecure ? Utils.SECURE_PORT : Utils.INSECURE_PORT,
callingFormat);
}
public QueryStringAuthGenerator(String awsAccessKeyId, String awsSecretAccessKey,
boolean isSecure, String server, int port, CallingFormat callingFormat)
{
this.awsAccessKeyId = awsAccessKeyId;
this.awsSecretAccessKey = awsSecretAccessKey;
this.isSecure = isSecure;
this.server = server;
this.port = port;
this.callingFormat = callingFormat;
this.expiresIn = DEFAULT_EXPIRES_IN;
this.expires = null;
}
public void setCallingFormat(CallingFormat format) {
this.callingFormat = format;
}
public void setExpires(long millisSinceEpoch) {
expires = new Long(millisSinceEpoch);
expiresIn = null;
}
public void setExpiresIn(long millis) {
expiresIn = new Long(millis);
expires = null;
}
public String createBucket(String bucket, Map headers)
{
// validate bucket name
if (!Utils.validateBucketName(bucket, callingFormat, false))
throw new IllegalArgumentException("Invalid S3Bucket Name: "+bucket);
Map pathArgs = new HashMap();
return generateURL("PUT", bucket, "", pathArgs, headers);
}
public String listBucket(String bucket, String prefix, String marker,
Integer maxKeys, Map headers){
return listBucket(bucket, prefix, marker, maxKeys, null, headers);
}
public String listBucket(String bucket, String prefix, String marker,
Integer maxKeys, String delimiter, Map headers)
{
Map pathArgs = Utils.paramsForListOptions(prefix, marker, maxKeys, delimiter);
return generateURL("GET", bucket, "", pathArgs, headers);
}
public String deleteBucket(String bucket, Map headers)
{
Map pathArgs = new HashMap();
return generateURL("DELETE", bucket, "", pathArgs, headers);
}
public String put(String bucket, String key, S3Object object, Map headers) {
Map metadata = null;
Map pathArgs = new HashMap();
if (object != null) {
metadata = object.metadata;
}
return generateURL("PUT", bucket, Utils.urlencode(key), pathArgs, mergeMeta(headers, metadata));
}
public String get(String bucket, String key, Map headers)
{
Map pathArgs = new HashMap();
return generateURL("GET", bucket, Utils.urlencode(key), pathArgs, headers);
}
public String delete(String bucket, String key, Map headers)
{
Map pathArgs = new HashMap();
return generateURL("DELETE", bucket, Utils.urlencode(key), pathArgs, headers);
}
public String getBucketLogging(String bucket, Map headers) {
Map pathArgs = new HashMap();
pathArgs.put("logging", null);
return generateURL("GET", bucket, "", pathArgs, headers);
}
public String putBucketLogging(String bucket, String loggingXMLDoc, Map headers) {
Map pathArgs = new HashMap();
pathArgs.put("logging", null);
return generateURL("PUT", bucket, "", pathArgs, headers);
}
public String getBucketACL(String bucket, Map headers) {
return getACL(bucket, "", headers);
}
public String getACL(String bucket, String key, Map headers)
{
Map pathArgs = new HashMap();
pathArgs.put("acl", null);
return generateURL("GET", bucket, Utils.urlencode(key), pathArgs, headers);
}
public String putBucketACL(String bucket, String aclXMLDoc, Map headers) {
return putACL(bucket, "", aclXMLDoc, headers);
}
public String putACL(String bucket, String key, String aclXMLDoc, Map headers)
{
Map pathArgs = new HashMap();
pathArgs.put("acl", null);
return generateURL("PUT", bucket, Utils.urlencode(key), pathArgs, headers);
}
public String listAllMyBuckets(Map headers)
{
Map pathArgs = new HashMap();
return generateURL("GET", "", "", pathArgs, headers);
}
public String makeBareURL(String bucket, String key) {
StringBuffer buffer = new StringBuffer();
if (this.isSecure) {
buffer.append("https://");
} else {
buffer.append("http://");
}
buffer.append(this.server).append(":").append(this.port).append("/").append(bucket);
buffer.append("/").append(Utils.urlencode(key));
return buffer.toString();
}
private String generateURL(String method, String bucketName, String key, Map pathArgs, Map headers)
{
long expires = 0L;
if (this.expiresIn != null) {
expires = System.currentTimeMillis() + this.expiresIn.longValue();
} else if (this.expires != null) {
expires = this.expires.longValue();
} else {
throw new RuntimeException("Illegal expires state");
}
// convert to seconds
expires /= 1000;
String canonicalString = Utils.makeCanonicalString(method, bucketName, key, pathArgs, headers, ""+expires);
String encodedCanonical = Utils.encode(this.awsSecretAccessKey, canonicalString, true);
pathArgs.put("Signature", encodedCanonical);
pathArgs.put("Expires", Long.toString(expires));
pathArgs.put("AWSAccessKeyId", this.awsAccessKeyId);
CallingFormat callingFormat = Utils.getCallingFormatForBucket( this.callingFormat, bucketName );
if ( isSecure && callingFormat != CallingFormat.getPathCallingFormat() && bucketName.indexOf( "." ) != -1 ) {
System.err.println( "You are making an SSL connection, however, the bucket contains periods and the wildcard certificate will not match by default. Please consider using HTTP." );
}
String returnString;
try {
URL url = callingFormat.getURL(isSecure, server, port, bucketName, key, pathArgs);
returnString = url.toString();
} catch (MalformedURLException e) {
returnString = "Exception generating url " + e;
}
return returnString;
}
private Map mergeMeta(Map headers, Map metadata) {
Map merged = new TreeMap();
if (headers != null) {
for (Iterator i = headers.keySet().iterator(); i.hasNext(); ) {
String key = (String)i.next();
merged.put(key, headers.get(key));
}
}
if (metadata != null) {
for (Iterator i = metadata.keySet().iterator(); i.hasNext(); ) {
String key = (String)i.next();
String metadataKey = Utils.METADATA_PREFIX + key;
if (merged.containsKey(metadataKey)) {
((List)merged.get(metadataKey)).addAll((List)metadata.get(key));
} else {
merged.put(metadataKey, metadata.get(key));
}
}
}
return merged;
}
}

View File

@ -1,25 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.net.HttpURLConnection;
import java.io.IOException;
/**
* The parent class of all other Responses. This class keeps track of the
* HttpURLConnection response.
*/
public class Response {
public HttpURLConnection connection;
public Response(HttpURLConnection connection) throws IOException {
this.connection = connection;
}
}

View File

@ -1,30 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.util.Map;
/**
* A representation of a single object stored in S3.
*/
public class S3Object {
public byte[] data;
/**
* A Map from String to List of Strings representing the object's metadata
*/
public Map metadata;
public S3Object(byte[] data, Map metadata) {
this.data = data;
this.metadata = metadata;
}
}

View File

@ -1,324 +0,0 @@
// This software code is made available "AS IS" without warranties of any
// kind. You may copy, display, modify and redistribute the software
// code either by itself or as incorporated into your code; provided that
// you do not remove any proprietary notices. Your use of this software
// code is at your own risk and you waive any claim against Amazon
// Digital Services, Inc. or its affiliates with respect to your use of
// this software code. (c) 2006-2007 Amazon Digital Services, Inc. or its
// affiliates.
package com.amazon.s3;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.SAXException;
import com.amazon.thirdparty.Base64;
public class Utils {
static final String METADATA_PREFIX = "x-amz-meta-";
static final String AMAZON_HEADER_PREFIX = "x-amz-";
static final String ALTERNATIVE_DATE_HEADER = "x-amz-date";
public static final String DEFAULT_HOST = "s3.amazonaws.com";
public static final int SECURE_PORT = 443;
public static final int INSECURE_PORT = 80;
/**
* HMAC/SHA1 Algorithm per RFC 2104.
*/
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
static String makeCanonicalString(String method, String bucket, String key, Map pathArgs, Map headers) {
return makeCanonicalString(method, bucket, key, pathArgs, headers, null);
}
/**
* Calculate the canonical string. When expires is non-null, it will be
* used instead of the Date header.
*/
static String makeCanonicalString(String method, String bucketName, String key, Map pathArgs,
Map headers, String expires)
{
StringBuffer buf = new StringBuffer();
buf.append(method + "\n");
// Add all interesting headers to a list, then sort them. "Interesting"
// is defined as Content-MD5, Content-Type, Date, and x-amz-
SortedMap interestingHeaders = new TreeMap();
if (headers != null) {
for (Iterator i = headers.keySet().iterator(); i.hasNext(); ) {
String hashKey = (String)i.next();
if (hashKey == null) continue;
String lk = hashKey.toLowerCase();
// Ignore any headers that are not particularly interesting.
if (lk.equals("content-type") || lk.equals("content-md5") || lk.equals("date") ||
lk.startsWith(AMAZON_HEADER_PREFIX))
{
List s = (List)headers.get(hashKey);
interestingHeaders.put(lk, concatenateList(s));
}
}
}
if (interestingHeaders.containsKey(ALTERNATIVE_DATE_HEADER)) {
interestingHeaders.put("date", "");
}
// if the expires is non-null, use that for the date field. this
// trumps the x-amz-date behavior.
if (expires != null) {
interestingHeaders.put("date", expires);
}
// these headers require that we still put a new line in after them,
// even if they don't exist.
if (! interestingHeaders.containsKey("content-type")) {
interestingHeaders.put("content-type", "");
}
if (! interestingHeaders.containsKey("content-md5")) {
interestingHeaders.put("content-md5", "");
}
// Finally, add all the interesting headers (i.e.: all that startwith x-amz- ;-))
for (Iterator i = interestingHeaders.keySet().iterator(); i.hasNext(); ) {
String headerKey = (String)i.next();
if (headerKey.startsWith(AMAZON_HEADER_PREFIX)) {
buf.append(headerKey).append(':').append(interestingHeaders.get(headerKey));
} else {
buf.append(interestingHeaders.get(headerKey));
}
buf.append("\n");
}
// build the path using the bucket and key
if (bucketName != null && !bucketName.equals("")) {
buf.append("/" + bucketName );
}
// append the key (it might be an empty string)
// append a slash regardless
buf.append("/");
if(key != null) {
buf.append(key);
}
// if there is an acl, logging or torrent parameter
// add them to the string
if (pathArgs != null ) {
if (pathArgs.containsKey("acl")) {
buf.append("?acl");
} else if (pathArgs.containsKey("torrent")) {
buf.append("?torrent");
} else if (pathArgs.containsKey("logging")) {
buf.append("?logging");
} else if (pathArgs.containsKey("location")) {
buf.append("?location");
}
}
return buf.toString();
}
/**
* Calculate the HMAC/SHA1 on a string.
* @param data Data to sign
* @param passcode Passcode to sign it with
* @return Signature
* @throws NoSuchAlgorithmException If the algorithm does not exist. Unlikely
* @throws InvalidKeyException If the key is invalid.
*/
static String encode(String awsSecretAccessKey, String canonicalString,
boolean urlencode)
{
// The following HMAC/SHA1 code for the signature is taken from the
// AWS Platform's implementation of RFC2104 (amazon.webservices.common.Signature)
//
// Acquire an HMAC/SHA1 from the raw key bytes.
SecretKeySpec signingKey =
new SecretKeySpec(awsSecretAccessKey.getBytes(), HMAC_SHA1_ALGORITHM);
// Acquire the MAC instance and initialize with the signing key.
Mac mac = null;
try {
mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
// should not happen
throw new RuntimeException("Could not find sha1 algorithm", e);
}
try {
mac.init(signingKey);
} catch (InvalidKeyException e) {
// also should not happen
throw new RuntimeException("Could not initialize the MAC algorithm", e);
}
// Compute the HMAC on the digest, and set it.
String b64 = Base64.encodeBytes(mac.doFinal(canonicalString.getBytes()));
if (urlencode) {
return urlencode(b64);
} else {
return b64;
}
}
static Map paramsForListOptions(String prefix, String marker, Integer maxKeys) {
return paramsForListOptions(prefix, marker, maxKeys, null);
}
static Map paramsForListOptions(String prefix, String marker, Integer maxKeys, String delimiter) {
Map argParams = new HashMap();
// these three params must be url encoded
if (prefix != null)
argParams.put("prefix", urlencode(prefix));
if (marker != null)
argParams.put("marker", urlencode(marker));
if (delimiter != null)
argParams.put("delimiter", urlencode(delimiter));
if (maxKeys != null)
argParams.put("max-keys", Integer.toString(maxKeys.intValue()));
return argParams;
}
/**
* Converts the Path Arguments from a map to String which can be used in url construction
* @param pathArgs a map of arguments
* @return a string representation of pathArgs
*/
public static String convertPathArgsHashToString(Map pathArgs) {
StringBuffer pathArgsString = new StringBuffer();
String argumentValue;
boolean firstRun = true;
if (pathArgs != null) {
for (Iterator argumentIterator = pathArgs.keySet().iterator(); argumentIterator.hasNext(); ) {
String argument = (String)argumentIterator.next();
if (firstRun) {
firstRun = false;
pathArgsString.append("?");
} else {
pathArgsString.append("&");
}
argumentValue = (String)pathArgs.get(argument);
pathArgsString.append(argument);
if (argumentValue != null) {
pathArgsString.append("=");
pathArgsString.append(argumentValue);
}
}
}
return pathArgsString.toString();
}
static String urlencode(String unencoded) {
try {
return URLEncoder.encode(unencoded, "UTF-8");
} catch (UnsupportedEncodingException e) {
// should never happen
throw new RuntimeException("Could not url encode to UTF-8", e);
}
}
static XMLReader createXMLReader() {
try {
return XMLReaderFactory.createXMLReader();
} catch (SAXException e) {
// oops, lets try doing this (needed in 1.4)
System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
}
try {
// try once more
return XMLReaderFactory.createXMLReader();
} catch (SAXException e) {
throw new RuntimeException("Couldn't initialize a sax driver for the XMLReader");
}
}
/**
* Concatenates a bunch of header values, seperating them with a comma.
* @param values List of header values.
* @return String of all headers, with commas.
*/
private static String concatenateList(List values) {
StringBuffer buf = new StringBuffer();
for (int i = 0, size = values.size(); i < size; ++ i) {
buf.append(((String)values.get(i)).replaceAll("\n", "").trim());
if (i != (size - 1)) {
buf.append(",");
}
}
return buf.toString();
}
/**
* Validate bucket-name
*/
static boolean validateBucketName(String bucketName, CallingFormat callingFormat, boolean located) {
if (callingFormat == CallingFormat.getPathCallingFormat())
{
final int MIN_BUCKET_LENGTH = 3;
final int MAX_BUCKET_LENGTH = 255;
final String BUCKET_NAME_REGEX = "^[0-9A-Za-z\\.\\-_]*$";
return null != bucketName &&
bucketName.length() >= MIN_BUCKET_LENGTH &&
bucketName.length() <= MAX_BUCKET_LENGTH &&
bucketName.matches(BUCKET_NAME_REGEX);
} else {
return isValidSubdomainBucketName( bucketName );
}
}
static boolean isValidSubdomainBucketName( String bucketName ) {
final int MIN_BUCKET_LENGTH = 3;
final int MAX_BUCKET_LENGTH = 63;
// don't allow names that look like 127.0.0.1
final String IPv4_REGEX = "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$";
// dns sub-name restrictions
final String BUCKET_NAME_REGEX = "^[a-z0-9]([a-z0-9\\-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9\\-]*[a-z0-9])?)*$";
// If there wasn't a location-constraint, then the current actual
// restriction is just that no 'part' of the name (i.e. sequence
// of characters between any 2 '.'s has to be 63) but the recommendation
// is to keep the entire bucket name under 63.
return null != bucketName &&
bucketName.length() >= MIN_BUCKET_LENGTH &&
bucketName.length() <= MAX_BUCKET_LENGTH &&
!bucketName.matches(IPv4_REGEX) &&
bucketName.matches(BUCKET_NAME_REGEX);
}
static CallingFormat getCallingFormatForBucket( CallingFormat desiredFormat, String bucketName ) {
CallingFormat callingFormat = desiredFormat;
if ( callingFormat == CallingFormat.getSubdomainCallingFormat() && ! Utils.isValidSubdomainBucketName( bucketName ) ) {
callingFormat = CallingFormat.getPathCallingFormat();
}
return callingFormat;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,84 +0,0 @@
This is one of a collection of interface libraries that can be used to interact
with the Amazon S3 system in a number of different languages. They each expose
two main interface classes, AWSAuthConnection and QueryStringAuthGenerator.
The first actually performs all the operations using the appropriate libraries
for the language, including header signing. The second,
QueryStringAuthGenerator, has the same interface, but instead of performing
the operation, this class will return urls with the right query string
authentication parameters set.
Basic Operations:
object requests:
GetResponse get(bucketName, keyName) - retrieves an object
GetResponse getACL(bucketName, keyName) - returns the xml acl doc
Response put(bucketName, keyName, object) - writes an object
Response putACL(bucketName, keyName, aclXMLDoc) - sets the xml acl doc
Response delete(bucketName, keyName) - deletes an object
bucket requests:
Response createBucket(bucketName, location) - creates a bucket
ListResponse listBucket(bucketName) - lists a bucket's contents
LocationResponse getBucketLocation(bucketName) - return the location-constraint of this bucket
GetResponse getBucketACL(bucketName) - returns the xml representation of this bucket's access control list
Response putBucketAcl(bucketName, aclXMLDoc) - sets xml representation of the bucket acl
Response deleteBucket(bucketName) - delete an empty bucket
GetResponse getBucketLogging(bucketName) - returns the xml representation of this bucket's access logging configuration
Response putBucketLogging(bucketName, loggingXMLDoc) - sets the xml representation of the bucket logging configuration
ListAllMyBucketsResponse listAllMyBuckets() - returns a list of all buckets owned by this AWS Access Key Id
Dependencies:
None, beyond the standard libraries.
Notes:
Please note that this uses the public domain iHarder.net Base64 library. For updates to that library,
see http://iharder.sourceforge.net/current/java/base64/ .
If your bucket name contains periods, you will need to use a non-HTTPS connection as the SSL certificate
presented by s3.amazonaws.com will not match if you do.
Limitations:
One of the main limitations of these sample AWSAuthConnection implementations
is that the interfaces are not streaming. This means that you have to pass the
data in as a string or as a byte array and the operation returns a string or a
byte array back. This is conceptually simpler, and fine for smaller objects,
but large objects, say a couple megabytes or greater, will show poor
performance, since everything is being passed around in memory. More
sophisticated libraries would pass streams in and out, and would only read the
data on-demand, rather than storing it all in memory (S3 itself would have no
problem with such streaming applications). Another upshot of this is that the
interfaces are all blocking---that is, you cannot look at the data until all of
it has downloaded. Again, this is fine for smaller objects, but unacceptable
for larger ones.
These libraries have nearly non-existent error handling. All errors from lower
libraries are simply passed up. The response code in the connection object needs
to be checked after each request to verify whether the request succeeded.
Only the java library has proper handling for repeated headers. The others
assume that each header will have only one value.
It is our intention that these libraries act as a starting point for future
development. They are meant to show off the various operations and provide an
example of how to negotiate the authentication process.
This software code is made available "AS IS" without warranties of any
kind. You may copy, display, modify and redistribute the software
code either by itself or as incorporated into your code; provided that
you do not remove any proprietary notices. Your use of this software
code is at your own risk and you waive any claim against Amazon
Digital Services, Inc. or its affiliates with respect to your use of
this software code. (c) 2006 Amazon Digital Services, Inc. or its
affiliates.

View File

@ -1,131 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import org.jclouds.aws.s3.reference.S3Constants;
import org.testng.ITestContext;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ExecutionException;
/**
* Runs operations that amazon s3 sample code is capable of performing.
*
* @author Adrian Cole
*/
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.AmazonPerformance")
public class AmazonPerformanceTest extends BasePerformance {
private AWSAuthConnection amzClient;
@Override
@BeforeTest
@Parameters({S3Constants.PROPERTY_AWS_ACCESSKEYID,
S3Constants.PROPERTY_AWS_SECRETACCESSKEY})
protected void setUpCredentials(@Optional String AWSAccessKeyId,
@Optional String AWSSecretAccessKey, ITestContext context) throws Exception {
super.setUpCredentials(AWSAccessKeyId, AWSSecretAccessKey, context);
amzClient = new AWSAuthConnection(AWSAccessKeyId, AWSSecretAccessKey,
false);
}
@Override
@Test(enabled = false)
public void testPutFileSerial() throws Exception {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutFileParallel() throws InterruptedException,
ExecutionException {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutInputStreamSerial() throws Exception {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutInputStreamParallel() throws InterruptedException,
ExecutionException {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutStringSerial() throws Exception {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutStringParallel() throws InterruptedException,
ExecutionException {
throw new UnsupportedOperationException();
}
@Override
protected boolean putByteArray(String bucket, String key, byte[] data,
String contentType) throws Exception {
com.amazon.s3.S3Object object = new com.amazon.s3.S3Object(data, null);
Map<String, List<String>> headers = new TreeMap<String, List<String>>();
headers
.put("Content-Type", Arrays
.asList(new String[]{contentType}));
return amzClient.put(bucket, key, object, headers).connection
.getResponseMessage() != null;
}
@Override
protected boolean putFile(String bucket, String key, File data,
String contentType) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected boolean putInputStream(String bucket, String key,
InputStream data, String contentType) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected boolean putString(String bucket, String key, String data,
String contentType) throws Exception {
throw new UnsupportedOperationException();
}
}

View File

@ -1,94 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import java.io.File;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
/**
* // TODO: Adrian: Document this!
*
* @author Adrian Cole
*/
public abstract class BaseJCloudsPerformance extends BasePerformance {
// boolean get
// (
// int id) throws Exception {
// S3Bucket s3Bucket = new S3Bucket();
// s3Bucket.setName(bucketPrefix + "-jclouds-puts");
// org.jclouds.aws.s3.domain.S3Object object = new
// org.jclouds.aws.s3.domain.S3Object();
// object.setKey(id + "");
// //object.setContentType("text/plain");
// object.setContentType("application/octetstream");
// //object.setData("this is a test");
// object.setData(test);
// return clientProvider.getObject(s3Bucket,
// object.getKey()).get(120,TimeUnit.SECONDS) !=
// org.jclouds.aws.s3.domain.S3Object.NOT_FOUND;
// }
@Override
protected boolean putByteArray(String bucket, String key, byte[] data,
String contentType) throws Exception {
org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object(
key);
object.getMetadata().setContentType(contentType);
object.setData(data);
return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null;
}
@Override
protected boolean putFile(String bucket, String key, File data,
String contentType) throws Exception {
org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object(
key);
object.getMetadata().setContentType(contentType);
object.setData(data);
return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null;
}
@Override
protected boolean putInputStream(String bucket, String key,
InputStream data, String contentType) throws Exception {
org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object(
key);
object.getMetadata().setContentType(contentType);
object.setData(data);
object.getMetadata().setSize(data.available());
return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null;
}
@Override
protected boolean putString(String bucket, String key, String data,
String contentType) throws Exception {
org.jclouds.aws.s3.domain.S3Object object = new org.jclouds.aws.s3.domain.S3Object(
key);
object.getMetadata().setContentType(contentType);
object.setData(data);
return client.putObject(bucket, object).get(120, TimeUnit.SECONDS) != null;
}
}

View File

@ -1,252 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import com.google.inject.Provider;
import org.jclouds.aws.s3.S3IntegrationTest;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.testng.ITestContext;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* // TODO: Adrian: Document this!
*
* @author Adrian Cole
*/
@Test
public abstract class BasePerformance extends S3IntegrationTest {
protected boolean debugEnabled() {
return false;
}
protected static int LOOP_COUNT = 100;
protected ExecutorService exec;
protected final String BUCKET_BYTES = bucketPrefix + "-bytes";
protected final String BUCKET_INPUTSTREAM = bucketPrefix + "-inputstream";
protected final String BUCKET_STRING = bucketPrefix + "-string";
protected final String BUCKET_FILE = bucketPrefix + "-file";
protected final String[] BUCKETS = {BUCKET_BYTES, BUCKET_INPUTSTREAM,
BUCKET_STRING, BUCKET_FILE};
protected PutBytesCallable putBytesCallable;
protected PutFileCallable putFileCallable;
protected PutInputStreamCallable putInputStreamCallable;
protected PutStringCallable putStringCallable;
protected CompletionService<Boolean> completer;
@BeforeTest
protected void setUpCallables() {
putBytesCallable = new PutBytesCallable();
putFileCallable = new PutFileCallable();
putInputStreamCallable = new PutInputStreamCallable();
putStringCallable = new PutStringCallable();
exec = Executors.newCachedThreadPool();
completer = new ExecutorCompletionService<Boolean>(exec);
}
@Override
@BeforeTest
protected void setUpClient(ITestContext context) throws Exception {
super.setUpClient(context);
for (String bucket : BUCKETS) {
client.putBucketIfNotExists(bucket).get(10, TimeUnit.SECONDS);
}
}
@AfterTest
protected void tearDownExecutor() throws Exception {
exec.shutdownNow();
exec = null;
}
@Test(enabled = true)
public void testPutBytesSerial() throws Exception {
doSerial(putBytesCallable, LOOP_COUNT / 10);
}
@Test(enabled = true)
public void testPutBytesParallel() throws InterruptedException,
ExecutionException, TimeoutException {
doParallel(putBytesCallable, LOOP_COUNT);
}
@Test(enabled = true)
public void testPutFileSerial() throws Exception {
doSerial(putFileCallable, LOOP_COUNT / 10);
}
@Test(enabled = true)
public void testPutFileParallel() throws InterruptedException,
ExecutionException, TimeoutException {
doParallel(putFileCallable, LOOP_COUNT);
}
@Test(enabled = true)
public void testPutInputStreamSerial() throws Exception {
doSerial(putInputStreamCallable, LOOP_COUNT / 10);
}
@Test(enabled = true)
public void testPutInputStreamParallel() throws InterruptedException,
ExecutionException, TimeoutException {
doParallel(putInputStreamCallable, LOOP_COUNT);
}
@Test(enabled = true)
public void testPutStringSerial() throws Exception {
doSerial(putStringCallable, LOOP_COUNT / 10);
}
@Test(enabled = true)
public void testPutStringParallel() throws InterruptedException,
ExecutionException, TimeoutException {
doParallel(putStringCallable, LOOP_COUNT);
}
private void doSerial(Provider<Callable<Boolean>> provider, int loopCount)
throws Exception, ExecutionException {
for (int i = 0; i < loopCount; i++)
assert provider.get().call();
}
private void doParallel(Provider<Callable<Boolean>> provider, int loopCount)
throws InterruptedException, ExecutionException, TimeoutException {
for (int i = 0; i < loopCount; i++)
completer.submit(provider.get());
for (int i = 0; i < loopCount; i++)
assert completer.take().get(10, TimeUnit.SECONDS);
}
class PutBytesCallable implements Provider<Callable<Boolean>> {
final AtomicInteger key = new AtomicInteger(0);
protected byte[] test = new byte[1024 * 2];
public Callable<Boolean> get() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
return putByteArray(BUCKET_BYTES, key.getAndIncrement()
+ "", test, "application/octetstring");
}
};
}
}
class PutFileCallable implements Provider<Callable<Boolean>> {
final AtomicInteger key = new AtomicInteger(0);
protected File file = new File("pom.xml");
public Callable<Boolean> get() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
return putFile(BUCKET_FILE, key.getAndIncrement() + "",
file, "text/xml");
}
};
}
}
class PutInputStreamCallable extends PutBytesCallable {
final AtomicInteger key = new AtomicInteger(0);
@Override
public Callable<Boolean> get() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
return putInputStream(BUCKET_INPUTSTREAM, key
.getAndIncrement()
+ "", new ByteArrayInputStream(test),
"application/octetstring");
}
};
}
}
class PutStringCallable implements Provider<Callable<Boolean>> {
final AtomicInteger key = new AtomicInteger(0);
protected String testString = "hello world!";
public Callable<Boolean> get() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
return putString(BUCKET_STRING, key.getAndIncrement() + "",
testString, "text/plain");
}
};
}
}
protected abstract boolean putByteArray(String bucket, String key,
byte[] data, String contentType) throws Exception;
protected abstract boolean putFile(String bucket, String key, File data,
String contentType) throws Exception;
protected abstract boolean putInputStream(String bucket, String key,
InputStream data, String contentType) throws Exception;
protected abstract boolean putString(String bucket, String key,
String data, String contentType) throws Exception;
// private class BucketDeleter implements Callable<Boolean> {
// private BucketDeleter(S3Bucket bucket) {
// this.bucket = bucket;
// }
//
// private S3Bucket bucket;
//
// @Override
// public String toString() {
// return "BucketDeleter{" + "bucket=" + bucket + '}';
// }
//
// public Boolean call() throws Exception {
// bucket =
// clientProvider.get(10,TimeUnit.SECONDS).getBucket(bucket).get(10,TimeUnit.SECONDS);
// List<Future<Boolean>> deletes = new ArrayList<Future<Boolean>>();
// for (org.jclouds.aws.s3.domain.S3Object object : bucket
// .getContents()) {
// deletes.add(clientProvider.get(10,TimeUnit.SECONDS).deleteObject(bucket,
// object.getKey()));
// }
// for (Future<Boolean> isdeleted : deletes)
// assert isdeleted.get(10,TimeUnit.SECONDS) :
// String.format("failed to delete %1$ss",
// isdeleted);
// return
// clientProvider.get(10,TimeUnit.SECONDS).deleteBucket(bucket).get(10,TimeUnit.SECONDS);
// }
// }
}

View File

@ -1,183 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.util.DateService;
import org.joda.time.DateTime;
import org.testng.annotations.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SimpleTimeZone;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
/**
* Compares performance of date operations
*
* @author Adrian Cole
*/
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.DateTest")
public class DateServiceTest extends PerformanceTest {
Injector i = Guice.createInjector();
DateService utils = i.getInstance(DateService.class);
SimpleDateFormat dateParser;
public DateServiceTest() {
this.dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
this.dateParser.setTimeZone(new SimpleTimeZone(0, "GMT"));
}
Date amazonDateFromString(String toParse) throws ParseException {
return this.dateParser.parse(toParse);
}
private static String toParse = "2009-03-12T02:00:07.000Z";
@Test
public void testParseDateSameAsAmazon() throws ParseException,
ExecutionException, InterruptedException {
Date java = dateParser.parse(toParse);
DateTime joda = utils.dateTimeFromXMLFormat(toParse);
assert java.equals(joda.toDate());
}
@Test
public void testTimeStampDateSameAsAmazon() throws ExecutionException,
InterruptedException {
String java = AWSAuthConnection.httpDate();
String joda = utils.timestampAsHeaderString();
assert java.equals(joda);
}
@Test
public void testToHeaderString() throws ExecutionException,
InterruptedException {
String joda1 = utils.toHeaderString(new DateTime());
String joda = utils.timestampAsHeaderString();
assert joda1.equals(joda);
}
@Test
void testTimeStampSerialResponseTime() throws ExecutionException,
InterruptedException {
for (int i = 0; i < LOOP_COUNT; i++)
utils.timestampAsHeaderString();
}
@Test
void testAmazonTimeStampSerialResponseTime() {
for (int i = 0; i < LOOP_COUNT; i++)
AWSAuthConnection.httpDate();
}
@Test
void testTimeStampParallelResponseTime() throws InterruptedException,
ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() throws ExecutionException,
InterruptedException {
utils.timestampAsHeaderString();
return true;
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
}
@Test
void testAmazonTimeStampParallelResponseTime() throws InterruptedException,
ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() {
AWSAuthConnection.httpDate();
return true;
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
}
@Test
void testParseDateSerialResponseTime() throws ExecutionException,
InterruptedException {
for (int i = 0; i < LOOP_COUNT; i++)
utils.dateTimeFromXMLFormat(toParse);
}
@Test
void testAmazonParseDateSerialResponseTime() {
for (int i = 0; i < LOOP_COUNT; i++)
AWSAuthConnection.httpDate();
}
@Test
void testParseDateParallelResponseTime() throws InterruptedException,
ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() throws ExecutionException,
InterruptedException {
utils.dateTimeFromXMLFormat(toParse);
return true;
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
}
@Test
void testAmazonParseDateParallelResponseTime() throws InterruptedException,
ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() {
AWSAuthConnection.httpDate();
return true;
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
}
}

View File

@ -1,53 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import java.util.Properties;
import org.jclouds.http.httpnio.config.HttpNioConnectionPoolClientModule;
import org.testng.annotations.Test;
import com.google.inject.Module;
@Test(sequential=true, testName = "s3.JCloudsNioPerformance")
public class JCloudsNioPerformanceTest extends BaseJCloudsPerformance {
@Override
protected Properties buildS3Properties(String AWSAccessKeyId,
String AWSSecretAccessKey) {
Properties properties = super.buildS3Properties(AWSAccessKeyId, AWSSecretAccessKey);
properties.setProperty("jclouds.http.pool.max_connection_reuse", "75");
properties.setProperty("jclouds.http.pool.max_session_failures", "2");
properties.setProperty("jclouds.http.pool.request_invoker_threads", "1");
properties.setProperty("jclouds.http.pool.io_worker_threads", "2");
properties.setProperty("jclouds.pool.max_connections", "12");
return properties;
}
@Override
protected Module createHttpModule() {
return new HttpNioConnectionPoolClientModule();
}
}

View File

@ -1,37 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import org.testng.annotations.Test;
/**
* Tests the default JClouds client.
*
* @author Adrian Cole
*
*/
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.JCloudsPerformance")
public class JCloudsPerformanceTest extends BaseJCloudsPerformance {
}

View File

@ -1,130 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import org.jets3t.service.S3Service;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.security.AWSCredentials;
import org.testng.ITestContext;
import org.testng.annotations.Test;
import java.io.File;
import java.io.InputStream;
import java.util.concurrent.ExecutionException;
/**
* Runs operations that jets3t is capable of performing.
*
* @author Adrian Cole
*/
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.Jets3tPerformance")
public class Jets3tPerformanceTest extends BasePerformance {
private S3Service jetClient;
@Override
protected void setUpCredentials(String AWSAccessKeyId, String AWSSecretAccessKey, ITestContext context)
throws Exception {
super.setUpCredentials(AWSAccessKeyId, AWSSecretAccessKey, context);
jetClient = new RestS3Service(new AWSCredentials(AWSAccessKeyId,
AWSSecretAccessKey));
}
@Override
@Test(enabled = false)
public void testPutStringSerial() throws Exception {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutBytesSerial() throws Exception {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutStringParallel() throws InterruptedException,
ExecutionException {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutBytesParallel() throws InterruptedException,
ExecutionException {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutInputStreamParallel() throws InterruptedException,
ExecutionException {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
public void testPutFileParallel() throws InterruptedException,
ExecutionException {
throw new UnsupportedOperationException();
}
@Override
@Test(enabled = false)
protected boolean putByteArray(String bucket, String key, byte[] data,
String contentType) throws Exception {
throw new UnsupportedOperationException();
}
@Override
protected boolean putFile(String bucket, String key, File data,
String contentType) throws Exception {
org.jets3t.service.model.S3Object object = new org.jets3t.service.model.S3Object(
key);
object.setContentType(contentType);
object.setDataInputFile(data);
object.setContentLength(data.length());
return jetClient.putObject(bucket, object) != null;
}
@Override
protected boolean putInputStream(String bucket, String key,
InputStream data, String contentType) throws Exception {
org.jets3t.service.model.S3Object object = new org.jets3t.service.model.S3Object(
key);
object.setContentType(contentType);
object.setDataInputStream(data);
object.setContentLength(data.available());
return jetClient.putObject(bucket, object) != null;
}
@Override
protected boolean putString(String bucket, String key, String data,
String contentType) throws Exception {
throw new UnsupportedOperationException();
}
}

View File

@ -1,169 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
/**
* Compares performance of xml parsing apis.
*
* @author Adrian Cole
*/
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.S3ParserTest")
public class S3ParserTest extends org.jclouds.aws.s3.commands.S3ParserTest {
class MockHttpURLConnection extends HttpURLConnection {
private String content;
@Override
public InputStream getInputStream() throws IOException {
return IOUtils.toInputStream(content);
}
protected MockHttpURLConnection(String content) {
super(null);
this.content = content;
}
public void disconnect() {
}
public boolean usingProxy() {
return false;
}
@Override
public int getResponseCode() throws IOException {
return 200;
}
public void connect() throws IOException {
}
}
@Test
void testAmazonParseListAllMyBucketsSerialResponseTime() throws IOException {
for (int i = 0; i < LOOP_COUNT; i++)
runAmazonParseListAllMyBuckets();
}
@Test
void testAmazonParseListAllMyBucketsParallelResponseTime()
throws InterruptedException, ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() throws IOException {
runAmazonParseListAllMyBuckets();
return true;
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
}
@SuppressWarnings("unchecked")
@Test(enabled = false)
public void testAmazonCanParseListAllMyBuckets() throws IOException {
ListAllMyBucketsResponse response = runAmazonParseListAllMyBuckets();
List<Bucket> buckets = response.entries;
Bucket bucket1 = (Bucket) buckets.get(0);
assert bucket1.name.equals("adrianjbosstest");
Date expectedDate1 = new DateTime("2009-03-12T02:00:07.000Z").toDate();
Date date1 = bucket1.creationDate;
assert date1.toString().equals(expectedDate1.toString());
Bucket bucket2 = (Bucket) buckets.get(1);
assert bucket2.name.equals("adrianjbosstest2");
Date expectedDate2 = new DateTime("2009-03-12T02:00:09.000Z").toDate();
Date date2 = bucket2.creationDate;
assert date2.toString().equals(expectedDate2.toString());
assert buckets.size() == 2;
}
private ListAllMyBucketsResponse runAmazonParseListAllMyBuckets()
throws IOException {
ListAllMyBucketsResponse response = new ListAllMyBucketsResponse(
new MockHttpURLConnection(listAllMyBucketsResultOn200));
return response;
}
public void testAmazonCanParseListBucketResult() throws IOException {
ListBucketResponse response = runAmazonParseListBucketResult();
ListEntry content = (ListEntry) response.entries.get(0);
assert content.key.equals("3366");
assert content.lastModified.equals(new DateTime(
"2009-03-12T02:00:13.000Z").toDate());
assert content.eTag.equals("\"9d7bb64e8e18ee34eec06dd2cf37b766\"");
assert content.size == 136;
assert content.owner.id
.equals("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0");
assert content.owner.displayName.equals("ferncam");
assert content.storageClass.equals("STANDARD");
}
private ListBucketResponse runAmazonParseListBucketResult()
throws IOException {
ListBucketResponse response = new ListBucketResponse(
new MockHttpURLConnection(listBucketResult));
return response;
}
@Test
void testAmazonParseListBucketResultSerialResponseTime() throws IOException {
for (int i = 0; i < LOOP_COUNT; i++)
runAmazonParseListBucketResult();
}
@Test
void testAmazonParseListBucketResultParallelResponseTime()
throws InterruptedException, ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec);
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() throws IOException {
runAmazonParseListBucketResult();
return true;
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
}
}

View File

@ -1,73 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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 com.amazon.s3;
import org.testng.annotations.Test;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
/**
* Compares performance of encryption operations.
*
* @author Adrian Cole
*
*/
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.S3UtilsTest")
public class S3UtilsTest extends org.jclouds.aws.s3.S3UtilsTest {
@Test(dataProvider = "hmacsha1")
void testAmazonSampleDigestSerialResponseTime(byte[] key, String message, String base64Digest) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {
for (int i = 0; i < 10000; i++)
testAmazonSampleDigest(key, message, base64Digest);
}
@Test(dataProvider = "hmacsha1")
public void testAmazonSampleDigest(byte[] key, String message, String base64Digest) {
String encoded = Utils.encode(new String(key), message, false);
assert encoded.equals(base64Digest);
}
@Test(dataProvider = "hmacsha1")
void testAmazonSampleDigestParallelResponseTime(final byte[] key, final String message, final String base64Digest) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, InterruptedException, ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(exec);
for (int i = 0; i < 10000; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() {
try {
testAmazonSampleDigest(key, message, base64Digest);
return true;
} catch (Exception e) {
return false;
}
}
});
for (int i = 0; i < 10000; i++) assert completer.take().get();
}
}

View File

@ -1,184 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$HeadURL$
$Revision$
$Date$
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.html
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.
====================================================================
-->
<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/maven-v4_0_0.xsd">
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-s3</artifactId>
<name>jclouds Amazon S3 Components Core</name>
<packaging>jar</packaging>
<description>jclouds Core components to access Amazon S3</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/s3</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/s3</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/s3</url>
</scm>
<properties>
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey>
<jclouds.s3.httpstream.url>http://apache.rediris.es/maven/binaries/apache-maven-2.1.0-bin.tar.bz2
</jclouds.s3.httpstream.url>
<jclouds.s3.httpstream.md5>9268c9de2cccfd0d8fbcdbcfaf517a87</jclouds.s3.httpstream.md5>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk15</artifactId>
<version>140</version>
</dependency>
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<!-- note that the groups/excluded groups don't work due to some problem
in surefire or testng. instead, we have to exclude via file path
<groups>integration</groups>
<excludedGroups>unit,performance,live</excludedGroups> -->
<excludes>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
<systemProperties>
<property>
<name>jclouds.s3.httpstream.url</name>
<value>${jclouds.s3.httpstream.url}</value>
</property>
<property>
<name>jclouds.s3.httpstream.md5</name>
<value>${jclouds.s3.httpstream.md5}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
<configuration>
<!-- note that the groups/excluded groups don't work due to some problem
in surefire or testng. instead, we have to exclude via file path
<groups>unit,performance</groups>
<excludedGroups>integration,live</excludedGroups> -->
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*LiveTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<!-- note that the groups/excluded groups don't work due to some problem
in surefire or testng. instead, we have to exclude via file path
<groups>live,integration</groups>
<excludedGroups>unit,performance</excludedGroups> -->
<excludes>
<exclude>none</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
<include>**/*LiveTest.java</include>
</includes>
<systemProperties>
<property>
<name>jclouds.aws.accesskeyid</name>
<value>${jclouds.aws.accesskeyid}</value>
</property>
<property>
<name>jclouds.aws.secretaccesskey</name>
<value>${jclouds.aws.secretaccesskey}</value>
</property>
<property>
<name>jclouds.s3.httpstream.url</name>
<value>${jclouds.s3.httpstream.url}</value>
</property>
<property>
<name>jclouds.s3.httpstream.md5</name>
<value>${jclouds.s3.httpstream.md5}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -1,54 +0,0 @@
====
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.
====================================================================
====
This samples uses the Google App Engine for Java SDK located at http://googleappengine.googlecode.com/files/appengine-java-sdk-1.2.0.zip
Please unzip the above file and modify your maven settings.xml like below before attempting to run 'mvn install'
<profile>
<id>appengine</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<appengine.home>/path/to/appengine-java-sdk-1.2.0</appengine.home>
</properties>
</profile>
<profile>
<id>aws</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<jclouds.aws.accesskeyid>YOUR_ACCESS_KEY_ID</jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey>YOUR_SECRET_KEY</jclouds.aws.secretaccesskey>
</properties>
</profile>
<repositories>
<repository>
<id>jclouds</id>
<url>http://jclouds.googlecode.com/svn/trunk/repo</url>
</repository>
</repositories>

View File

@ -1,194 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$HeadURL$
$Revision$
$Date$
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.html
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.
====================================================================
-->
<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/maven-v4_0_0.xsd">
<parent>
<artifactId>jclouds-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../../project/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jclouds-gae-s3-example</artifactId>
<packaging>war</packaging>
<name>JClouds Sample for Google App Engine</name>
<description>JClouds Sample for Google App Engine</description>
<properties>
<!-- note you must set the property ${appengine.home} to a valid extraction of appengine-java-sdk -->
<appengine.home>/Users/adriancole/Desktop/appengine-java-sdk-1.2.0</appengine.home>
<devappserver.address>localhost</devappserver.address>
<devappserver.port>8088</devappserver.port>
<jclouds.aws.accesskeyid></jclouds.aws.accesskeyid>
<jclouds.aws.secretaccesskey></jclouds.aws.secretaccesskey>
</properties>
<repositories>
<repository>
<id>guice-snapshot</id>
<url>http://guice-maven.googlecode.com/svn/trunk</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>Main Maven Repo</id>
<url>http://repo1.maven.org/maven2/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-gae</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-s3</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-s3</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>com.google.code.guice</groupId>
<artifactId>guice-servlet</artifactId>
<version>2.0-r943</version>
</dependency>
<dependency>
<artifactId>standard</artifactId>
<groupId>taglibs</groupId>
<version>1.1.2</version>
<type>jar</type>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>jstl</artifactId>
<groupId>javax.servlet</groupId>
<version>1.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-el_1.0_spec</artifactId>
<version>1.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jsp_2.1_spec</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_2.5_spec</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-api</artifactId>
<version>1.2.0</version>
<scope>system</scope>
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<testSourceDirectory>src/it/java</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<testClassesDirectory>target/test-classes</testClassesDirectory>
<systemProperties>
<property>
<name>jclouds.aws.accesskeyid</name>
<value>${jclouds.aws.accesskeyid}</value>
</property>
<property>
<name>jclouds.aws.secretaccesskey</name>
<value>${jclouds.aws.secretaccesskey}</value>
</property>
<property>
<name>appengine.home</name>
<value>${appengine.home}</value>
</property>
<property>
<name>devappserver.address</name>
<value>${devappserver.address}</value>
</property>
<property>
<name>devappserver.port</name>
<value>${devappserver.port}</value>
</property>
<property>
<name>warfile</name>
<value>${project.build.directory}/${project.artifactId}</value>
</property>
</systemProperties>
<additionalClasspathElements>
<additionalClasspathElement>${appengine.home}/lib/appengine-tools-api.jar
</additionalClasspathElement>
</additionalClasspathElements>
<environmentVariables>
<DEBUG>true</DEBUG>
<SDK_BIN>${appengine.home}/bin</SDK_BIN>
<SDK_LIB>${appengine.home}/lib</SDK_LIB>
<SDK_CONFIG>${appengine.home}/config/sdk</SDK_CONFIG>
</environmentVariables>
</configuration>
</execution>
</executions>
<configuration>
<!-- fool default surefire execution in 'test' to not find any test classes -->
<testClassesDirectory>target/classes</testClassesDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,75 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.samples.googleappengine.functest;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;
import org.testng.annotations.AfterTest;
import com.google.appengine.tools.KickStart;
/**
* Basic functionality to start a local google app engine instance.
*
* @author Adrian Cole
*
*/
public abstract class BaseGoogleAppEngineTest {
Thread server;
URL url;
protected void writePropertiesAndStartServer(final String address,
final String port, final String warfile, Properties props)
throws IOException, FileNotFoundException, InterruptedException {
url = new URL(String.format("http://%1$s:%2$s", address, port));
props.store(new FileOutputStream(String.format(
"%1$s/WEB-INF/jclouds.properties", warfile)), "test");
this.server = new Thread(new Runnable() {
public void run() {
KickStart
.main(new String[] {
"com.google.appengine.tools.development.DevAppServerMain",
"--disable_update_check", "-a", address, "-p",
port, warfile });
}
});
server.start();
Thread.sleep(7 * 1000);
}
@SuppressWarnings("deprecation")
@AfterTest
public void stopDevAppServer() throws Exception {
server.stop();
}
}

View File

@ -1,101 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.samples.googleappengine.functest;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.reference.S3Constants;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
/**
* Starts up the Google App Engine for Java Development environment and deploys
* an application which tests S3.
*
* @author Adrian Cole
*
*/
@Test(groups = "integration", enabled = true, sequential = true, testName = "functionalTests")
public class GoogleAppEngineTest extends BaseGoogleAppEngineTest {
private static final String sysAWSAccessKeyId = System
.getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID);
private static final String sysAWSSecretAccessKey = System
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
@BeforeTest
@Parameters( { "warfile", "devappserver.address", "devappserver.port",
S3Constants.PROPERTY_AWS_ACCESSKEYID,
S3Constants.PROPERTY_AWS_SECRETACCESSKEY })
public void startDevAppServer(final String warfile, final String address,
final String port, @Optional String AWSAccessKeyId,
@Optional String AWSSecretAccessKey) throws Exception {
AWSAccessKeyId = AWSAccessKeyId != null ? AWSAccessKeyId
: sysAWSAccessKeyId;
AWSSecretAccessKey = AWSSecretAccessKey != null ? AWSSecretAccessKey
: sysAWSSecretAccessKey;
checkNotNull(AWSAccessKeyId, "AWSAccessKeyId");
checkNotNull(AWSSecretAccessKey, "AWSSecretAccessKey");
Properties props = new Properties();
props.put(S3Constants.PROPERTY_AWS_ACCESSKEYID, AWSAccessKeyId);
props.put(S3Constants.PROPERTY_AWS_SECRETACCESSKEY, AWSSecretAccessKey);
writePropertiesAndStartServer(address, port, warfile, props);
}
@Test
public void shouldPass() throws InterruptedException, IOException {
InputStream i = url.openStream();
String string = IOUtils.toString(i);
assert string.indexOf("Hello World!") >= 0 : string;
}
@Test(invocationCount = 5, enabled = true)
public void testGuiceJCloudsSerial() throws InterruptedException,
IOException {
URL gurl = new URL(url, "/guice/listbuckets.s3");
InputStream i = gurl.openStream();
String string = IOUtils.toString(i);
assert string.indexOf("List") >= 0 : string;
}
@Test(invocationCount = 50, enabled = true, threadPoolSize = 10)
public void testGuiceJCloudsParallel() throws InterruptedException,
IOException {
URL gurl = new URL(url, "/guice/listbuckets.s3");
InputStream i = gurl.openStream();
String string = IOUtils.toString(i);
assert string.indexOf("List") >= 0 : string;
}
}

View File

@ -1,90 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.samples.googleappengine;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.S3ResponseException;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.logging.Logger;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* Shows an example of how to use @{link S3Connection} injected with Guice.
*
* @author Adrian Cole
*/
@Singleton
public class JCloudsServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Inject
S3Context context;
@Resource
protected Logger logger = Logger.NULL;
@Override
protected void doGet(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws ServletException,
IOException {
httpServletResponse.setContentType("text/plain");
Writer writer = httpServletResponse.getWriter();
try {
List<S3Bucket.Metadata> myBuckets = context.getConnection()
.listOwnedBuckets().get(10, TimeUnit.SECONDS);
writer.write("List:\n");
for (S3Bucket.Metadata bucket : myBuckets) {
writer.write(String.format(" %1$s", bucket));
try {
writer.write(String.format(": %1$s entries%n", context
.createInputStreamMap(bucket.getName()).size()));
} catch (S3ResponseException e) {
String message = String.format(
": unable to list entries due to: %1$s%n", e
.getError().getCode());
writer.write(message);
logger.warn(e, "message");
}
}
} catch (Exception e) {
throw new ServletException(e);
}
writer.flush();
writer.close();
}
}

View File

@ -1,100 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.samples.googleappengine.config;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletContextEvent;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.S3ContextFactory;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.gae.config.URLFetchServiceClientModule;
import org.jclouds.samples.googleappengine.JCloudsServlet;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;
/**
* Setup Logging and create Injector for use in testing S3.
*
* @author Adrian Cole
*
*/
public class GuiceServletConfig extends GuiceServletContextListener {
@Inject
S3Context context;
String accessKeyId;
String secretAccessKey;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
Properties props = loadJCloudsProperties(servletContextEvent);
this.accessKeyId = props
.getProperty(S3Constants.PROPERTY_AWS_ACCESSKEYID);
this.secretAccessKey = props
.getProperty(S3Constants.PROPERTY_AWS_SECRETACCESSKEY);
super.contextInitialized(servletContextEvent);
}
private Properties loadJCloudsProperties(
ServletContextEvent servletContextEvent) {
InputStream input = servletContextEvent.getServletContext()
.getResourceAsStream("/WEB-INF/jclouds.properties");
Properties props = new Properties();
try {
props.load(input);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(input);
}
return props;
}
@Override
protected Injector getInjector() {
return S3ContextFactory.createInjector(accessKeyId, secretAccessKey,
false, new URLFetchServiceClientModule(),
new ServletModule() {
@Override
protected void configureServlets() {
serve("*.s3").with(JCloudsServlet.class);
requestInjection(this);
}
});
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
context.close();
super.contextDestroyed(servletContextEvent);
}
}

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.
====================================================================
-->
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>jclouds-s3-example</application>
<version>1</version>
</appengine-web-app>

View File

@ -1,48 +0,0 @@
<!--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.
====================================================================
-->
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
<display-name>jclouds-s3-example</display-name>
<!-- Servlets -->
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/guice/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jclouds.samples.googleappengine.config.GuiceServletConfig</listener-class>
</listener>
</web-app>

View File

@ -1,30 +0,0 @@
<%--
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
====================================================================
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.
====================================================================
--%>
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

View File

@ -1,214 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3;
import org.jclouds.aws.s3.commands.options.*;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* Provides access to S3 via their REST API.
* <p/>
* All commands return a Future of the result from S3. Any exceptions incurred
* during processing will be wrapped in an {@link ExecutionException} as
* documented in {@link Future#get()}.
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/RESTAPI.html" />
*/
public interface S3Connection {
/**
* Retrieve a complete <code>S3Object</code>.
*
* @param bucketName namespace of the object you are retrieving
* @param key unique key in the s3Bucket identifying the object
* @return Future reference to a fully populated S3Object including data
* stored in S3 or {@link S3Object#NOT_FOUND} if not present.
* @see org.jclouds.aws.s3.commands.GetObject
*/
Future<S3Object> getObject(String bucketName, String key);
/**
* Like {@link #getObject(String, String)} except you can use
* {@link GetObjectOptions} to control delivery.
*
* @return S3Object containing data relevant to the
* <code>options</options> specified or {@link S3Object#NOT_FOUND} if not present.
* @throws org.jclouds.http.HttpResponseException
* if the conditions requested set were not satisfied by the
* object on the server.
* @see #getObject(String, String)
* @see GetObjectOptions
*/
Future<S3Object> getObject(String bucketName, String key,
GetObjectOptions options);
/**
* Retrieves the {@link org.jclouds.aws.s3.domain.S3Object.Metadata metadata} of the object associated
* with the key.
*
* @param bucketName namespace of the metadata you are retrieving
* @param key unique key in the s3Bucket identifying the object
* @return metadata associated with the key or
* {@link org.jclouds.aws.s3.domain.S3Object.Metadata#NOT_FOUND} if not present;
* @see org.jclouds.aws.s3.commands.HeadObject
*/
Future<S3Object.Metadata> headObject(String bucketName, String key);
/**
* Removes the object and metadata associated with the key.
*
* @param bucketName namespace of the object you are deleting
* @param key unique key in the s3Bucket identifying the object
* @return true if deleted
* @throws org.jclouds.http.HttpResponseException
* if the bucket is not available
* @see org.jclouds.aws.s3.commands.DeleteObject
*/
Future<Boolean> deleteObject(String bucketName, String key);
/**
* Store data by creating or overwriting an object.
* <p/>
* This method will store the object with the default <code>private</code>
* acl.
*
* @param bucketName namespace of the object you are storing
* @param object contains the data and metadata to create or overwrite
* @return MD5 hash of the content uploaded
* @see org.jclouds.aws.s3.domain.acl.CannedAccessPolicy#PRIVATE
* @see org.jclouds.aws.s3.commands.PutObject
*/
Future<byte[]> putObject(String bucketName, S3Object object);
/**
* Like {@link #putObject(String, S3Object)} except you can use
* {@link CopyObjectOptions} to specify an alternate
* {@link org.jclouds.aws.s3.domain.acl.CannedAccessPolicy acl}, override
* {@link org.jclouds.aws.s3.domain.S3Object.Metadata#getUserMetadata() userMetadata}, or specify
* conditions for copying the object.
*
* @param options options for creating the object
* @throws org.jclouds.http.HttpResponseException
* if the conditions requested set are not satisfied by the
* object on the server.
* @see S3Connection#putObject(String, S3Object)
* @see PutObjectOptions
*/
Future<byte[]> putObject(String bucketName, S3Object object,
PutObjectOptions options);
/**
* Create and name your own bucket in which to store your objects.
*
* @return true, if the bucket was created or already exists
* @see org.jclouds.aws.s3.commands.PutBucket
*/
Future<Boolean> putBucketIfNotExists(String name);
/**
* Like {@link #putBucketIfNotExists(String)} except that you can use
* {@link PutBucketOptions} to create the bucket in EU. Create and name your
*
* @param options for creating your bucket
* @see PutBucketOptions
*/
Future<Boolean> putBucketIfNotExists(String name, PutBucketOptions options);
/**
* Deletes the bucket, if it is empty.
*
* @param s3Bucket what to delete
* @return false, if the bucket was not empty and therefore not deleted
* @see org.jclouds.aws.s3.commands.DeleteBucket
*/
Future<Boolean> deleteBucketIfEmpty(String s3Bucket);
/**
* Copies one object to another bucket, retaining UserMetadata from the
* source. The destination will have a private acl.
*
* @return metadata populated with lastModified and md5 of the new object
* @see org.jclouds.aws.s3.commands.CopyObject
*/
Future<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket,
String destinationObject);
/**
* Like {@link #putObject(String, S3Object)} except you can use
* {@link PutObjectOptions} to specify an alternate
* {@link org.jclouds.aws.s3.domain.acl.CannedAccessPolicy acl}.
*
* @param options options for creating the object
* @throws org.jclouds.http.HttpResponseException
* if the conditions requested set are not satisfied by the
* object on the server.
* @see S3Connection#putObject(String, S3Object)
* @see PutObjectOptions
*/
Future<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket,
String destinationObject, CopyObjectOptions options);
/**
* @see org.jclouds.aws.s3.commands.BucketExists
*/
Future<Boolean> bucketExists(String name);
/**
* Retrieve a complete <code>S3Bucket</code> listing.
*
* @param bucketName namespace of the objects you wish to list
* @return Future reference to a fully populated S3Bucket including metadata
* of the S3Objects it contains or {@link S3Bucket#NOT_FOUND} if not
* present.
* @see org.jclouds.aws.s3.commands.ListBucket
*/
Future<S3Bucket> listBucket(String bucketName);
/**
* Like {@link #listBucket(String)} except you can use
* {@link ListBucketOptions} to control the amount of S3Objects to return.
*
* @return S3Bucket containing a subset of {@link org.jclouds.aws.s3.domain.S3Object.Metadata}
* depending on
* <code>options</options> specified or {@link S3Bucket#NOT_FOUND} if not present.
* @see #listBucket(String)
* @see ListBucketOptions
*/
Future<S3Bucket> listBucket(String name, ListBucketOptions options);
/**
* @return list of all of the buckets owned by the authenticated sender of
* the request.
* @see org.jclouds.aws.s3.commands.ListOwnedBuckets
*/
Future<List<S3Bucket.Metadata>> listOwnedBuckets();
}

View File

@ -1,68 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3;
/**
* Represents an authenticated context to S3.
*
* <h2>Note</h2> Please issue {@link #close()} when you are finished with this
* context in order to release resources.
*
*
* @see S3Connection
* @see S3InputStreamMap
* @see S3ObjectMap
* @author Adrian Cole
*
*/
public interface S3Context {
/**
* low-level api to S3. Threadsafe implementations will return a singleton.
*
* @return a connection to S3
*/
S3Connection getConnection();
/**
* Creates a <code>Map<String,InputStream></code> view of the specified
* bucket.
*
* @param bucket
*/
S3InputStreamMap createInputStreamMap(String bucket);
/**
* Creates a <code>Map<String,S3Object></code> view of the specified bucket.
*
* @param bucket
*/
S3ObjectMap createS3ObjectMap(String bucket);
/**
* Closes all connections to S3.
*/
void close();
}

View File

@ -1,236 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3;
import com.google.common.annotations.VisibleForTesting;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.name.Names;
import org.jclouds.aws.s3.config.LiveS3ConnectionModule;
import org.jclouds.aws.s3.config.S3ConnectionModule;
import org.jclouds.aws.s3.config.S3ContextModule;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_ACCESSKEYID;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_AWS_SECRETACCESSKEY;
import org.jclouds.aws.s3.internal.LiveS3Connection;
import static org.jclouds.command.pool.PoolConstants.*;
import static org.jclouds.http.HttpConstants.*;
import org.jclouds.http.config.HttpFutureCommandClientModule;
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import java.util.List;
import java.util.Properties;
/**
* Creates {@link S3Context} or {@link Injector} instances based on the most
* commonly requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or
* Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default
* {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpFutureCommandClientModule http transports} will be
* installed.
*
* @author Adrian Cole
* @see S3Context
*/
public class S3ContextFactory {
public static final Properties DEFAULT_PROPERTIES;
static {
DEFAULT_PROPERTIES = new Properties();
DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_ADDRESS,
"s3.amazonaws.com");
DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_PORT, "443");
DEFAULT_PROPERTIES.setProperty(PROPERTY_HTTP_SECURE, "true");
DEFAULT_PROPERTIES
.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, "75");
DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, "2");
DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS,
"1");
DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, "2");
DEFAULT_PROPERTIES.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, "12");
}
public static Injector createInjector(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
Properties properties = new Properties(DEFAULT_PROPERTIES);
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId);
properties
.setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey);
return createInjector(properties, modules);
}
public static S3Context createS3Context(String awsAccessKeyId,
String awsSecretAccessKey, Module... modules) {
return createInjector(awsAccessKeyId, awsSecretAccessKey, modules)
.getInstance(S3Context.class);
}
public static Injector createInjector(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, Module... modules) {
Properties properties = new Properties(DEFAULT_PROPERTIES);
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId);
properties
.setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey);
properties
.setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure));
if (!isSecure)
properties.setProperty(PROPERTY_HTTP_PORT, "80");
return createInjector(properties, modules);
}
public static S3Context createS3Context(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, Module... modules) {
return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure,
modules).getInstance(S3Context.class);
}
public static Injector createInjector(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, String server,
Module... modules) {
Properties properties = new Properties(DEFAULT_PROPERTIES);
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId);
properties
.setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey);
properties
.setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure));
properties.setProperty(PROPERTY_HTTP_ADDRESS, server);
if (!isSecure)
properties.setProperty(PROPERTY_HTTP_PORT, "80");
return createInjector(properties, modules);
}
public static S3Context createS3Context(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, String server,
Module... modules) {
return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure,
server, modules).getInstance(S3Context.class);
}
public static S3Context createS3Context(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, String server,
int port, Module... modules) {
return createInjector(awsAccessKeyId, awsSecretAccessKey, isSecure,
server, port, modules).getInstance(S3Context.class);
}
public static Injector createInjector(String awsAccessKeyId,
String awsSecretAccessKey, boolean isSecure, String server,
int port, Module... modules) {
Properties properties = new Properties(DEFAULT_PROPERTIES);
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, awsAccessKeyId);
properties
.setProperty(PROPERTY_AWS_SECRETACCESSKEY, awsSecretAccessKey);
properties
.setProperty(PROPERTY_HTTP_SECURE, Boolean.toString(isSecure));
properties.setProperty(PROPERTY_HTTP_ADDRESS, server);
properties.setProperty(PROPERTY_HTTP_PORT, port + "");
return createInjector(properties, modules);
}
public static S3Context createS3Context(Properties properties,
Module... modules) {
return createInjector(properties, modules).getInstance(S3Context.class);
}
/**
* Bind the given properties and install the list of modules. If no modules
* are specified, install the default {@link JDKLoggingModule}
* {@link JavaUrlHttpFutureCommandClientModule}
*
* @param properties - contains constants used by jclouds
* {@link #DEFAULT_PROPERTIES}
* @param configModules - alternative configuration modules
*/
public static Injector createInjector(final Properties properties,
Module... configModules) {
final List<Module> modules = Lists.newArrayList(configModules);
addLoggingModuleIfNotPresent(modules);
addHttpModuleIfNeededAndNotPresent(modules);
addS3ConnectionModuleIfNotPresent(modules);
return Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
Names.bindProperties(binder(), checkNotNull(properties,
"properties"));
for (Module module : modules)
install(module);
}
}, new S3ContextModule());
}
@VisibleForTesting
static void addHttpModuleIfNeededAndNotPresent(final List<Module> modules) {
if (Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) {
return input instanceof LiveS3ConnectionModule;
}
}) && (!Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) {
return input.getClass().isAnnotationPresent(
HttpFutureCommandClientModule.class);
}
})))
modules.add(new JavaUrlHttpFutureCommandClientModule());
}
@VisibleForTesting
static void addS3ConnectionModuleIfNotPresent(final List<Module> modules) {
if (!Iterables.any(modules, new Predicate<Module>() {
public boolean apply(Module input) {
return input.getClass().isAnnotationPresent(
S3ConnectionModule
.class);
}
})){
modules.add(new LiveS3ConnectionModule());
}
}
@VisibleForTesting
static void addLoggingModuleIfNotPresent(final List<Module> modules) {
if (!Iterables.any(modules, Predicates.instanceOf(LoggingModule.class)))
modules.add(new JDKLoggingModule());
}
}

View File

@ -1,55 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3;
import java.io.File;
import java.io.InputStream;
import java.util.Map;
/**
* Map view of an {@link org.jclouds.aws.s3.domain.S3Bucket}. Provides additional methods for inserting
* common object types.
* <p/>
* <h2>Note</h2> All <code>put</code> operations will invoke
* {@link org.jclouds.aws.s3.domain.S3Object#generateMd5}. By extension, {@link #put(Object, Object)}
* will result in the InputStream being converted to a byte array. For this
* reason, do not use {@link #put(Object, Object)} to store files. Use
* {@link #putFile(String, File)} or {@link S3ObjectMap} instead.
*
* @author Adrian Cole
*/
public interface S3InputStreamMap extends S3Map<String, InputStream> {
InputStream putString(String key, String value);
InputStream putFile(String key, File value);
InputStream putBytes(String key, byte[] value);
void putAllStrings(Map<? extends String, ? extends String> map);
void putAllBytes(Map<? extends String, ? extends byte[]> map);
void putAllFiles(Map<? extends String, ? extends File> map);
}

View File

@ -1,45 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3;
import java.util.Map;
import org.jclouds.aws.s3.domain.S3Bucket;
/**
* All Map views of {@link S3Bucket}s provide means to access the underlying S3
* object.
*
* @author Adrian Cole
*
*/
public interface S3Map<K, V> extends Map<K, V> {
/**
*
* @return s3 bucket listing that this map represents
*/
S3Bucket getBucket();
}

View File

@ -1,41 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
/**
* Map view of an {@link S3Bucket}.
*
* <p/>
* This allows you to acces the underlying {@link S3Object} so that you can
* manually set metadata such as length, content-type, or md5 hash.
*
* @author Adrian Cole
*
*/
public interface S3ObjectMap extends S3Map<String, S3Object> {
}

View File

@ -1,82 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3;
import org.jclouds.aws.s3.domain.S3Error;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
/**
* Encapsulates an S3 Error from Amazon.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTError.html" />
* @see S3Error
* @see org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent
* @author Adrian Cole
*
*/
public class S3ResponseException extends HttpResponseException {
private static final long serialVersionUID = 1L;
private S3Error error = new S3Error();
public S3ResponseException(HttpFutureCommand<?> command,
HttpResponse response, S3Error error) {
super(error.toString(), command, response);
this.setError(error);
}
public S3ResponseException(HttpFutureCommand<?> command,
HttpResponse response, S3Error error, Throwable cause) {
super(error.toString(), command, response, cause);
this.setError(error);
}
public S3ResponseException(String message, HttpFutureCommand<?> command,
HttpResponse response, S3Error error) {
super(message, command, response);
this.setError(error);
}
public S3ResponseException(String message, HttpFutureCommand<?> command,
HttpResponse response, S3Error error, Throwable cause) {
super(message, command, response, cause);
this.setError(error);
}
public void setError(S3Error error) {
this.error = error;
}
public S3Error getError() {
return error;
}
}

View File

@ -1,86 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import static org.jclouds.aws.s3.commands.options.ListBucketOptions.Builder.maxResults;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* Issues a HEAD command to determine if the bucket exists or not.
*
* @author Adrian Cole
*
*/
public class BucketExists extends S3FutureCommand<Boolean> {
@Inject
public BucketExists(@Named("jclouds.http.address") String amazonHost,
ReturnTrueIf2xx callable, @Assisted String s3Bucket) {
super("HEAD", "/" + maxResults(0).buildQueryString(), callable,
amazonHost, s3Bucket);
}
@Override
public Boolean get() throws InterruptedException, ExecutionException {
try {
return super.get();
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
@VisibleForTesting
Boolean attemptNotFound(ExecutionException e) throws ExecutionException {
if (e.getCause() != null
&& e.getCause() instanceof HttpResponseException) {
HttpResponseException responseException = (HttpResponseException) e
.getCause();
if (responseException.getResponse().getStatusCode() == 404) {
return false;
}
}
throw e;
}
@Override
public Boolean get(long l, TimeUnit timeUnit) throws InterruptedException,
ExecutionException, TimeoutException {
try {
return super.get(l, timeUnit);
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
}

View File

@ -1,76 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.xml.CopyObjectHandler;
import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* The copy operation creates a copy of an object that is already storedin
* Amazon S3.
* <p/>
* When copying an object, you can preserve all metadata (default) or
* {@link CopyObjectOptions#overrideMetadataWith(com.google.common.collect.Multimap)
* specify new metadata}. However, the ACL is not preserved and is set to
* private for the user making the request. To override the default ACL setting,
* {@link CopyObjectOptions#overrideAcl(org.jclouds.aws.s3.domain.acl.CannedAccessPolicy)
* specify a new ACL} when generating a copy request.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html" />
* @see CopyObjectOptions
* @see org.jclouds.aws.s3.domain.acl.CannedAccessPolicy
* @author Adrian Cole
*
*/
public class CopyObject extends S3FutureCommand<S3Object.Metadata> {
@Inject
public CopyObject(@Named("jclouds.http.address") String amazonHost,
ParseSax<S3Object.Metadata> callable,
@Assisted("sourceBucket") String sourceBucket,
@Assisted("sourceObject") String sourceObject,
@Assisted("destinationBucket") String destinationBucket,
@Assisted("destinationObject") String destinationObject,
@Assisted CopyObjectOptions options) {
super("PUT",
"/" + checkNotNull(destinationObject, "destinationObject"),
callable, amazonHost, destinationBucket);
CopyObjectHandler handler = (CopyObjectHandler) callable.getHandler();
handler.setKey(destinationObject);
getRequest().getHeaders().put(
"x-amz-copy-source",
String.format("/%1$s/%2$s", checkNotNull(sourceBucket,
"sourceBucket"), checkNotNull(sourceObject,
"sourceObject")));
getRequest().getHeaders().putAll(options.buildRequestHeaders());
}
}

View File

@ -1,92 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3ResponseException;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* The DELETE request operation deletes the bucket named in the URI. All objects
* in the bucket must be deleted before the bucket itself can be deleted.
* <p />
* Only the owner of a bucket can delete it, regardless of the bucket's access
* control policy.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketDELETE.html"
* />
* @author Adrian Cole
*/
public class DeleteBucket extends S3FutureCommand<Boolean> {
@Inject
public DeleteBucket(@Named("jclouds.http.address") String amazonHost,
ReturnTrueIf2xx callable, @Assisted String s3Bucket) {
super("DELETE", "/", callable, amazonHost, s3Bucket);
}
@Override
public Boolean get() throws InterruptedException, ExecutionException {
try {
return super.get();
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
@VisibleForTesting
Boolean attemptNotFound(ExecutionException e) throws ExecutionException {
if (e.getCause() != null
&& e.getCause() instanceof HttpResponseException) {
S3ResponseException responseException = (S3ResponseException) e
.getCause();
if (responseException.getResponse().getStatusCode() == 404) {
return true;
} else if ("BucketNotEmpty".equals(responseException.getError()
.getCode())) {
return false;
}
}
throw e;
}
@Override
public Boolean get(long l, TimeUnit timeUnit) throws InterruptedException,
ExecutionException, TimeoutException {
try {
return super.get(l, timeUnit);
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
}

View File

@ -1,50 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* The DELETE request operation removes the specified object from Amazon S3.
* Once deleted, there is no method to restore or undelete an object.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
* RESTObjectDELETE.html" />
* @author Adrian Cole
*/
public class DeleteObject extends S3FutureCommand<Boolean> {
@Inject
public DeleteObject(@Named("jclouds.http.address") String amazonHost,
ReturnTrueIf2xx callable, @Assisted("bucketName") String bucket,
@Assisted("key") String key) {
super("DELETE", "/" + checkNotNull(key), callable, amazonHost, bucket);
}
}

View File

@ -1,109 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3ResponseException;
import org.jclouds.aws.s3.commands.callables.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.domain.S3Object;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* Retrieves the S3Object associated with the Key or {@link S3Object#NOT_FOUND}
* if not available;
*
* <p/>
* To use GET, you must have READ access to the object. If READ access is
* granted to the anonymous user, you can request the object without an
* authorization header.
* <p />
* <p/>
* This command allows you to specify {@link GetObjectOptions} to control
* delivery of content.
*
* <h2>Note</h2> If you specify any of the below options, you will receive
* partial content:
* <ul>
* <li>{@link GetObjectOptions#range}</li>
* <li>{@link GetObjectOptions#startAt}</li>
* <li>{@link GetObjectOptions#tail}</li>
* </ul>
*
* @see GetObjectOptions
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectGET.html" />
* @author Adrian Cole
*/
public class GetObject extends S3FutureCommand<S3Object> {
@Inject
public GetObject(@Named("jclouds.http.address") String amazonHost,
ParseObjectFromHeadersAndHttpContent callable,
@Assisted("bucketName") String s3Bucket,
@Assisted("key") String key, @Assisted GetObjectOptions options) {
super("GET", "/" + checkNotNull(key), callable, amazonHost, s3Bucket);
this.getRequest().getHeaders().putAll(options.buildRequestHeaders());
callable.setKey(key);
}
@Override
public S3Object get() throws InterruptedException, ExecutionException {
try {
return super.get();
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
@VisibleForTesting
S3Object attemptNotFound(ExecutionException e) throws ExecutionException {
if (e.getCause() != null && e.getCause() instanceof S3ResponseException) {
S3ResponseException responseException = (S3ResponseException) e
.getCause();
if ("NoSuchKey".equals(responseException.getError().getCode())) {
return S3Object.NOT_FOUND;
}
}
throw e;
}
@Override
public S3Object get(long l, TimeUnit timeUnit) throws InterruptedException,
ExecutionException, TimeoutException {
try {
return super.get(l, timeUnit);
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
}

View File

@ -1,100 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.commands.callables.ParseMetadataFromHeaders;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.HttpResponseException;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* Retrieves the metadata associated with the Key or
* {@link org.jclouds.aws.s3.domain.S3Object.Metadata#NOT_FOUND} if not available.
*
* <p/>
* The HEAD operation is used to retrieve information about a specific object or
* object size, without actually fetching the object itself. This is useful if
* you're only interested in the object metadata, and don't want to waste
* bandwidth on the object data.
*
* @see GetObject
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectHEAD.html"
* />
* @author Adrian Cole
*
*/
public class HeadObject extends S3FutureCommand<S3Object.Metadata> {
@Inject
public HeadObject(@Named("jclouds.http.address") String amazonHost,
ParseMetadataFromHeaders callable,
@Assisted("bucketName") String bucket, @Assisted("key") String key) {
super("HEAD", "/" + checkNotNull(key), callable, amazonHost, bucket);
callable.setKey(key);
}
@Override
public S3Object.Metadata get() throws InterruptedException,
ExecutionException {
try {
return super.get();
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
@VisibleForTesting
S3Object.Metadata attemptNotFound(ExecutionException e)
throws ExecutionException {
if (e.getCause() != null
&& e.getCause() instanceof HttpResponseException) {
HttpResponseException responseException = (HttpResponseException) e
.getCause();
if (responseException.getResponse().getStatusCode() == 404) {
return S3Object.Metadata.NOT_FOUND;
}
}
throw e;
}
@Override
public S3Object.Metadata get(long l, TimeUnit timeUnit)
throws InterruptedException, ExecutionException, TimeoutException {
try {
return super.get(l, timeUnit);
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
}

View File

@ -1,100 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.s3.S3ResponseException;
import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* A GET request operation using a bucket URI lists information about the
* objects in the bucket.
* <p />
* To list the keys of a bucket, you must have READ access to the bucket.
* <p/>
* List output is controllable via {@link ListBucketOptions}
*
* @see ListBucketOptions
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html"
* />
* @author Adrian Cole
*
*/
public class ListBucket extends S3FutureCommand<S3Bucket> {
@Inject
public ListBucket(@Named("jclouds.http.address") String amazonHost,
ParseSax<S3Bucket> bucketParser, @Assisted String bucket,
@Assisted ListBucketOptions options) {
super("GET", "/" + options.buildQueryString(), bucketParser,
amazonHost, bucket);
ListBucketHandler handler = (ListBucketHandler) bucketParser
.getHandler();
handler.setBucketName(bucket);
}
@Override
public S3Bucket get() throws InterruptedException, ExecutionException {
try {
return super.get();
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
@VisibleForTesting
S3Bucket attemptNotFound(ExecutionException e) throws ExecutionException {
if (e.getCause() != null
&& e.getCause() instanceof HttpResponseException) {
S3ResponseException responseException = (S3ResponseException) e
.getCause();
if ("NoSuchBucket".equals(responseException.getError().getCode())) {
return S3Bucket.NOT_FOUND;
}
}
throw e;
}
@Override
public S3Bucket get(long l, TimeUnit timeUnit) throws InterruptedException,
ExecutionException, TimeoutException {
try {
return super.get(l, timeUnit);
} catch (ExecutionException e) {
return attemptNotFound(e);
}
}
}

View File

@ -1,51 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import java.util.List;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.inject.Inject;
import com.google.inject.name.Named;
/**
* Returns a list of all of the buckets owned by the authenticated sender of the
* request.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTServiceGET.html"
* />
* @author Adrian Cole
*
*/
public class ListOwnedBuckets extends S3FutureCommand<List<S3Bucket.Metadata>> {
@Inject
public ListOwnedBuckets(@Named("jclouds.http.address") String amazonHost,
ParseSax<List<S3Bucket.Metadata>> callable) {
super("GET", "/", callable, amazonHost);
}
}

View File

@ -1,65 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpHeaders;
import org.jclouds.http.commands.callables.ReturnTrueIf2xx;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* Create and name your own bucket in which to store your objects.
* <p/>
* The PUT request operation with a bucket URI creates a new bucket. Depending
* on your latency and legal requirements, you can specify a location constraint
* that will affect where your data physically resides. You can currently
* specify a Europe (EU) location constraint via {@link PutBucketOptions}.
*
* @see PutBucketOptions
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html"
* />
* @author Adrian Cole
*
*/
public class PutBucket extends S3FutureCommand<Boolean> {
@Inject
public PutBucket(@Named("jclouds.http.address") String amazonHost,
ReturnTrueIf2xx callable, @Assisted String bucketName,
@Assisted PutBucketOptions options) {
super("PUT", "/", callable, amazonHost, S3Utils
.validateBucketName(bucketName));
getRequest().getHeaders().putAll(options.buildRequestHeaders());
String payload = options.buildPayload();
if (payload != null) {
getRequest().setPayload(payload);
getRequest().getHeaders().put(HttpHeaders.CONTENT_LENGTH,
payload.getBytes().length + "");
}
}
}

View File

@ -1,98 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.commands.callables.ParseMd5FromETagHeader;
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpHeaders;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* Store data by creating or overwriting an object.
*
* <p/>
* This returns a byte[] of the md5 hash of what Amazon S3 received
* <p />
* <p/>
* This command allows you to specify {@link PutObjectOptions} to control
* delivery of content.
*
*
* @see PutObjectOptions
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html"
* />
* @author Adrian Cole
*/
public class PutObject extends S3FutureCommand<byte[]> {
@Inject
public PutObject(@Named("jclouds.http.address") String amazonHost,
ParseMd5FromETagHeader callable, @Assisted String s3Bucket,
@Assisted S3Object object, @Assisted PutObjectOptions options) {
super("PUT", "/" + checkNotNull(object.getKey()), callable, amazonHost,
s3Bucket);
checkArgument(object.getMetadata().getSize() >= 0, "size must be set");
getRequest().setPayload(
checkNotNull(object.getData(), "object.getContent()"));
getRequest().getHeaders().put(
HttpHeaders.CONTENT_TYPE,
checkNotNull(object.getMetadata().getContentType(),
"object.metadata.contentType()"));
getRequest().getHeaders().put(HttpHeaders.CONTENT_LENGTH,
object.getMetadata().getSize() + "");
if (object.getMetadata().getCacheControl() != null) {
getRequest().getHeaders().put(HttpHeaders.CACHE_CONTROL,
object.getMetadata().getCacheControl());
}
if (object.getMetadata().getContentDisposition() != null) {
getRequest().getHeaders().put(HttpHeaders.CONTENT_DISPOSITION,
object.getMetadata().getContentDisposition());
}
if (object.getMetadata().getContentEncoding() != null) {
getRequest().getHeaders().put(HttpHeaders.CONTENT_ENCODING,
object.getMetadata().getContentEncoding());
}
if (object.getMetadata().getMd5() != null)
getRequest().getHeaders().put(HttpHeaders.CONTENT_MD5,
S3Utils.toBase64String(object.getMetadata().getMd5()));
getRequest().getHeaders()
.putAll(object.getMetadata().getUserMetadata());
getRequest().getHeaders().putAll(options.buildRequestHeaders());
}
}

View File

@ -1,152 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* Assembles the command objects for S3.
*
* @author Adrian Cole
*/
public class S3CommandFactory {
@Inject
private S3ParserFactory parserFactory;
@Inject
private DeleteBucketFactory deleteBucketFactory;
public static interface DeleteBucketFactory {
DeleteBucket create(String bucket);
}
public DeleteBucket createDeleteBucket(String bucket) {
return deleteBucketFactory.create(bucket);
}
@Inject
private DeleteObjectFactory deleteObjectFactory;
public static interface DeleteObjectFactory {
DeleteObject create(@Assisted("bucketName") String bucket,
@Assisted("key") String key);
}
public DeleteObject createDeleteObject(String bucket, String key) {
return deleteObjectFactory.create(bucket, key);
}
@Inject
private BucketExistsFactory headBucketFactory;
public static interface BucketExistsFactory {
BucketExists create(String bucket);
}
public BucketExists createHeadBucket(String bucket) {
return headBucketFactory.create(bucket);
}
@Inject
private PutBucketFactory putBucketFactoryOptions;
public static interface PutBucketFactory {
PutBucket create(String bucket, PutBucketOptions options);
}
public PutBucket createPutBucket(String bucket, PutBucketOptions options) {
return putBucketFactoryOptions.create(bucket, options);
}
@Inject
private PutObjectFactory putObjectFactory;
public static interface PutObjectFactory {
PutObject create(String bucket, S3Object object,
PutObjectOptions options);
}
public PutObject createPutObject(String bucket, S3Object s3Object,
PutObjectOptions options) {
return putObjectFactory.create(bucket, s3Object, options);
}
@Inject
private GetObjectFactory getObjectFactory;
public static interface GetObjectFactory {
GetObject create(@Assisted("bucketName") String bucket,
@Assisted("key") String key, GetObjectOptions options);
}
public GetObject createGetObject(String bucket, String key,
GetObjectOptions options) {
return getObjectFactory.create(bucket, key, options);
}
@Inject
private HeadMetadataFactory headMetadataFactory;
public static interface HeadMetadataFactory {
HeadObject create(@Assisted("bucketName") String bucket,
@Assisted("key") String key);
}
public HeadObject createHeadMetadata(String bucket, String key) {
return headMetadataFactory.create(bucket, key);
}
@Inject
@Named("jclouds.http.address")
String amazonHost;
public ListOwnedBuckets createGetMetadataForOwnedBuckets() {
return new ListOwnedBuckets(amazonHost, parserFactory
.createListBucketsParser());
}
public ListBucket createListBucket(String bucket, ListBucketOptions options) {
return new ListBucket(amazonHost, parserFactory
.createListBucketParser(), bucket, options);
}
public CopyObject createCopyObject(String sourceBucket,
String sourceObject, String destinationBucket,
String destinationObject, CopyObjectOptions options) {
return new CopyObject(amazonHost, parserFactory
.createCopyObjectParser(), sourceBucket, sourceObject,
destinationBucket, destinationObject, options);
}
}

View File

@ -1,57 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.HttpFutureCommand;
/**
* Conditionally adds the amazon host header to requests.
*
* @author Adrian Cole
*
* @param <T>
*/
public class S3FutureCommand<T> extends HttpFutureCommand<T> {
public S3FutureCommand(String method, String uri,
ResponseCallable<T> responseCallable, String amazonHost,
String bucketName) {
super(method, uri, responseCallable);
addHostHeader(checkNotNull(amazonHost, "amazonHost"), checkNotNull(
bucketName, "bucketName"));
}
public S3FutureCommand(String method, String uri,
ResponseCallable<T> responseCallable, String amazonHost) {
super(method, uri, responseCallable);
addHostHeader(checkNotNull(amazonHost, "amazonHost"));
}
protected void addHostHeader(String amazonHost, String bucketName) {
addHostHeader(checkNotNull(bucketName) + "." + amazonHost);
}
}

View File

@ -1,51 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.callables;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpFutureCommand;
/**
* Parses an MD5 checksum from the header {@link S3Headers#ETAG}.
*
* @author Adrian Cole
*/
public class ParseMd5FromETagHeader extends
HttpFutureCommand.ResponseCallable<byte[]> {
public byte[] call() throws HttpException {
checkCode();
IOUtils.closeQuietly(getResponse().getContent());
String eTag = getResponse().getFirstHeaderOrNull(S3Headers.ETAG);
if (eTag != null) {
return S3Utils.fromHexString(eTag.replaceAll("\"", ""));
}
throw new HttpException("did not receive ETag");
}
}

View File

@ -1,146 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.callables;
import java.util.Map.Entry;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Object.Metadata;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpHeaders;
import com.google.inject.Inject;
/**
* This parses @{link {@link org.jclouds.aws.s3.domain.S3Object.Metadata} from HTTP headers.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTObjectGET.html" />
* @author Adrian Cole
*/
public class ParseMetadataFromHeaders extends
HttpFutureCommand.ResponseCallable<S3Object.Metadata> {
private final DateService dateParser;
private String key;
@Inject
public ParseMetadataFromHeaders(DateService dateParser) {
this.dateParser = dateParser;
}
/**
* parses the http response headers to create a new
* {@link org.jclouds.aws.s3.domain.S3Object.Metadata} object.
*/
public S3Object.Metadata call() throws HttpException {
checkCode();
S3Object.Metadata metadata = new S3Object.Metadata(key);
addAllHeadersTo(metadata);
addUserMetadataTo(metadata);
addMd5To(metadata);
parseLastModifiedOrThrowException(metadata);
setContentTypeOrThrowException(metadata);
setContentLengthOrThrowException(metadata);
metadata.setCacheControl(getResponse().getFirstHeaderOrNull(
HttpHeaders.CACHE_CONTROL));
metadata.setContentDisposition(getResponse().getFirstHeaderOrNull(
HttpHeaders.CONTENT_DISPOSITION));
metadata.setContentEncoding(getResponse().getFirstHeaderOrNull(
HttpHeaders.CONTENT_ENCODING));
return metadata;
}
private void addAllHeadersTo(Metadata metadata) {
metadata.getAllHeaders().putAll(getResponse().getHeaders());
}
private void setContentTypeOrThrowException(S3Object.Metadata metadata)
throws HttpException {
String contentType = getResponse().getFirstHeaderOrNull(
HttpHeaders.CONTENT_TYPE);
if (contentType == null)
throw new HttpException(HttpHeaders.CONTENT_TYPE
+ " not found in headers");
else
metadata.setContentType(contentType);
}
private void setContentLengthOrThrowException(S3Object.Metadata metadata)
throws HttpException {
String contentLength = getResponse().getFirstHeaderOrNull(
HttpHeaders.CONTENT_LENGTH);
if (contentLength == null)
throw new HttpException(HttpHeaders.CONTENT_LENGTH
+ " not found in headers");
else
metadata.setSize(Long.parseLong(contentLength));
}
private void parseLastModifiedOrThrowException(S3Object.Metadata metadata)
throws HttpException {
String lastModified = getResponse().getFirstHeaderOrNull(
HttpHeaders.LAST_MODIFIED);
metadata.setLastModified(dateParser
.dateTimeFromHeaderFormat(lastModified));
if (metadata.getLastModified() == null)
throw new HttpException("could not parse: "
+ HttpHeaders.LAST_MODIFIED + ": " + lastModified);
}
private void addMd5To(S3Object.Metadata metadata) {
String md5Header = getResponse()
.getFirstHeaderOrNull(S3Headers.AMZ_MD5);
if (md5Header != null) {
metadata.setMd5(S3Utils.fromHexString(md5Header));
}
String eTag = getResponse().getFirstHeaderOrNull(S3Headers.ETAG);
if (metadata.getMd5() == null && eTag != null) {
metadata.setMd5(S3Utils.fromHexString(eTag.replaceAll("\"", "")));
}
}
private void addUserMetadataTo(S3Object.Metadata metadata) {
for (Entry<String, String> header : getResponse().getHeaders()
.entries()) {
if (header.getKey() != null
&& header.getKey().startsWith(
S3Headers.USER_METADATA_PREFIX))
metadata.getUserMetadata().put(header.getKey(),
header.getValue());
}
}
public void setKey(String key) {
this.key = key;
}
}

View File

@ -1,95 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.callables;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpHeaders;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
/**
* Parses response headers and creates a new S3Object from them and the HTTP
* content.
*
* @see ParseMetadataFromHeaders
* @author Adrian Cole
*/
public class ParseObjectFromHeadersAndHttpContent extends
HttpFutureCommand.ResponseCallable<S3Object> {
private final ParseMetadataFromHeaders metadataParser;
@Inject
public ParseObjectFromHeadersAndHttpContent(
ParseMetadataFromHeaders metadataParser) {
this.metadataParser = metadataParser;
}
/**
* First, calls {@link ParseMetadataFromHeaders}.
*
* Then, sets the object size based on the Content-Length header and adds
* the content to the {@link S3Object} result.
*
* @throws org.jclouds.http.HttpException
*/
public S3Object call() throws HttpException {
checkCode();
metadataParser.setResponse(getResponse());
S3Object.Metadata metadata = metadataParser.call();
S3Object object = new S3Object(metadata, getResponse().getContent());
parseContentLengthOrThrowException(object);
return object;
}
@VisibleForTesting
void parseContentLengthOrThrowException(S3Object object)
throws HttpException {
String contentLength = getResponse().getFirstHeaderOrNull(
HttpHeaders.CONTENT_LENGTH);
String contentRange = getResponse().getFirstHeaderOrNull(
HttpHeaders.CONTENT_RANGE);
if (contentLength == null)
throw new HttpException(HttpHeaders.CONTENT_LENGTH
+ " header not present in headers: "
+ getResponse().getHeaders());
object.setContentLength(Long.parseLong(contentLength));
if (contentRange == null) {
object.getMetadata().setSize(object.getContentLength());
} else {
object.setContentRange(contentRange);
object.getMetadata().setSize(
Long.parseLong(contentRange.substring(contentRange
.lastIndexOf('/') + 1)));
}
}
public void setKey(String key) {
this.metadataParser.setKey(key);
}
}

View File

@ -1,28 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains response handlers for S3 commands.
* @author Adrian Cole
*/
package org.jclouds.aws.s3.commands.callables;

View File

@ -1,86 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.config;
import org.jclouds.aws.s3.commands.BucketExists;
import org.jclouds.aws.s3.commands.DeleteBucket;
import org.jclouds.aws.s3.commands.DeleteObject;
import org.jclouds.aws.s3.commands.GetObject;
import org.jclouds.aws.s3.commands.HeadObject;
import org.jclouds.aws.s3.commands.PutBucket;
import org.jclouds.aws.s3.commands.PutObject;
import org.jclouds.aws.s3.commands.S3CommandFactory;
import org.jclouds.aws.s3.xml.config.S3ParserModule;
import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryProvider;
/**
* Creates the factories needed to produce S3 commands
*
* @author Adrian Cole
*/
public class S3CommandsModule extends AbstractModule {
@Override
protected void configure() {
install(new S3ParserModule());
bind(S3CommandFactory.DeleteBucketFactory.class).toProvider(
FactoryProvider.newFactory(
S3CommandFactory.DeleteBucketFactory.class,
DeleteBucket.class));
bind(S3CommandFactory.DeleteObjectFactory.class).toProvider(
FactoryProvider.newFactory(
S3CommandFactory.DeleteObjectFactory.class,
DeleteObject.class));
bind(S3CommandFactory.BucketExistsFactory.class).toProvider(
FactoryProvider.newFactory(
S3CommandFactory.BucketExistsFactory.class,
BucketExists.class));
bind(S3CommandFactory.PutBucketFactory.class).toProvider(
FactoryProvider.newFactory(
S3CommandFactory.PutBucketFactory.class,
PutBucket.class));
bind(S3CommandFactory.PutObjectFactory.class).toProvider(
FactoryProvider.newFactory(
S3CommandFactory.PutObjectFactory.class,
PutObject.class));
bind(S3CommandFactory.GetObjectFactory.class).toProvider(
FactoryProvider.newFactory(
S3CommandFactory.GetObjectFactory.class,
GetObject.class));
bind(S3CommandFactory.HeadMetadataFactory.class).toProvider(
FactoryProvider.newFactory(
S3CommandFactory.HeadMetadataFactory.class,
HeadObject.class));
}
}

View File

@ -1,28 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains modules who manage the dependencies of S3 command objects.
* @author Adrian Cole
*/
package org.jclouds.aws.s3.commands.config;

View File

@ -1,327 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.options;
import com.google.common.base.Preconditions;
import static com.google.common.base.Preconditions.*;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.options.BaseHttpRequestOptions;
import org.joda.time.DateTime;
import java.io.UnsupportedEncodingException;
/**
* Contains options supported in the REST API for the COPY object operation.
* <p/>
* <h2>Usage</h2> The recommended way to instantiate a CopyObjectOptions object
* is to statically import CopyObjectOptions.Builder.* and invoke a static
* creation method followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.CopyObjectOptions.Builder.*
* <p/>
* S3Connection connection = // get connection
* <p/>
* Multimap<String,String> metadata = HashMultimap.create();
* metadata.put("x-amz-meta-adrian", "foo");
* <p/>
* // this will copy the object, provided it wasn't modified since yesterday.
* // it will not use metadata from the source, and instead use what we pass in.
* Future<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
* "destinationBucket", "destinationName",
* overrideMetadataWith(meta).
* ifSourceModifiedSince(new DateTime().minusDays(1))
* );
* <code>
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectCOPY.html?"
* />
*/
public class CopyObjectOptions extends BaseHttpRequestOptions {
private final static DateService dateService = new DateService();
public static final CopyObjectOptions NONE = new CopyObjectOptions();
private Multimap<String, String> metadata;
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
/**
* Override the default ACL (private) with the specified one.
*
* @see CannedAccessPolicy
*/
public CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this;
}
/**
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
*/
public CannedAccessPolicy getAcl() {
return acl;
}
/**
* For use in the header x-amz-copy-source-if-unmodified-since
* <p/>
* Copies the object if it hasn't been modified since the specified time;
* otherwise returns a 412 (precondition failed).
* <p/>
* This header can be used with x-amz-copy-source-if-match, but cannot be
* used with other conditional copy headers.
*
* @return valid HTTP date
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @see CopyObjectOptions#ifSourceModifiedSince(DateTime)
*/
public String getIfModifiedSince() {
return getFirstHeaderOrNull("x-amz-copy-source-if-modified-since");
}
/**
* For use in the header x-amz-copy-source-if-modified-since
* <p/>
* Copies the object if it has been modified since the specified time;
* otherwise returns a 412 (failed condition).
* <p/>
* This header can be used with x-amz-copy-source-if-none-match, but cannot
* be used with other conditional copy headers.
*
* @return valid HTTP date
* @see <a href="http://rfc.net/rfc2616.html?s3.3"/>
* @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime)
*/
public String getIfUnmodifiedSince() {
return getFirstHeaderOrNull("x-amz-copy-source-if-unmodified-since");
}
/**
* For use in the request header: x-amz-copy-source-if-match
* <p/>
* Copies the object if its entity tag (ETag) matches the specified tag;
* otherwise return a 412 (precondition failed).
* <p/>
* This header can be used with x-amz-copy-source-if-unmodified-since, but
* cannot be used with other conditional copy headers.
*
* @see CopyObjectOptions#ifSourceMd5Matches(byte[])
*/
public String getIfMatch() {
return getFirstHeaderOrNull("x-amz-copy-source-if-match");
}
/**
* For use in the request header: x-amz-copy-source-if-none-match
* <p/>
* Copies the object if its entity tag (ETag) is different than the
* specified Etag; otherwise returns a 412 (failed condition).
* <p/>
* This header can be used with x-amz-copy-source-if-modified-since, but
* cannot be used with other conditional copy headers.
*
* @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[])
*/
public String getIfNoneMatch() {
return getFirstHeaderOrNull("x-amz-copy-source-if-none-match");
}
/**
* When not null, contains the header
* [x-amz-copy-source-if-unmodified-since] -> [REPLACE] and metadata headers
* passed in from the users.
*
* @see #overrideMetadataWith(Multimap)
*/
public Multimap<String, String> getMetadata() {
return metadata;
}
/**
* Only return the object if it has changed since this time.
* <p/>
* Not compatible with {@link #ifSourceMd5Matches(byte[])} or
* {@link #ifSourceUnmodifiedSince(DateTime)}
*/
public CopyObjectOptions ifSourceModifiedSince(DateTime ifModifiedSince) {
checkState(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifModifiedSince()");
checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
replaceHeader("x-amz-copy-source-if-modified-since",
dateService.toHeaderString(checkNotNull(ifModifiedSince,
"ifModifiedSince")));
return this;
}
/**
* Only return the object if it hasn't changed since this time.
* <p/>
* Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or
* {@link #ifSourceModifiedSince(DateTime)}
*/
public CopyObjectOptions ifSourceUnmodifiedSince(DateTime ifUnmodifiedSince) {
checkState(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()");
checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
replaceHeader("x-amz-copy-source-if-unmodified-since", dateService
.toHeaderString(checkNotNull(ifUnmodifiedSince,
"ifUnmodifiedSince")));
return this;
}
/**
* The object's md5 hash should match the parameter <code>md5</code>.
* <p/>
* <p/>
* Not compatible with {@link #ifSourceMd5DoesntMatch(byte[])} or
* {@link #ifSourceModifiedSince(DateTime)}
*
* @param md5 hash representing the entity
* @throws UnsupportedEncodingException if there was a problem converting this into an S3 eTag string
*/
public CopyObjectOptions ifSourceMd5Matches(byte[] md5)
throws UnsupportedEncodingException {
checkState(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifMd5Matches()");
checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifMd5Matches()");
replaceHeader("x-amz-copy-source-if-match", String.format("\"%1$s\"",
S3Utils.toHexString(checkNotNull(md5, "md5"))));
return this;
}
/**
* The object should not have a md5 hash corresponding with the parameter
* <code>md5</code>.
* <p/>
* Not compatible with {@link #ifSourceMd5Matches(byte[])} or
* {@link #ifSourceUnmodifiedSince(DateTime)}
*
* @param md5 hash representing the entity
* @throws UnsupportedEncodingException if there was a problem converting this into an S3 eTag string
*/
public CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException {
checkState(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifMd5DoesntMatch()");
Preconditions
.checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()");
replaceHeader("x-amz-copy-source-if-none-match", String.format(
"\"%1$s\"", S3Utils.toHexString(checkNotNull(md5,
"ifMd5DoesntMatch"))));
return this;
}
@Override
public Multimap<String, String> buildRequestHeaders() {
Multimap<String, String> returnVal = HashMultimap.create();
returnVal.putAll(headers);
if (metadata != null) {
returnVal.putAll(metadata);
returnVal.put("x-amz-metadata-directive", "REPLACE");
}
return returnVal;
}
/**
* Use the provided metadata instead of what is on the source object.
*/
public CopyObjectOptions overrideMetadataWith(
Multimap<String, String> metadata) {
checkNotNull(metadata, "metadata");
for (String header : metadata.keySet()) {
checkArgument(header.startsWith("x-amz-meta-"),
"Metadata keys must start with x-amz-meta-");
}
this.metadata = metadata;
return this;
}
public static class Builder {
/**
* @see CopyObjectOptions#overrideAcl(CannedAccessPolicy)
*/
public static CopyObjectOptions overrideAcl(CannedAccessPolicy acl) {
CopyObjectOptions options = new CopyObjectOptions();
return options.overrideAcl(acl);
}
/**
* @see CopyObjectOptions#getIfModifiedSince()
*/
public static CopyObjectOptions ifSourceModifiedSince(
DateTime ifModifiedSince) {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceModifiedSince(ifModifiedSince);
}
/**
* @see CopyObjectOptions#ifSourceUnmodifiedSince(DateTime)
*/
public static CopyObjectOptions ifSourceUnmodifiedSince(
DateTime ifUnmodifiedSince) {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceUnmodifiedSince(ifUnmodifiedSince);
}
/**
* @see CopyObjectOptions#ifSourceMd5Matches(byte[])
*/
public static CopyObjectOptions ifSourceMd5Matches(byte[] md5)
throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceMd5Matches(md5);
}
/**
* @see CopyObjectOptions#ifSourceMd5DoesntMatch(byte[])
*/
public static CopyObjectOptions ifSourceMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException {
CopyObjectOptions options = new CopyObjectOptions();
return options.ifSourceMd5DoesntMatch(md5);
}
/**
* @see #overrideMetadataWith(Multimap)
*/
public static CopyObjectOptions overrideMetadataWith(
Multimap<String, String> metadata) {
CopyObjectOptions options = new CopyObjectOptions();
return options.overrideMetadataWith(metadata);
}
}
}

View File

@ -1,306 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkArgument;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpHeaders;
import org.jclouds.http.options.BaseHttpRequestOptions;
import org.joda.time.DateTime;
import com.google.common.base.Joiner;
import com.google.common.collect.Multimap;
/**
* Contains options supported in the REST API for the GET object operation. <h2>
* Usage</h2> The recommended way to instantiate a GetObjectOptions object is to
* statically import GetObjectOptions.Builder.* and invoke a static creation
* method followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.GetObjectOptions.Builder.*
*
* S3Connection connection = // get connection
*
* // this will get the first megabyte of an object, provided it wasn't modified since yesterday
* Future<S3Object> object = connection.getObject("bucket","objectName",range(0,1024).ifUnmodifiedSince(new DateTime().minusDays(1)));
* <code>
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectGET.html?"
* />
* @author Adrian Cole
*
*
*/
public class GetObjectOptions extends BaseHttpRequestOptions {
private final static DateService dateService = new DateService();
public static final GetObjectOptions NONE = new GetObjectOptions();
private final List<String> ranges = new ArrayList<String>();
@Override
public Multimap<String, String> buildRequestHeaders() {
Multimap<String, String> headers = super.buildRequestHeaders();
String range = getRange();
if (range != null)
headers.put(HttpHeaders.RANGE, this.getRange());
return headers;
}
/**
* download the specified range of the object.
*/
public GetObjectOptions range(long start, long end) {
checkArgument(start >= 0, "start must be >= 0");
checkArgument(end >= 0, "end must be >= 0");
ranges.add(String.format("%d-%d", start, end));
return this;
}
/**
* download the object offset at <code>start</code>
*/
public GetObjectOptions startAt(long start) {
checkArgument(start >= 0, "start must be >= 0");
ranges.add(String.format("%d-", start));
return this;
}
/**
* download the last <code>count</code> bytes of the object
*/
public GetObjectOptions tail(long count) {
checkArgument(count > 0, "count must be > 0");
ranges.add(String.format("-%d", count));
return this;
}
/**
* For use in the header Range
* <p />
*
* @see GetObjectOptions#range(long, long)
*/
public String getRange() {
return (ranges.size() > 0) ? String.format("bytes=%s", Joiner.on(",")
.join(ranges)) : null;
}
/**
* Only return the object if it has changed since this time.
* <p />
* Not compatible with {@link #ifMd5Matches(byte[])} or
* {@link #ifUnmodifiedSince(DateTime)}
*/
public GetObjectOptions ifModifiedSince(DateTime ifModifiedSince) {
checkArgument(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifModifiedSince()");
checkArgument(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifModifiedSince()");
this.headers.put(HttpHeaders.IF_MODIFIED_SINCE,
dateService.toHeaderString(checkNotNull(ifModifiedSince,
"ifModifiedSince")));
return this;
}
/**
* For use in the header If-Modified-Since
* <p />
* Return the object only if it has been modified since the specified time,
* otherwise return a 304 (not modified).
*
* @see GetObjectOptions#ifModifiedSince(DateTime)
*/
public String getIfModifiedSince() {
return this.getFirstHeaderOrNull(HttpHeaders.IF_MODIFIED_SINCE);
}
/**
* Only return the object if it hasn't changed since this time.
* <p />
* Not compatible with {@link #ifMd5DoesntMatch(byte[])} or
* {@link #ifModifiedSince(DateTime)}
*/
public GetObjectOptions ifUnmodifiedSince(DateTime ifUnmodifiedSince) {
checkArgument(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifUnmodifiedSince()");
checkArgument(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifUnmodifiedSince()");
this.headers.put(HttpHeaders.IF_UNMODIFIED_SINCE, dateService
.toHeaderString(checkNotNull(ifUnmodifiedSince,
"ifUnmodifiedSince")));
return this;
}
/**
* For use in the header If-Unmodified-Since
* <p />
* Return the object only if it has not been modified since the specified
* time, otherwise return a 412 (precondition failed).
*
* @see GetObjectOptions#ifUnmodifiedSince(DateTime)
*/
public String getIfUnmodifiedSince() {
return this.getFirstHeaderOrNull(HttpHeaders.IF_UNMODIFIED_SINCE);
}
/**
* The object's md5 hash should match the parameter <code>md5</code>.
*
* <p />
* Not compatible with {@link #ifMd5DoesntMatch(byte[])} or
* {@link #ifModifiedSince(DateTime)}
*
* @param md5
* hash representing the entity
* @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string
*/
public GetObjectOptions ifMd5Matches(byte[] md5)
throws UnsupportedEncodingException {
checkArgument(getIfNoneMatch() == null,
"ifMd5DoesntMatch() is not compatible with ifMd5Matches()");
checkArgument(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifMd5Matches()");
this.headers.put(HttpHeaders.IF_MATCH, String.format("\"%1$s\"",
S3Utils.toHexString(checkNotNull(md5, "md5"))));
return this;
}
/**
* For use in the request header: If-Match
* <p />
* Return the object only if its entity tag (ETag) is the same as the md5
* specified, otherwise return a 412 (precondition failed).
*
* @see GetObjectOptions#ifMd5Matches(byte[])
*/
public String getIfMatch() {
return this.getFirstHeaderOrNull(HttpHeaders.IF_MATCH);
}
/**
* The object should not have a md5 hash corresponding with the parameter
* <code>md5</code>.
* <p />
* Not compatible with {@link #ifMd5Matches(byte[])} or
* {@link #ifUnmodifiedSince(DateTime)}
*
* @param md5
* hash representing the entity
* @throws UnsupportedEncodingException
* if there was a problem converting this into an S3 eTag string
*/
public GetObjectOptions ifMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException {
checkArgument(getIfMatch() == null,
"ifMd5Matches() is not compatible with ifMd5DoesntMatch()");
checkArgument(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifMd5DoesntMatch()");
this.headers.put(HttpHeaders.IF_NONE_MATCH, String.format("\"%1$s\"",
S3Utils.toHexString(checkNotNull(md5, "ifMd5DoesntMatch"))));
return this;
}
/**
* For use in the request header: If-None-Match
* <p />
* Return the object only if its entity tag (ETag) is different from the one
* specified, otherwise return a 304 (not modified).
*
* @see GetObjectOptions#ifMd5DoesntMatch(byte[])
*/
public String getIfNoneMatch() {
return this
.getFirstHeaderOrNull(org.jclouds.http.HttpHeaders.IF_NONE_MATCH);
}
public static class Builder {
/**
* @see GetObjectOptions#range(long, long)
*/
public static GetObjectOptions range(long start, long end) {
GetObjectOptions options = new GetObjectOptions();
return options.range(start, end);
}
/**
* @see GetObjectOptions#startAt(long)
*/
public static GetObjectOptions startAt(long start) {
GetObjectOptions options = new GetObjectOptions();
return options.startAt(start);
}
/**
* @see GetObjectOptions#tail(long)
*/
public static GetObjectOptions tail(long count) {
GetObjectOptions options = new GetObjectOptions();
return options.tail(count);
}
/**
* @see GetObjectOptions#getIfModifiedSince()
*/
public static GetObjectOptions ifModifiedSince(DateTime ifModifiedSince) {
GetObjectOptions options = new GetObjectOptions();
return options.ifModifiedSince(ifModifiedSince);
}
/**
* @see GetObjectOptions#ifUnmodifiedSince(DateTime)
*/
public static GetObjectOptions ifUnmodifiedSince(
DateTime ifUnmodifiedSince) {
GetObjectOptions options = new GetObjectOptions();
return options.ifUnmodifiedSince(ifUnmodifiedSince);
}
/**
* @see GetObjectOptions#ifMd5Matches(byte[])
*/
public static GetObjectOptions ifMd5Matches(byte[] md5)
throws UnsupportedEncodingException {
GetObjectOptions options = new GetObjectOptions();
return options.ifMd5Matches(md5);
}
/**
* @see GetObjectOptions#ifMd5DoesntMatch(byte[])
*/
public static GetObjectOptions ifMd5DoesntMatch(byte[] md5)
throws UnsupportedEncodingException {
GetObjectOptions options = new GetObjectOptions();
return options.ifMd5DoesntMatch(md5);
}
}
}

View File

@ -1,176 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import org.jclouds.http.options.BaseHttpRequestOptions;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* Contains options supported in the REST API for the GET bucket operation. <h2>
* Usage</h2> The recommended way to instantiate a GetBucketOptions object is to
* statically import GetBucketOptions.Builder.* and invoke a static creation
* method followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
* <p/>
* S3Connection connection = // get connection
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* <code>
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketGET.html?"
* />
*/
public class ListBucketOptions extends BaseHttpRequestOptions {
public static final ListBucketOptions NONE = new ListBucketOptions();
/**
* Limits the response to keys which begin with the indicated prefix. You
* can use prefixes to separate a bucket into different sets of keys in a
* way similar to how a file system uses folders.
*
* @throws UnsupportedEncodingException
*/
public ListBucketOptions withPrefix(String prefix)
throws UnsupportedEncodingException {
options.put("prefix", URLEncoder.encode(checkNotNull(prefix, "prefix"),
"UTF-8"));
return this;
}
/**
* @see ListBucketOptions#withPrefix(String)
*/
public String getPrefix() {
return options.get("prefix");
}
/**
* Indicates where in the bucket to begin listing. The list will only
* include keys that occur lexicographically after marker. This is
* convenient for pagination: To get the next page of results use the last
* key of the current page as the marker.
*
* @throws UnsupportedEncodingException
*/
public ListBucketOptions afterMarker(String marker)
throws UnsupportedEncodingException {
options.put("marker", URLEncoder.encode(checkNotNull(marker, "marker"),
"UTF-8"));
return this;
}
/**
* @see ListBucketOptions#afterMarker(String)
*/
public String getMarker() {
return options.get("marker");
}
/**
* The maximum number of keys you'd like to see in the response body. The
* server might return fewer than this many keys, but will not return more.
*/
public ListBucketOptions maxResults(long maxKeys) {
checkState(maxKeys >= 0, "maxKeys must be >= 0");
options.put("max-keys", Long.toString(maxKeys));
return this;
}
/**
* @see ListBucketOptions#maxResults(long)
*/
public String getMaxKeys() {
return options.get("max-keys");
}
/**
* Causes keys that contain the same string between the prefix and the first
* occurrence of the delimiter to be rolled up into a single result element
* in the CommonPrefixes collection. These rolled-up keys are not returned
* elsewhere in the response.
*
* @throws UnsupportedEncodingException
*/
public ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException {
options.put("delimiter", URLEncoder.encode(checkNotNull(delimiter,
"delimiter"), "UTF-8"));
return this;
}
/**
* @see ListBucketOptions#delimiter(String)
*/
public String getDelimiter() {
return options.get("delimiter");
}
public static class Builder {
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#withPrefix(String)
*/
public static ListBucketOptions withPrefix(String prefix)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.withPrefix(prefix);
}
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#afterMarker(String)
*/
public static ListBucketOptions afterMarker(String marker)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.afterMarker(marker);
}
/**
* @see ListBucketOptions#maxResults(long)
*/
public static ListBucketOptions maxResults(long maxKeys) {
ListBucketOptions options = new ListBucketOptions();
return options.maxResults(maxKeys);
}
/**
* @throws UnsupportedEncodingException
* @see ListBucketOptions#delimiter(String)
*/
public static ListBucketOptions delimiter(String delimiter)
throws UnsupportedEncodingException {
ListBucketOptions options = new ListBucketOptions();
return options.delimiter(delimiter);
}
}
}

View File

@ -1,113 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.options;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Contains options supported in the REST API for the PUT bucket operation. <h2>
* Usage</h2> The recommended way to instantiate a PutBucketOptions object is to
* statically import PutBucketOptions.Builder.* and invoke a static creation
* method followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.PutBucketOptions.Builder.*
* import static org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint.*;
* import org.jclouds.aws.s3.S3Connection;
* <p/>
* S3Connection connection = // get connection
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* <code>
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTBucketPUT.html?"
* />
*/
public class PutBucketOptions extends BaseHttpRequestOptions {
public static final PutBucketOptions NONE = new PutBucketOptions();
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
private LocationConstraint constraint;
/**
* Depending on your latency and legal requirements, you can specify a
* location constraint that will affect where your data physically resides.
* You can currently specify a Europe (EU) location constraint.
*/
public PutBucketOptions createIn(LocationConstraint constraint) {
this.constraint = checkNotNull(constraint, "constraint");
this.payload = String
.format(
"<CreateBucketConfiguration><LocationConstraint>%1$s</LocationConstraint></CreateBucketConfiguration>",
constraint.toString());
return this;
}
/**
* Override the default ACL (private) with the specified one.
*
* @see CannedAccessPolicy
*/
public PutBucketOptions withBucketAcl(CannedAccessPolicy acl) {
this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this;
}
/**
* @see PutBucketOptions#withBucketAcl(CannedAccessPolicy)
*/
public CannedAccessPolicy getAcl() {
return acl;
}
/**
* @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
*/
public LocationConstraint getLocationConstraint() {
return constraint;
}
public static class Builder {
/**
* @see PutBucketOptions#createIn(org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint)
*/
public static PutBucketOptions createIn(LocationConstraint constraint) {
PutBucketOptions options = new PutBucketOptions();
return options.createIn(constraint);
}
/**
* @see PutBucketOptions#withBucketAcl(CannedAccessPolicy)
*/
public static PutBucketOptions withBucketAcl(CannedAccessPolicy acl) {
PutBucketOptions options = new PutBucketOptions();
return options.withBucketAcl(acl);
}
}
}

View File

@ -1,88 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.commands.options;
import org.jclouds.aws.s3.domain.acl.CannedAccessPolicy;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.http.options.BaseHttpRequestOptions;
import static com.google.common.base.Preconditions.*;
/**
* Contains options supported in the REST API for the PUT object operation.
* <p/>
* <h2>
* Usage</h2> The recommended way to instantiate a PutObjectOptions object is to
* statically import PutObjectOptions.Builder.* and invoke a static creation
* method followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.aws.s3.commands.options.PutObjectOptions.Builder.*
* import org.jclouds.aws.s3.S3Connection;
*
* S3Connection connection = // get connection
* Future<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
* <code>
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html?"
* />
*
* @author Adrian Cole
*
*/
public class PutObjectOptions extends BaseHttpRequestOptions {
public static final PutObjectOptions NONE = new PutObjectOptions();
private CannedAccessPolicy acl = CannedAccessPolicy.PRIVATE;
/**
* Override the default ACL (private) with the specified one.
*
* @see CannedAccessPolicy
*/
public PutObjectOptions withAcl(CannedAccessPolicy acl) {
this.acl = checkNotNull(acl, "acl");
if (!acl.equals(CannedAccessPolicy.PRIVATE))
this.replaceHeader(S3Headers.CANNED_ACL, acl.toString());
return this;
}
/**
* @see PutObjectOptions#withAcl(CannedAccessPolicy)
*/
public CannedAccessPolicy getAcl() {
return acl;
}
public static class Builder {
/**
* @see PutObjectOptions#withAcl(CannedAccessPolicy)
*/
public static PutObjectOptions withAcl(CannedAccessPolicy acl) {
PutObjectOptions options = new PutObjectOptions();
return options.withAcl(acl);
}
}
}

View File

@ -1,30 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains request options for S3 REST commands.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAPI.html" />
* @author Adrian Cole
*/
package org.jclouds.aws.s3.commands.options;

View File

@ -1,29 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains all currently supported commands in the Amazon S3 REST Api.
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAPI.html" />
* @author Adrian Cole
*/
package org.jclouds.aws.s3.commands;

View File

@ -1,96 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.config;
import com.google.inject.*;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.name.Named;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.handlers.ParseS3ErrorFromXmlContent;
import org.jclouds.aws.s3.internal.GuiceS3Context;
import org.jclouds.aws.s3.internal.LiveS3Connection;
import org.jclouds.aws.s3.internal.LiveS3InputStreamMap;
import org.jclouds.aws.s3.internal.LiveS3ObjectMap;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponseHandler;
import org.jclouds.http.annotation.ClientErrorHandler;
import org.jclouds.http.annotation.RedirectHandler;
import org.jclouds.http.annotation.ServerErrorHandler;
import org.jclouds.http.handlers.CloseContentAndSetExceptionHandler;
import org.jclouds.logging.Logger;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* Configures the S3 connection, including logging and http transport.
*
* @author Adrian Cole
*/
@S3ConnectionModule
public class LiveS3ConnectionModule extends AbstractModule {
@Resource
protected Logger logger = Logger.NULL;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_ADDRESS)
String address;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_PORT)
int port;
@Inject
@Named(HttpConstants.PROPERTY_HTTP_SECURE)
boolean isSecure;
@Override
protected void configure() {
bind(S3Connection.class).to(LiveS3Connection.class)
.in(Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class)
.to(CloseContentAndSetExceptionHandler.class).in(
Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(ClientErrorHandler.class)
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
bind(HttpResponseHandler.class).annotatedWith(ServerErrorHandler.class)
.to(ParseS3ErrorFromXmlContent.class).in(Scopes.SINGLETON);
requestInjection(this);
logger.info("S3 Context = %1$s://%2$s:%3$s", (isSecure ? "https"
: "http"), address, port);
}
@Provides
@Singleton
List<HttpRequestFilter> provideRequestFilters(
RequestAuthorizeSignature requestAuthorizeSignature) {
List<HttpRequestFilter> filters = new ArrayList<HttpRequestFilter>();
filters.add(requestAuthorizeSignature);
return filters;
}
}

View File

@ -1,21 +0,0 @@
package org.jclouds.aws.s3.config;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.jclouds.http.HttpFutureCommandClient;
/**
* designates the the module configures a {@link org.jclouds.aws.s3.S3Connection}
*
* @author Adrian Cole
*
*/
@Retention(RUNTIME)
@Target(TYPE)
public @interface S3ConnectionModule {
}

View File

@ -1,59 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.config;
import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryProvider;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.commands.config.S3CommandsModule;
import org.jclouds.aws.s3.internal.GuiceS3Context;
import org.jclouds.aws.s3.internal.LiveS3InputStreamMap;
import org.jclouds.aws.s3.internal.LiveS3ObjectMap;
/**
* Configures the {@link S3Context}; requires {@link S3Connection} bound.
*
* @author Adrian Cole
*/
public class S3ContextModule extends AbstractModule {
@Override
protected void configure() {
this.requireBinding(S3Connection.class);
install(new S3CommandsModule());
bind(GuiceS3Context.S3ObjectMapFactory.class).toProvider(
FactoryProvider.newFactory(
GuiceS3Context.S3ObjectMapFactory.class,
LiveS3ObjectMap.class));
bind(GuiceS3Context.S3InputStreamMapFactory.class).toProvider(
FactoryProvider.newFactory(
GuiceS3Context.S3InputStreamMapFactory.class,
LiveS3InputStreamMap.class));
bind(S3Context.class).to(GuiceS3Context.class);
}
}

View File

@ -1,28 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains modules who manage the dependencies of the S3Context, S3Connection, and S3 Map views.
* @author Adrian Cole
*/
package org.jclouds.aws.s3.config;

View File

@ -1,100 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.domain;
/**
* Every bucket and object in Amazon S3 has an owner, the user that created the
* bucket or object. The owner of a bucket or object cannot be changed. However,
* if the object is overwritten by another user (deleted and rewritten), the new
* object will have a new owner.
* <p/>
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
* RESTAccessPolicy.html" />
* @author Adrian Cole
*/
public class CanonicalUser {
private final String id;
private String displayName;
public CanonicalUser(String id) {
this.id = id;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("S3Owner");
sb.append("{id='").append(id).append('\'');
sb.append(", displayName='").append(displayName).append('\'');
sb.append('}');
return sb.toString();
}
/**
* To locate the CanonicalUser ID for a user, the user must perform the
* {@link org.jclouds.aws.s3.S3Connection#listBucket(String)} and retrieve
* {@link S3Bucket.Metadata#getOwner()}
*/
public String getId() {
return id;
}
/**
* read-only as is maintained by Amazon.
*/
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof CanonicalUser))
return false;
CanonicalUser s3Owner = (CanonicalUser) o;
if (displayName != null ? !displayName.equals(s3Owner.displayName)
: s3Owner.displayName != null)
return false;
if (!id.equals(s3Owner.id))
return false;
return true;
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result
+ (displayName != null ? displayName.hashCode() : 0);
return result;
}
}

View File

@ -1,336 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import org.joda.time.DateTime;
import java.util.HashSet;
import java.util.Set;
/**
* A container that provides namespace, access control and aggregation of
* {@link S3Object}s
* <p/>
* <p/>
* Every object stored in Amazon S3 is contained in a bucket. Buckets partition
* the namespace of objects stored in Amazon S3 at the top level. Within a
* bucket, you can use any names for your objects, but bucket names must be
* unique across all of Amazon S3.
* <p/>
* Buckets are similar to Internet domain names. Just as Amazon is the only
* owner of the domain name Amazon.com, only one person or organization can own
* a bucket within Amazon S3. Once you create a uniquely named bucket in Amazon
* S3, you can organize and name the objects within the bucket in any way you
* like and the bucket will remain yours for as long as you like and as long as
* you have the Amazon S3 account.
* <p/>
* The similarities between buckets and domain names is not a coincidenceÑthere
* is a direct mapping between Amazon S3 buckets and subdomains of
* s3.amazonaws.com. Objects stored in Amazon S3 are addressable using the REST
* API under the domain bucketname.s3.amazonaws.com. For example, if the object
* homepage.html?is stored in the Amazon S3 bucket mybucket its address would be
* http://mybucket.s3.amazonaws.com/homepage.html?
*
* @author Adrian Cole
* @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html"
* />
*/
public class S3Bucket {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("S3Bucket");
sb.append("{metadata=").append(metadata);
sb.append(", isTruncated=").append(isTruncated);
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof S3Bucket))
return false;
S3Bucket s3Bucket = (S3Bucket) o;
if (isTruncated != s3Bucket.isTruncated)
return false;
if (!metadata.equals(s3Bucket.metadata))
return false;
if (objects != null ? !objects.equals(s3Bucket.objects)
: s3Bucket.objects != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = objects != null ? objects.hashCode() : 0;
result = 31 * result + metadata.hashCode();
result = 31 * result + (isTruncated ? 1 : 0);
return result;
}
/**
* System metadata of the S3Bucket
*
* @author Adrian Cole
*/
public static class Metadata {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Metadata");
sb.append("{name='").append(name).append('\'');
sb.append(", creationDate=").append(creationDate);
sb.append(", canonicalUser=").append(canonicalUser);
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Metadata))
return false;
Metadata metadata = (Metadata) o;
if (canonicalUser != null ? !canonicalUser
.equals(metadata.canonicalUser)
: metadata.canonicalUser != null)
return false;
if (!name.equals(metadata.name))
return false;
return true;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result
+ (canonicalUser != null ? canonicalUser.hashCode() : 0);
return result;
}
/**
* Location constraint of the bucket.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/latest/RESTBucketLocationGET.html"
* />
*/
public static enum LocationConstraint {
EU
}
private final String name;
private DateTime creationDate;
private CanonicalUser canonicalUser;
/**
* @see #getName()
*/
public Metadata(String name) {
this.name = checkNotNull(name, "name");
}
/**
* To comply with Amazon S3 requirements, bucket names must:
* <p/>
* Contain lowercase letters, numbers, periods (.), underscores (_), and
* dashes (-)
* <p/>
* Start with a number or letter
* <p/>
* Be between 3 and 255 characters long
* <p/>
* Not be in an IP address style (e.g., "192.168.5.4")
*/
public String getName() {
return name;
}
public DateTime getCreationDate() {
return creationDate;
}
public void setCreationDate(DateTime creationDate) {
this.creationDate = creationDate;
}
/**
* Every bucket and object in Amazon S3 has an owner, the user that
* created the bucket or object. The owner of a bucket or object cannot
* be changed. However, if the object is overwritten by another user
* (deleted and rewritten), the new object will have a new owner.
*/
public CanonicalUser getOwner() {
return canonicalUser;
}
public void setOwner(CanonicalUser canonicalUser) {
this.canonicalUser = canonicalUser;
}
}
public static final S3Bucket NOT_FOUND = new S3Bucket("NOT_FOUND");
private Set<S3Object.Metadata> objects = new HashSet<S3Object.Metadata>();
private Set<String> commonPrefixes = new HashSet<String>();
private String prefix;
private String marker;
private String delimiter;
private long maxKeys;
private final Metadata metadata;
private boolean isTruncated;
public S3Bucket(String name) {
this.metadata = new Metadata(name);
}
public String getName() {
return this.metadata.getName();
}
public S3Bucket(Metadata metadata) {
this.metadata = checkNotNull(metadata, "metadata");
}
/**
* @see org.jclouds.aws.s3.S3Connection#listBucket(String)
*/
public Set<S3Object.Metadata> getContents() {
return objects;
}
public void setContents(Set<S3Object.Metadata> objects) {
this.objects = objects;
}
/**
* @return true, if the list contains all objects.
*/
public boolean isTruncated() {
return isTruncated;
}
public void setTruncated(boolean truncated) {
isTruncated = truncated;
}
public Metadata getMetadata() {
return metadata;
}
public void setCommonPrefixes(Set<String> commonPrefixes) {
this.commonPrefixes = commonPrefixes;
}
/**
* Example:
* <p/>
* if the following keys are in the bucket
* <p/>
* a/1/a<br/>
* a/1/b<br/>
* a/2/a<br/>
* a/2/b<br/>
* <p/>
* and prefix is set to <code>a/</code> and delimiter is set to
* <code>/</code> then commonprefixes would return 1,2
*
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getPrefix()
*/
public Set<String> getCommonPrefixes() {
return commonPrefixes;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* return keys that start with this.
*
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getPrefix()
*/
public String getPrefix() {
return prefix;
}
public void setMaxKeys(long maxKeys) {
this.maxKeys = maxKeys;
}
/**
* @return maximum results of the bucket.
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMaxKeys()
*/
public long getMaxKeys() {
return maxKeys;
}
public void setMarker(String marker) {
this.marker = marker;
}
/**
* when set, bucket contains results whose keys are lexigraphically after
* marker.
*
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMarker()
*/
public String getMarker() {
return marker;
}
public void setDelimiter(String delimiter) {
this.delimiter = delimiter;
}
/**
* when set, bucket results will not contain keys that have text following
* this delimiter.
* <p/>
* note that delimiter has no effect on prefix. prefix can contain the
* delimiter many times, or not at all. delimiter only restricts after the
* prefix.
*
* @see org.jclouds.aws.s3.commands.options.ListBucketOptions#getMarker()
*/
public String getDelimiter() {
return delimiter;
}
}

View File

@ -1,131 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.domain;
import java.util.HashMap;
import java.util.Map;
/**
* When an Amazon S3 request is in error, the client receives an error response.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?ErrorResponse.html" />
* @author Adrian Cole
*
*/
public class S3Error {
private String code;
private String message;
private String requestId;
private String requestToken;
private Map<String, String> details = new HashMap<String, String>();
private String stringSigned;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("S3Error");
sb.append("{code='").append(code).append('\'');
sb.append(", message='").append(message).append('\'');
sb.append(", requestId='").append(requestId).append('\'');
sb.append(", requestToken='").append(requestToken).append('\'');
if (stringSigned != null)
sb.append(", stringSigned='").append(stringSigned).append('\'');
sb.append(", context='").append(details.toString()).append('\'')
.append('}');
return sb.toString();
}
public void setCode(String code) {
this.code = code;
}
/**
* The error code is a string that uniquely identifies an error condition.
* It is meant to be read and understood by programs that detect and handle
* errors by type
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorCode.html" />
*/
public String getCode() {
return code;
}
public void setMessage(String message) {
this.message = message;
}
/**
* The error message contains a generic description of the error condition
* in English.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/ErrorMessage.html" />
*/
public String getMessage() {
return message;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
/**
* * A unique ID assigned to each request by the system. In the unlikely
* event that you have problems with Amazon S3, Amazon can use this to help
* troubleshoot the problem.
*
*/
public String getRequestId() {
return requestId;
}
public void setStringSigned(String stringSigned) {
this.stringSigned = stringSigned;
}
/**
* @return what jclouds signed before sending the request.
*/
public String getStringSigned() {
return stringSigned;
}
public void setDetails(Map<String, String> context) {
this.details = context;
}
/**
* @return additional details surrounding the error.
*/
public Map<String, String> getDetails() {
return details;
}
public void setRequestToken(String requestToken) {
this.requestToken = requestToken;
}
public String getRequestToken() {
return requestToken;
}
}

View File

@ -1,458 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.domain;
import static com.google.common.base.Preconditions.*;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.util.S3Utils.Md5InputStreamResult;
import org.jclouds.http.ContentTypes;
import org.joda.time.DateTime;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
/**
* Amazon S3 is designed to store objects. Objects are stored in
* {@link S3Bucket buckets} and consist of a {@link org.jclouds.aws.s3.domain.S3Object#getData() value},
* a {@link S3Object#getKey key}, {@link S3Object.Metadata#getUserMetadata()
* metadata}, and an access control policy.
*
* @author Adrian Cole
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingObjects.html"
* />
*/
public class S3Object {
public static final S3Object NOT_FOUND = new S3Object(Metadata.NOT_FOUND);
private Object data;
private Metadata metadata;
private long contentLength = -1;
private String contentRange;
public S3Object(String key) {
this(new Metadata(key));
}
public S3Object(Metadata metadata) {
this.metadata = metadata;
}
public S3Object(Metadata metadata, Object data) {
this(metadata);
setData(data);
}
public S3Object(String key, Object data) {
this(key);
setData(data);
}
/**
* System and user Metadata for the {@link S3Object}.
*
* @author Adrian Cole
* @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingMetadata.html"
* />
*/
public static class Metadata implements Comparable<Metadata> {
public static final Metadata NOT_FOUND = new Metadata("NOT_FOUND");
// parsed during list, head, or get
private final String key;
private byte[] md5;
private volatile long size = -1;
// only parsed during head or get
private Multimap<String, String> allHeaders = HashMultimap.create();
private Multimap<String, String> userMetadata = HashMultimap.create();
private DateTime lastModified;
private String dataType = ContentTypes.BINARY;
private String cacheControl;
private String dataDisposition;
private String dataEncoding;
// only parsed on list
private CanonicalUser owner = null;
private String storageClass = null;
/**
* @param key
* @see #getKey()
*/
public Metadata(String key) {
checkNotNull(key, "key");
checkArgument(!key.startsWith("/"), "keys cannot start with /");
this.key = key;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Metadata");
sb.append("{key='").append(key).append('\'');
sb.append(", lastModified=").append(lastModified);
sb.append(", md5=").append(
getMd5() == null ? "null" : Arrays.asList(getMd5())
.toString());
sb.append(", size=").append(size);
sb.append(", dataType='").append(dataType).append('\'');
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Metadata))
return false;
Metadata metadata = (Metadata) o;
if (size != metadata.size)
return false;
if (dataType != null ? !dataType.equals(metadata.dataType)
: metadata.dataType != null)
return false;
if (!key.equals(metadata.key))
return false;
if (lastModified != null ? !lastModified
.equals(metadata.lastModified)
: metadata.lastModified != null)
return false;
if (!Arrays.equals(getMd5(), metadata.getMd5()))
return false;
return true;
}
@Override
public int hashCode() {
int result = key.hashCode();
result = 31 * result
+ (lastModified != null ? lastModified.hashCode() : 0);
result = 31 * result
+ (getMd5() != null ? Arrays.hashCode(getMd5()) : 0);
result = 31 * result + (int) (size ^ (size >>> 32));
result = 31 * result + (dataType != null ? dataType.hashCode() : 0);
return result;
}
/**
* The key is the handle that you assign to an object that allows you
* retrieve it later. A key is a sequence of Unicode characters whose
* UTF-8 encoding is at most 1024 bytes long. Each object in a bucket
* must have a unique key.
*
* @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingKeys.html"
* />
*/
public String getKey() {
return key;
}
public DateTime getLastModified() {
return lastModified;
}
public void setLastModified(DateTime lastModified) {
this.lastModified = lastModified;
}
/**
* The size of the object, in bytes.
*
* @see <a href=
* "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.13."
* />
*/
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
/**
* A standard MIME type describing the format of the contents. If none
* is provided, the default is binary/octet-stream.
* @see <a href=
* "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.17."
* />
*/
public String getContentType() {
return dataType;
}
public void setContentType(String dataType) {
this.dataType = dataType;
}
public void setMd5(byte[] md5) {
this.md5 = Arrays.copyOf(md5, md5.length);
}
/**
* @return the md5 value stored in the Etag header returned by S3.
*/
public byte[] getMd5() {
return (md5 == null) ? null : Arrays.copyOf(md5, md5.length);
}
public void setUserMetadata(Multimap<String, String> userMetadata) {
this.userMetadata = userMetadata;
}
/**
* Any header starting with <code>x-amz-meta-</code> is considered user
* metadata. It will be stored with the object and returned when you
* retrieve the object. The total size of the HTTP request, not
* including the body, must be less than 8 KB.
*/
public Multimap<String, String> getUserMetadata() {
return userMetadata;
}
public void setOwner(CanonicalUser owner) {
this.owner = owner;
}
/**
* Every bucket and object in Amazon S3 has an owner, the user that
* created the bucket or object. The owner of a bucket or object cannot
* be changed. However, if the object is overwritten by another user
* (deleted and rewritten), the new object will have a new owner.
*/
public CanonicalUser getOwner() {
return owner;
}
public void setStorageClass(String storageClass) {
this.storageClass = storageClass;
}
/**
* Currently defaults to 'STANDARD' and not used.
*/
public String getStorageClass() {
return storageClass;
}
public void setCacheControl(String cacheControl) {
this.cacheControl = cacheControl;
}
/**
* Can be used to specify caching behavior along the request/reply
* chain.
*
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.9.
*/
public String getCacheControl() {
return cacheControl;
}
public void setContentDisposition(String dataDisposition) {
this.dataDisposition = dataDisposition;
}
/**
* Specifies presentational information for the object.
*
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html?sec19.5.1."/>
*/
public String getContentDisposition() {
return dataDisposition;
}
public void setContentEncoding(String dataEncoding) {
this.dataEncoding = dataEncoding;
}
/**
* Specifies what content encodings have been applied to the object and
* thus what decoding mechanisms must be applied in order to obtain the
* media-type referenced by the Content-Type header field.
*
* @see <a href=
* "http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html?sec14.11"
* />
*/
public String getContentEncoding() {
return dataEncoding;
}
public void setAllHeaders(Multimap<String, String> allHeaders) {
this.allHeaders = allHeaders;
}
/**
* @return all http response headers associated with this S3Object
*/
public Multimap<String, String> getAllHeaders() {
return allHeaders;
}
public int compareTo(Metadata o) {
return (this == o) ? 0 : getKey().compareTo(o.getKey());
}
}
/**
* @see Metadata#getKey()
*/
public String getKey() {
return metadata.getKey();
}
/**
* Sets payload for the request or the content from the response. If size
* isn't set, this will attempt to discover it.
*
* @param data typically InputStream for downloads, or File, byte [], String,
* or InputStream for uploads.
*/
public void setData(Object data) {
this.data = checkNotNull(data, "data");
if (getMetadata().getSize() == -1)
this.getMetadata().setSize(S3Utils.calculateSize(data));
}
/**
* generate an MD5 Hash for the current data.
* <p/>
* <h2>Note</h2>
* <p/>
* If this is an InputStream, it will be converted to a byte array first.
*
* @throws IOException if there is a problem generating the hash.
*/
public void generateMd5() throws IOException {
checkState(data != null, "data");
if (data instanceof InputStream) {
Md5InputStreamResult result = S3Utils
.generateMd5Result((InputStream) data);
getMetadata().setSize(result.length);
getMetadata().setMd5(result.md5);
setData(result.data);
} else {
getMetadata().setMd5(S3Utils.md5(data));
}
}
/**
* @return InputStream, if downloading, or whatever was set during
* {@link #setData(Object)}
*/
public Object getData() {
return data;
}
public void setMetadata(Metadata metadata) {
this.metadata = metadata;
}
/**
* @return System and User metadata relevant to this object.
*/
public Metadata getMetadata() {
return metadata;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("S3Object");
sb.append("{metadata=").append(metadata);
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof S3Object))
return false;
S3Object s3Object = (S3Object) o;
if (data != null ? !data.equals(s3Object.data) : s3Object.data != null)
return false;
if (!metadata.equals(s3Object.metadata))
return false;
return true;
}
@Override
public int hashCode() {
int result = data != null ? data.hashCode() : 0;
result = 31 * result + metadata.hashCode();
return result;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
/**
* Returns the total size of the downloaded object, or the chunk that's
* available.
* <p/>
* Chunking is only used when
* {@link org.jclouds.aws.s3.S3Connection#getObject(String, String, org.jclouds.aws.s3.commands.options.GetObjectOptions) }
* is called with options like tail, range, or startAt.
*
* @return the length in bytes that can be be obtained from
* {@link #getData()}
* @see org.jclouds.http.HttpHeaders#CONTENT_LENGTH
* @see GetObjectOptions
*/
public long getContentLength() {
return contentLength;
}
public void setContentRange(String contentRange) {
this.contentRange = contentRange;
}
/**
* If this is not-null, {@link #getContentLength() } will the size of chunk
* of the S3Object available via {@link #getData()}
*
* @see org.jclouds.http.HttpHeaders#CONTENT_RANGE
* @see GetObjectOptions
*/
public String getContentRange() {
return contentRange;
}
}

View File

@ -1,80 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.domain.acl;
/**
* Description from Amazon's documentation:
*
* <p />
* Because of restrictions in what can be sent via http headers, Amazon S3
* supports the concept of canned access policies for REST. A canned access
* policy can be included with the x-amz-acl header as part of a PUT operation
* to provide shorthand representation of a full access policy. When Amazon S3
* sees the x-amz-acl header as part of a PUT operation, it will assign the
* respective access policy to the resource created as a result of the PUT. If
* no x-amz-acl header is included with a PUT request, then the bucket or object
* is written with the private access control policy (even if, in the case of an
* object, the object already exists with some other pre-existing access control
* policy).
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?
* RESTAccessPolicy.html" />
* @author Adrian Cole
*
*/
public enum CannedAccessPolicy {
/**
* Owner gets FULL_CONTROL. No one else has access rights (default).
*/
PRIVATE("private"),
/**
* Owner gets FULL_CONTROL and the anonymous principal is granted READ
* access. If this policy is used on an object, it can be read from a
* browser with no authentication.
*/
PUBLIC_READ("public-read"),
/**
* Owner gets FULL_CONTROL, the anonymous principal is granted READ and
* WRITE access. This can be a useful policy to apply to a bucket, but is
* generally not recommended.
*/
PUBLIC_READ_WRITE("public-read-write"),
/**
* Owner gets FULL_CONTROL, and any principal authenticated as a registered
* Amazon S3 user is granted READ access.
*/
AUTHENTICATED_READ("authenticated-read");
private String policyName;
CannedAccessPolicy(String policyName) {
this.policyName = policyName;
}
@Override
public String toString() {
return policyName;
}
}

View File

@ -1,29 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains components that represent authorization state.
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html" />
* @author Adrian Cole
*/
package org.jclouds.aws.s3.domain.acl;

View File

@ -1,29 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains the core components of S3.
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/Components.html" />
* @author Adrian Cole
*/
package org.jclouds.aws.s3.domain;

View File

@ -1,192 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.filters;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.util.DateService;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpHeaders;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import com.google.inject.Inject;
import com.google.inject.name.Named;
/**
* Signs the S3 request. This will update timestamps at most once per second.
*
* @see <a href=
* "http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html"
* />
* @author Adrian Cole
*
*/
public class RequestAuthorizeSignature implements HttpRequestFilter {
private static final String[] firstHeadersToSign = new String[] {
HttpHeaders.CONTENT_MD5, HttpHeaders.CONTENT_TYPE, HttpHeaders.DATE };
private final String accessKey;
private final String secretKey;
private final DateService dateService;
public static final long BILLION = 1000000000;
private final AtomicReference<String> timeStamp;
private final AtomicLong trigger = new AtomicLong(System.nanoTime() + 1
* BILLION);
/**
* Start the time update service. Amazon clocks need to be within 900
* seconds of the request time. This method updates the clock every second.
* This is not performed per-request, as creation of the date object is a
* slow, synchronized command.
*/
synchronized void updateIfTimeOut() {
if (trigger.get() - System.nanoTime() <= 0) {
timeStamp.set(createNewStamp());
trigger.set(System.nanoTime() + 1 * BILLION);
}
}
// this is a hotspot when submitted concurrently, so be lazy.
// amazon is ok with up to 15 minutes off their time, so let's
// be as lazy as possible.
String createNewStamp() {
return dateService.timestampAsHeaderString();
}
public String timestampAsHeaderString() {
updateIfTimeOut();
return timeStamp.get();
}
@Inject
public RequestAuthorizeSignature(
@Named(S3Constants.PROPERTY_AWS_ACCESSKEYID) String accessKey,
@Named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY) String secretKey,
DateService dateService) {
this.accessKey = accessKey;
this.secretKey = secretKey;
this.dateService = dateService;
timeStamp = new AtomicReference<String>(createNewStamp());
}
public void filter(HttpRequest request) throws HttpException {
// re-sign the request
removeOldHeaders(request);
addDateHeader(request);
String toSign = createStringToSign(request);
addAuthHeader(request, toSign);
}
public static String createStringToSign(HttpRequest request) {
StringBuilder buffer = new StringBuilder();
appendMethod(request, buffer);
appendHttpHeaders(request, buffer);
appendAmzHeaders(request, buffer);
appendBucketName(request, buffer);
appendUriPath(request, buffer);
return buffer.toString();
}
private void removeOldHeaders(HttpRequest request) {
request.getHeaders().removeAll(S3Constants.AUTHORIZATION);
request.getHeaders().removeAll(HttpHeaders.CONTENT_TYPE);
request.getHeaders().removeAll(HttpHeaders.DATE);
}
private void addAuthHeader(HttpRequest request, String toSign)
throws HttpException {
String signature;
try {
signature = S3Utils.hmacSha1Base64(toSign, secretKey.getBytes());
} catch (Exception e) {
throw new HttpException("error signing request", e);
}
request.getHeaders().put(S3Constants.AUTHORIZATION,
"AWS " + accessKey + ":" + signature);
}
private static void appendMethod(HttpRequest request, StringBuilder toSign) {
toSign.append(request.getMethod()).append("\n");
}
private void addDateHeader(HttpRequest request) {
request.getHeaders().put(HttpHeaders.DATE, timestampAsHeaderString());
}
private static void appendAmzHeaders(HttpRequest request,
StringBuilder toSign) {
Set<String> headers = new TreeSet<String>(request.getHeaders().keySet());
for (String header : headers) {
if (header.startsWith("x-amz-")) {
toSign.append(header).append(":");
for (String value : request.getHeaders().get(header))
toSign.append(value.replaceAll("\r?\n", "")).append(",");
toSign.deleteCharAt(toSign.lastIndexOf(","));
toSign.append("\n");
}
}
}
private static void appendHttpHeaders(HttpRequest request,
StringBuilder toSign) {
for (String header : firstHeadersToSign)
toSign.append(valueOrEmpty(request.getHeaders().get(header)))
.append("\n");
}
private static void appendBucketName(HttpRequest request,
StringBuilder toSign) {
String hostHeader = request.getHeaders().get(HttpHeaders.HOST)
.iterator().next();
if (hostHeader.endsWith(".s3.amazonaws.com"))
toSign.append("/").append(
hostHeader.substring(0, hostHeader.length() - 17));
}
private static void appendUriPath(HttpRequest request, StringBuilder toSign) {
int queryIndex = request.getUri().indexOf('?');
if (queryIndex >= 0)
toSign.append(request.getUri().substring(0, queryIndex));
else
toSign.append(request.getUri());
}
private static String valueOrEmpty(Collection<String> collection) {
return (collection != null && collection.size() >= 1) ? collection
.iterator().next() : "";
}
}

View File

@ -1,29 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains HttpRequestFilters needed to operate the REST api.
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html" />
* @author Adrian Cole
*/
package org.jclouds.aws.s3.filters;

View File

@ -1,86 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.handlers;
import java.io.InputStream;
import javax.annotation.Resource;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.S3ResponseException;
import org.jclouds.aws.s3.domain.S3Error;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.http.HttpFutureCommand;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseHandler;
import org.jclouds.logging.Logger;
import com.google.inject.Inject;
/**
* This will parse and set an appropriate exception on the command object.
*
* @see S3Error
* @author Adrian Cole
*
*/
public class ParseS3ErrorFromXmlContent implements HttpResponseHandler {
@Resource
protected Logger logger = Logger.NULL;
private final S3ParserFactory parserFactory;
@Inject
public ParseS3ErrorFromXmlContent(S3ParserFactory parserFactory) {
this.parserFactory = parserFactory;
}
public void handle(HttpFutureCommand<?> command, HttpResponse response) {
S3Error error = new S3Error();
error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID));
error.setRequestToken(response
.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN));
InputStream errorStream = response.getContent();
try {
if (errorStream != null) {
error = parserFactory.createErrorParser().parse(errorStream);
if ("SignatureDoesNotMatch".equals(error.getCode()))
error.setStringSigned(RequestAuthorizeSignature
.createStringToSign(command.getRequest()));
error.setRequestToken(response
.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN));
}
} catch (Exception e) {
logger.warn(e, "error parsing XML reponse: %1$s", response);
} finally {
command.setException(new S3ResponseException(command, response,
error));
IOUtils.closeQuietly(errorStream);
}
}
}

View File

@ -1,29 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains HttpResponseHandlers needed to operate the REST api.
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html" />
* @author Adrian Cole
*/
package org.jclouds.aws.s3.handlers;

View File

@ -1,236 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Map;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.util.Utils;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Implements core Map functionality with an {@link S3Connection}
* <p/>
* All commands will wait a maximum of ${jclouds.s3.map.timeout} milliseconds to
* complete before throwing an exception.
*
* @author Adrian Cole
* @param <V>
* value of the map
*/
public abstract class BaseS3Map<V> implements S3Map<String, V> {
protected final S3Connection connection;
protected final String bucket;
/**
* maximum duration of an S3 Request
*/
@Inject(optional = true)
@Named(S3Constants.PROPERTY_S3_MAP_TIMEOUT)
protected long requestTimeoutMilliseconds = 10000;
@Inject
public BaseS3Map(S3Connection connection, @Assisted String bucket) {
this.connection = checkNotNull(connection, "connection");
this.bucket = checkNotNull(bucket, "bucketName");
}
/**
* {@inheritDoc}
* <p/>
* This returns the number of keys in the {@link S3Bucket}
*
* @see S3Bucket#getContents()
*/
public int size() {
try {
S3Bucket bucket = refreshBucket();
Set<S3Object.Metadata> contents = bucket.getContents();
return contents.size();
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting size of bucketName"
+ bucket, e);
}
}
protected boolean containsMd5(byte[] md5) throws InterruptedException,
ExecutionException, TimeoutException {
for (S3Object.Metadata metadata : refreshBucket().getContents()) {
if (Arrays.equals(md5, metadata.getMd5()))
return true;
}
return false;
}
protected byte[] getMd5(Object value) throws IOException,
FileNotFoundException, InterruptedException, ExecutionException,
TimeoutException {
S3Object object = null;
if (value instanceof S3Object) {
object = (S3Object) value;
} else {
object = new S3Object("dummy", value);
}
if (object.getMetadata().getMd5() == null)
object.generateMd5();
return object.getMetadata().getMd5();
}
/**
* attempts asynchronous gets on all objects.
*
* @see S3Connection#getObject(String, String)
*/
protected Set<S3Object> getAllObjects() {
Set<S3Object> objects = new HashSet<S3Object>();
Set<Future<S3Object>> futureObjects = new HashSet<Future<S3Object>>();
for (String key : keySet()) {
futureObjects.add(connection.getObject(bucket, key));
}
for (Future<S3Object> futureObject : futureObjects) {
S3Object object = null;
try {
object = futureObject.get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error getting value from bucket %1$s", bucket), e);
}
if (object != S3Object.NOT_FOUND)
objects.add(object);
}
return objects;
}
/**
* {@inheritDoc}
* <p/>
* Note that if value is an instance of InputStream, it will be read and
* closed following this method. To reuse data from InputStreams, pass
* {@link java.io.InputStream}s inside {@link S3Object}s
*/
public boolean containsValue(Object value) {
try {
byte[] md5 = getMd5(value);
return containsMd5(md5);
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error searching for ETAG of value: [%2$s] in bucketName:%1$s",
bucket, value), e);
}
}
public static class S3RuntimeException extends RuntimeException {
private static final long serialVersionUID = 1L;
S3RuntimeException(String s) {
super(s);
}
public S3RuntimeException(String s, Throwable throwable) {
super(s, throwable);
}
}
public void clear() {
try {
List<Future<Boolean>> deletes = new ArrayList<Future<Boolean>>();
for (String key : keySet()) {
deletes.add(connection.deleteObject(bucket, key));
}
for (Future<Boolean> isdeleted : deletes)
if (!isdeleted.get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS)) {
throw new S3RuntimeException("failed to delete entry");
}
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error clearing bucketName" + bucket, e);
}
}
protected S3Bucket refreshBucket() throws InterruptedException,
ExecutionException, TimeoutException {
S3Bucket currentBucket = connection.listBucket(bucket).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
if (currentBucket == S3Bucket.NOT_FOUND)
throw new S3RuntimeException("bucketName not found: " + bucket);
else
return currentBucket;
}
public Set<String> keySet() {
try {
Set<String> keys = new HashSet<String>();
for (S3Object.Metadata object : refreshBucket().getContents())
keys.add(object.getKey());
return keys;
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting keys in bucketName: "
+ bucket, e);
}
}
public boolean containsKey(Object key) {
try {
return connection.headObject(bucket, key.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS) != S3Object.Metadata.NOT_FOUND;
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error searching for %1$s:%2$s", bucket, key), e);
}
}
public boolean isEmpty() {
return keySet().size() == 0;
}
public S3Bucket getBucket() {
try {
return refreshBucket();
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error getting bucketName" + bucket, e);
}
}
}

View File

@ -1,106 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.internal;
import com.google.inject.Inject;
import com.google.inject.Injector;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3Context;
import org.jclouds.aws.s3.S3InputStreamMap;
import org.jclouds.aws.s3.S3ObjectMap;
import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger;
import javax.annotation.Resource;
import java.io.IOException;
/**
* Uses a Guice Injector to configure the objects served by S3Context methods.
*
* @author Adrian Cole
* @see Injector
*/
public class GuiceS3Context implements S3Context {
public interface S3ObjectMapFactory {
S3ObjectMap createMapView(String bucket);
}
public interface S3InputStreamMapFactory {
S3InputStreamMap createMapView(String bucket);
}
@Resource
private Logger logger = Logger.NULL;
private final Injector injector;
private final S3InputStreamMapFactory s3InputStreamMapFactory;
private final S3ObjectMapFactory s3ObjectMapFactory;
private final Closer closer;
@Inject
private GuiceS3Context(Injector injector, Closer closer,
S3ObjectMapFactory s3ObjectMapFactory,
S3InputStreamMapFactory s3InputStreamMapFactory) {
this.injector = injector;
this.s3InputStreamMapFactory = s3InputStreamMapFactory;
this.s3ObjectMapFactory = s3ObjectMapFactory;
this.closer = closer;
}
/**
* {@inheritDoc}
*/
public S3Connection getConnection() {
return injector.getInstance(S3Connection.class);
}
/**
* {@inheritDoc}
*/
public S3InputStreamMap createInputStreamMap(String bucket) {
getConnection().putBucketIfNotExists(bucket);
return s3InputStreamMapFactory.createMapView(bucket);
}
/**
* {@inheritDoc}
*/
public S3ObjectMap createS3ObjectMap(String bucket) {
getConnection().putBucketIfNotExists(bucket);
return s3ObjectMapFactory.createMapView(bucket);
}
/**
* {@inheritDoc}
*
* @see Closer
*/
public void close() {
try {
closer.close();
} catch (IOException e) {
logger.error(e, "error closing content");
}
}
}

View File

@ -1,243 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.internal;
import java.util.List;
import java.util.concurrent.Future;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.commands.BucketExists;
import org.jclouds.aws.s3.commands.CopyObject;
import org.jclouds.aws.s3.commands.DeleteBucket;
import org.jclouds.aws.s3.commands.DeleteObject;
import org.jclouds.aws.s3.commands.ListOwnedBuckets;
import org.jclouds.aws.s3.commands.GetObject;
import org.jclouds.aws.s3.commands.HeadObject;
import org.jclouds.aws.s3.commands.ListBucket;
import org.jclouds.aws.s3.commands.PutBucket;
import org.jclouds.aws.s3.commands.PutObject;
import org.jclouds.aws.s3.commands.S3CommandFactory;
import org.jclouds.aws.s3.commands.options.CopyObjectOptions;
import org.jclouds.aws.s3.commands.options.GetObjectOptions;
import org.jclouds.aws.s3.commands.options.ListBucketOptions;
import org.jclouds.aws.s3.commands.options.PutBucketOptions;
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
import org.jclouds.aws.s3.domain.S3Bucket;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.aws.s3.domain.S3Bucket.Metadata;
import org.jclouds.http.HttpFutureCommandClient;
import com.google.inject.Inject;
/**
* Uses {@link HttpFutureCommandClient} to invoke the REST API of S3.
*
* @see <a
* href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?"
* />
* @author Adrian Cole
*/
public class LiveS3Connection implements S3Connection {
private final HttpFutureCommandClient client;
/**
* creates command objects that can be submitted to the client
*/
private final S3CommandFactory factory;
@Inject
public LiveS3Connection(HttpFutureCommandClient client,
S3CommandFactory factory) {
this.client = client;
this.factory = factory;
}
/**
* {@inheritDoc}
*
* @see GetObject
*/
public Future<S3Object> getObject(String s3Bucket, String key) {
return getObject(s3Bucket, key, GetObjectOptions.NONE);
}
/**
* {@inheritDoc}
*
* @see GetObject
*/
public Future<S3Object> getObject(String s3Bucket, String key,
GetObjectOptions options) {
GetObject getObject = factory.createGetObject(s3Bucket, key, options);
client.submit(getObject);
return getObject;
}
/**
* {@inheritDoc}
*
* @see HeadObject
*/
public Future<S3Object.Metadata> headObject(String s3Bucket, String key) {
HeadObject headMetadata = factory.createHeadMetadata(s3Bucket, key);
client.submit(headMetadata);
return headMetadata;
}
/**
* {@inheritDoc}
*
* @see DeleteObject
*/
public Future<Boolean> deleteObject(String s3Bucket, String key) {
DeleteObject deleteObject = factory.createDeleteObject(s3Bucket, key);
client.submit(deleteObject);
return deleteObject;
}
/**
* {@inheritDoc}
*
* @see PutObject
*/
public Future<byte[]> putObject(String s3Bucket, S3Object object) {
return putObject(s3Bucket, object, PutObjectOptions.NONE);
}
/**
* {@inheritDoc}
*
* @see PutObject
*/
public Future<byte[]> putObject(String bucketName, S3Object object,
PutObjectOptions options) {
PutObject putObject = factory.createPutObject(bucketName, object,
options);
client.submit(putObject);
return putObject;
}
/**
* {@inheritDoc}
*
* @see PutBucket
*/
public Future<Boolean> putBucketIfNotExists(String s3Bucket) {
return putBucketIfNotExists(s3Bucket, PutBucketOptions.NONE);
}
/**
* {@inheritDoc}
*
* @see PutBucket
*/
public Future<Boolean> putBucketIfNotExists(String s3Bucket,
PutBucketOptions options) {
PutBucket putBucket = factory.createPutBucket(s3Bucket, options);
client.submit(putBucket);
return putBucket;
}
/**
* {@inheritDoc}
*
* @see DeleteBucket
*/
public Future<Boolean> deleteBucketIfEmpty(String s3Bucket) {
DeleteBucket deleteBucket = factory.createDeleteBucket(s3Bucket);
client.submit(deleteBucket);
return deleteBucket;
}
/**
* {@inheritDoc}
*
* @see CopyObject
*/
public Future<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket,
String destinationObject) {
return copyObject(sourceBucket, sourceObject, destinationBucket,
destinationObject, new CopyObjectOptions());
}
/**
* {@inheritDoc}
*
* @see CopyObject
*/
public Future<S3Object.Metadata> copyObject(String sourceBucket,
String sourceObject, String destinationBucket,
String destinationObject, CopyObjectOptions options) {
CopyObject copy = factory.createCopyObject(sourceBucket, sourceObject,
destinationBucket, destinationObject, options);
client.submit(copy);
return copy;
}
/**
* {@inheritDoc}
*
* @see BucketExists
*/
public Future<Boolean> bucketExists(String s3Bucket) {
BucketExists headRequestObject = factory.createHeadBucket(s3Bucket);
client.submit(headRequestObject);
return headRequestObject;
}
/**
* {@inheritDoc}
*
* @see ListBucket
*/
public Future<S3Bucket> listBucket(String s3Bucket) {
return listBucket(s3Bucket, ListBucketOptions.NONE);
}
/**
* {@inheritDoc}
*
* @see ListBucket
*/
public Future<S3Bucket> listBucket(String s3Bucket,
ListBucketOptions options) {
ListBucket getBucket = factory.createListBucket(s3Bucket, options);
client.submit(getBucket);
return getBucket;
}
/**
* {@inheritDoc}
*
* @see ListOwnedBuckets
*/
public Future<List<Metadata>> listOwnedBuckets() {
ListOwnedBuckets listRequest = factory
.createGetMetadataForOwnedBuckets();
client.submit(listRequest);
return listRequest;
}
}

View File

@ -1,271 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.internal;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3InputStreamMap;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils;
import java.io.File;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* Map representation of a live connection to S3. All put operations will result
* in Md5 calculation. If this is not desired, use {@link LiveS3ObjectMap}
* instead.
*
* @author Adrian Cole
* @see S3Connection
* @see BaseS3Map
*/
public class LiveS3InputStreamMap extends BaseS3Map<InputStream> implements
S3InputStreamMap {
@Inject
public LiveS3InputStreamMap(S3Connection connection, @Assisted String bucket) {
super(connection, bucket);
}
/**
* {@inheritDoc}
*
* @see S3Connection#getObject(String, String)
*/
public InputStream get(Object o) {
try {
return (InputStream) (connection.getObject(bucket, o.toString())
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS))
.getData();
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error geting object %1$s:%2$s", bucket, o), e);
}
}
/**
* {@inheritDoc}
*
* @see S3Connection#deleteObject(String, String)
*/
public InputStream remove(Object o) {
InputStream old = get(o);
try {
connection.deleteObject(bucket, o.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error removing object %1$s:%2$s", bucket, o), e);
}
return old;
}
/**
* {@inheritDoc}
*
* @see #getAllObjects()
*/
public Collection<InputStream> values() {
Collection<InputStream> values = new LinkedList<InputStream>();
Set<S3Object> objects = getAllObjects();
for (S3Object object : objects) {
values.add((InputStream) object.getData());
}
return values;
}
/**
* {@inheritDoc}
*
* @see #getAllObjects()
*/
public Set<Map.Entry<String, InputStream>> entrySet() {
Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>();
for (S3Object object : getAllObjects()) {
entrySet.add(new Entry(object.getKey(), (InputStream) object
.getData()));
}
return entrySet;
}
public class Entry implements java.util.Map.Entry<String, InputStream> {
private InputStream value;
private String key;
Entry(String key, InputStream value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public InputStream getValue() {
return value;
}
/**
* {@inheritDoc}
*
* @see LiveS3InputStreamMap#put(String, InputStream)
*/
public InputStream setValue(InputStream value) {
return put(key, value);
}
}
/**
* {@inheritDoc}
*
* @see #putAllInternal(Map)
*/
public void putAll(Map<? extends String, ? extends InputStream> map) {
putAllInternal(map);
}
/**
* {@inheritDoc}
*
* @see #putAllInternal(Map)
*/
public void putAllBytes(Map<? extends String, ? extends byte[]> map) {
putAllInternal(map);
}
/**
* {@inheritDoc}
*
* @see #putAllInternal(Map)
*/
public void putAllFiles(Map<? extends String, ? extends File> map) {
putAllInternal(map);
}
/**
* {@inheritDoc}
*
* @see #putAllInternal(Map)
*/
public void putAllStrings(Map<? extends String, ? extends String> map) {
putAllInternal(map);
}
/**
* submits requests to add all objects and collects the results later. All
* values will have md5 calculated first. As a side-effect of this, the
* content will be copied into a byte [].
*
* @see S3Connection#putObject(String, S3Object)
*/
@VisibleForTesting
void putAllInternal(Map<? extends String, ? extends Object> map) {
try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
S3Object object = new S3Object(entry.getKey());
object.setData(entry.getValue());
object.generateMd5();
puts.add(connection.putObject(bucket, object));
}
for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error putting into bucketName" + bucket,
e);
}
}
/**
* {@inheritDoc}
*
* @see #putInternal(String, Object)
*/
public InputStream putString(String key, String value) {
return putInternal(key, value);
}
/**
* {@inheritDoc}
*
* @see #putInternal(String, Object)
*/
public InputStream putFile(String key, File value) {
return putInternal(key, value);
}
/**
* {@inheritDoc}
*
* @see #putInternal(String, Object)
*/
public InputStream putBytes(String key, byte[] value) {
return putInternal(key, value);
}
/**
* {@inheritDoc}
*
* @see #putInternal(String, Object)
*/
public InputStream put(String key, InputStream value) {
return putInternal(key, value);
}
/**
* calculates md5 before adding the object to s3. As a side-effect of this,
* the content will be copied into a byte []. *
*
* @see S3Connection#putObject(String, S3Object)
*/
@VisibleForTesting
InputStream putInternal(String s, Object o) {
S3Object object = new S3Object(s);
try {
InputStream returnVal = containsKey(s) ? get(s) : null;
object.setData(o);
object.generateMd5();
connection.putObject(bucket, object).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
return returnVal;
} catch (Exception e) {
Utils.<S3RuntimeException>rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error adding object %1$s:%2$s", bucket, object), e);
}
}
}

View File

@ -1,184 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.S3Connection;
import org.jclouds.aws.s3.S3ObjectMap;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
/**
* Map representation of a live connection to S3.
*
* @see S3Connection
* @see BaseS3Map
*
* @author Adrian Cole
*/
public class LiveS3ObjectMap extends BaseS3Map<S3Object> implements S3ObjectMap {
@Inject
public LiveS3ObjectMap(S3Connection connection, @Assisted String bucket) {
super(connection, bucket);
}
/**
* {@inheritDoc}
*
* @see #values()
*/
public Set<java.util.Map.Entry<String, S3Object>> entrySet() {
Set<Map.Entry<String, S3Object>> entrySet = new HashSet<Map.Entry<String, S3Object>>();
for (S3Object value : values()) {
Map.Entry<String, S3Object> entry = new Entry(value.getKey(), value);
entrySet.add(entry);
}
return entrySet;
}
public class Entry implements java.util.Map.Entry<String, S3Object> {
private S3Object value;
private String key;
Entry(String key, S3Object value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public S3Object getValue() {
return value;
}
/**
* {@inheritDoc}
*
* @see LiveS3ObjectMap#put(String, S3Object)
*/
public S3Object setValue(S3Object value) {
return put(key, value);
}
}
/**
* {@inheritDoc}
*
* @see S3Connection#getObject(String, String)
*/
public S3Object get(Object key) {
try {
return connection.getObject(bucket, key.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error geting object %1$s:%2$s", bucket, key), e);
}
}
/**
* {@inheritDoc}
*
* @see S3Connection#putObject(String, S3Object)
*/
public S3Object put(String key, S3Object value) {
S3Object returnVal = get(key);
try {
connection.putObject(bucket, value).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(
String.format("Error putting object %1$s:%2$s%n%3$s",
bucket, key, value), e);
}
return returnVal;
}
/**
* {@inheritDoc} attempts to put all objects asynchronously.
*
* @see S3Connection#putObject(String, S3Object)
*/
public void putAll(Map<? extends String, ? extends S3Object> map) {
try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
for (S3Object object : map.values()) {
puts.add(connection.putObject(bucket, object));
}
for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException("Error putting into bucketName" + bucket,
e);
}
}
/**
* {@inheritDoc}
*
* @see S3Connection#deleteObject(String, String)
*/
public S3Object remove(Object key) {
S3Object old = get(key);
try {
connection.deleteObject(bucket, key.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<S3RuntimeException> rethrowIfRuntimeOrSameType(e);
throw new S3RuntimeException(String.format(
"Error removing object %1$s:%2$s", bucket, key), e);
}
return old;
}
/**
* {@inheritDoc}
*
* @see #getAllObjects()
*/
public Collection<S3Object> values() {
return getAllObjects();
}
}

View File

@ -1,28 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains implementation classes for the jclouds-s3 public api
* @author Adrian Cole
*/
package org.jclouds.aws.s3.internal;

View File

@ -1,30 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains an Amazon S3 client implemented by {@link org.jclouds.http.HttpFutureCommandClient} commands.
*
* @see <a href="http://aws.amazon.com/s3"/>
* @author Adrian Cole
*/
package org.jclouds.aws.s3;

View File

@ -1,44 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.reference;
import org.jclouds.command.pool.PoolConstants;
import org.jclouds.http.HttpConstants;
/**
* Configuration properties and constants used in S3 connections.
*
* @author Adrian Cole
*/
public interface S3Constants extends HttpConstants, PoolConstants, S3Headers {
public static final String PROPERTY_AWS_SECRETACCESSKEY = "jclouds.aws.secretaccesskey";
public static final String PROPERTY_AWS_ACCESSKEYID = "jclouds.aws.accesskeyid";
/**
* longest time a single Map operation can take before throwing an
* exception.
*/
public static final String PROPERTY_S3_MAP_TIMEOUT = "jclouds.s3.map.timeout";
}

View File

@ -1,55 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.reference;
import org.jclouds.http.HttpHeaders;
/**
* Additional headers specified by Amazon S3 REST API.
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/index.html?RESTAuthentication.html"
* />
* @author Adrian Cole
*
*/
public interface S3Headers extends HttpHeaders {
/**
* The canned ACL to apply to the object. Options include private,
* public-read, public-read-write, and authenticated-read. For more
* information, see REST Access Control Policy.
*/
public static final String CANNED_ACL = "x-amz-acl";
/**
* Any header starting with this prefix is considered user metadata. It will
* be stored with the object and returned when you retrieve the object. The
* total size of the HTTP request, not including the body, must be less than
* 8 KB.
*/
public static final String USER_METADATA_PREFIX = "x-amz-meta-";
public static final String AMZ_MD5 = "x-amz-meta-object-md5";
public static final String REQUEST_ID = "x-amz-request-id";
public static final String REQUEST_TOKEN = "x-amz-id-2";
}

View File

@ -1,28 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains properties and reference data used in S3.
* @author Adrian Cole
*/
package org.jclouds.aws.s3.reference;

View File

@ -1,57 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.util;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
/**
* Parses dates found in XML responses and HTTP response headers.
*
* @author Adrian Cole
*
*/
public class DateService {
private DateTimeFormatter headerDateFormat = DateTimeFormat
.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'");
public DateTime dateTimeFromXMLFormat(String toParse) {
// the format is natively parseable from the DateTime constructor
return new DateTime(toParse);
}
public DateTime dateTimeFromHeaderFormat(String toParse) {
return headerDateFormat.parseDateTime(toParse);
}
public String timestampAsHeaderString() {
return toHeaderString(new DateTime());
}
public String toHeaderString(DateTime date) {
return headerDateFormat.print(date.withZone(DateTimeZone.UTC));
}
}

View File

@ -1,245 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.jclouds.aws.s3.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Base64;
import org.jclouds.aws.s3.domain.S3Object;
import org.jclouds.util.Utils;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;
/**
* Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests
* and responses.
*
* @author Adrian Cole
*/
public class S3Utils extends Utils {
private static final Pattern IP_PATTERN = Pattern
.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"
+ "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b");
public static String validateBucketName(String bucketName) {
checkNotNull(bucketName, "bucketName");
checkArgument(bucketName.matches("^[a-z0-9].*"),
"bucketName name must start with a number or letter");
checkArgument(
bucketName.matches("^[-_.a-z0-9]+"),
"bucketName name can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)");
checkArgument(bucketName.length() > 2 && bucketName.length() < 256,
"bucketName name must be between 3 and 255 characters long");
checkArgument(!IP_PATTERN.matcher(bucketName).matches(),
"bucketName name cannot be ip address style");
return bucketName;
}
static final byte[] HEX_CHAR_TABLE = {(byte) '0', (byte) '1', (byte) '2',
(byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c',
(byte) 'd', (byte) 'e', (byte) 'f'};
public static String toHexString(byte[] raw)
throws UnsupportedEncodingException {
byte[] hex = new byte[2 * raw.length];
int index = 0;
for (byte b : raw) {
int v = b & 0xFF;
hex[index++] = HEX_CHAR_TABLE[v >>> 4];
hex[index++] = HEX_CHAR_TABLE[v & 0xF];
}
return new String(hex, "ASCII");
}
public static long calculateSize(Object data) {
long size = -1;
if (data instanceof byte[]) {
size = ((byte[]) data).length;
} else if (data instanceof String) {
size = ((String) data).length();
} else if (data instanceof File) {
size = ((File) data).length();
}
return size;
}
/**
* @throws IOException
*/
public static byte[] md5(Object data) throws IOException {
checkNotNull(data, "data must be set before calling generateMd5()");
byte[] md5 = null;
if (data == null) {
} else if (data instanceof byte[]) {
md5 = S3Utils.md5((byte[]) data);
} else if (data instanceof String) {
md5 = S3Utils.md5(((String) data).getBytes());
} else if (data instanceof File) {
md5 = S3Utils.md5(((File) data));
} else {
throw new UnsupportedOperationException("Content not supported "
+ data.getClass());
}
return md5;
}
public static byte[] fromHexString(String hex) {
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2),
16);
}
return bytes;
}
public static String hmacSha1Base64(String toEncode, byte[] key)
throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException {
HMac hmac = new HMac(new SHA1Digest());
byte[] resBuf = new byte[hmac.getMacSize()];
byte[] plainBytes = toEncode.getBytes();
byte[] keyBytes = key;
hmac.init(new KeyParameter(keyBytes));
hmac.update(plainBytes, 0, plainBytes.length);
hmac.doFinal(resBuf, 0);
return toBase64String(resBuf);
}
public static String md5Hex(byte[] toEncode)
throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException, UnsupportedEncodingException {
byte[] resBuf = md5(toEncode);
return toHexString(resBuf);
}
public static String md5Base64(byte[] toEncode)
throws NoSuchAlgorithmException, NoSuchProviderException,
InvalidKeyException {
byte[] resBuf = md5(toEncode);
return toBase64String(resBuf);
}
public static String toBase64String(byte[] resBuf) {
return new String(Base64.encode(resBuf));
}
public static byte[] md5(byte[] plainBytes) {
MD5Digest md5 = new MD5Digest();
byte[] resBuf = new byte[md5.getDigestSize()];
md5.update(plainBytes, 0, plainBytes.length);
md5.doFinal(resBuf, 0);
return resBuf;
}
public static byte[] md5(File toEncode) throws IOException {
MD5Digest md5 = new MD5Digest();
byte[] resBuf = new byte[md5.getDigestSize()];
byte[] buffer = new byte[1024];
int numRead = -1;
InputStream i = new FileInputStream(toEncode);
try {
do {
numRead = i.read(buffer);
if (numRead > 0) {
md5.update(buffer, 0, numRead);
}
} while (numRead != -1);
} finally {
IOUtils.closeQuietly(i);
}
md5.doFinal(resBuf, 0);
return resBuf;
}
public static Md5InputStreamResult generateMd5Result(InputStream toEncode)
throws IOException {
MD5Digest md5 = new MD5Digest();
byte[] resBuf = new byte[md5.getDigestSize()];
byte[] buffer = new byte[1024];
ByteArrayOutputStream out = new ByteArrayOutputStream();
long length = 0;
int numRead = -1;
try {
do {
numRead = toEncode.read(buffer);
if (numRead > 0) {
length += numRead;
md5.update(buffer, 0, numRead);
out.write(buffer, 0, numRead);
}
} while (numRead != -1);
} finally {
out.close();
IOUtils.closeQuietly(toEncode);
}
md5.doFinal(resBuf, 0);
return new Md5InputStreamResult(out.toByteArray(), resBuf, length);
}
public static class Md5InputStreamResult {
public final byte[] data;
public final byte[] md5;
public final long length;
Md5InputStreamResult(byte[] data, byte[] md5, long length) {
this.data = checkNotNull(data, "data");
this.md5 = checkNotNull(md5, "md5");
checkArgument(length >= 0, "length cannot me negative");
this.length = length;
}
}
public static String getContentAsStringAndClose(S3Object object)
throws IOException {
checkNotNull(object, "s3Object");
checkNotNull(object.getData(), "s3Object.content");
Object o = object.getData();
if (o instanceof InputStream) {
String returnVal = toStringAndClose((InputStream) o);
if (object.getMetadata().getContentType().indexOf("xml") >= 0) {
}
return returnVal;
} else {
throw new IllegalArgumentException("Object type not supported: "
+ o.getClass().getName());
}
}
}

View File

@ -1,28 +0,0 @@
/**
*
* Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
*
* ====================================================================
* 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.
* ====================================================================
*/
/**
* This package contains utilities needed for S3.
* @author Adrian Cole
*/
package org.jclouds.aws.s3.util;

Some files were not shown because too many files have changed in this diff Show More