mirror of https://github.com/apache/jclouds.git
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:
parent
8b3424eaad
commit
c2c883558d
|
@ -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>
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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.
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
// }
|
||||
// }
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
184
s3/pom.xml
184
s3/pom.xml
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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> {
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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 + "");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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() : "";
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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";
|
||||
|
||||
}
|
|
@ -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";
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue