blob: f578732995313569b154100dde8a42c9946b31c7 [file] [log] [blame]
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed 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.springframework.aws.maven;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.proxy.ProxyInfoProvider;
import org.apache.maven.wagon.repository.Repository;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.acl.AccessControlList;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.security.AWSCredentials;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* An implementation of the Maven Wagon interface that allows you to access the
* Amazon S3 service. URLs that reference the S3 service should be in the form
* of <code>s3://bucket.name</code>. As an example
* <code>s3://static.springframework.org</code> would put files into the
* <code>static.springframework.org</code> bucket on the S3 service. <p/> This
* implementation uses the <code>username</code> and <code>passphrase</code>
* portions of the server authentication metadata for credentials.
*
* @author Ben Hale
*/
public class SimpleStorageServiceWagon extends AbstractWagon {
private S3Service service;
private S3Bucket bucket;
private String basedir;
public SimpleStorageServiceWagon() {
super(false);
}
protected void connectToRepository(Repository source, AuthenticationInfo authenticationInfo, ProxyInfoProvider proxyInfoProvider)
throws AuthenticationException {
try {
service = new RestS3Service(getCredentials(authenticationInfo));
}
catch (S3ServiceException e) {
throw new AuthenticationException("Cannot authenticate with current credentials", e);
}
bucket = new S3Bucket(source.getHost());
basedir = getBaseDir(source);
}
protected boolean doesRemoteResourceExist(String resourceName) {
try {
service.getObjectDetails(bucket, basedir + resourceName);
}
catch (S3ServiceException e) {
return false;
}
return true;
}
protected void disconnectFromRepository() {
// Nothing to do for S3
}
protected void getResource(String resourceName, File destination, TransferProgress progress)
throws ResourceDoesNotExistException, S3ServiceException, IOException {
S3Object object;
try {
object = service.getObject(bucket, basedir + resourceName);
}
catch (S3ServiceException e) {
throw new ResourceDoesNotExistException("Resource " + resourceName + " does not exist in the repository", e);
}
if(!destination.getParentFile().exists()) {
destination.getParentFile().mkdirs();
}
InputStream in = null;
OutputStream out = null;
try {
in = object.getDataInputStream();
out = new TransferProgressFileOutputStream(destination, progress);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
}
finally {
if (in != null) {
try {
in.close();
}
catch (IOException e) {
// Nothing possible at this point
}
}
if (out != null) {
try {
out.close();
}
catch (IOException e) {
// Nothing possible at this point
}
}
}
}
protected boolean isRemoteResourceNewer(String resourceName, long timestamp) throws S3ServiceException {
S3Object object = service.getObjectDetails(bucket, basedir + resourceName);
return object.getLastModifiedDate().compareTo(new Date(timestamp)) < 0;
}
protected List<String> listDirectory(String directory) throws Exception {
S3Object[] objects = service.listObjects(bucket, basedir + directory, "");
List<String> fileNames = new ArrayList<String>(objects.length);
for (S3Object object : objects) {
fileNames.add(object.getKey());
}
return fileNames;
}
protected void putResource(File source, String destination, TransferProgress progress) throws S3ServiceException,
IOException {
buildDestinationPath(getDestinationPath(destination));
S3Object object = new S3Object(basedir + destination);
object.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
object.setDataInputFile(source);
object.setContentLength(source.length());
InputStream in = null;
try {
service.putObject(bucket, object);
in = new FileInputStream(source);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) != -1) {
progress.notify(buffer, length);
}
}
finally {
if (in != null) {
try {
in.close();
}
catch (IOException e) {
// Nothing possible at this point
}
}
}
}
private void buildDestinationPath(String destination) throws S3ServiceException {
S3Object object = new S3Object(basedir + destination + "/");
object.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
object.setContentLength(0);
service.putObject(bucket, object);
int index = destination.lastIndexOf('/');
if (index != -1) {
buildDestinationPath(destination.substring(0, index));
}
}
private String getDestinationPath(String destination) {
return destination.substring(0, destination.lastIndexOf('/'));
}
private String getBaseDir(Repository source) {
StringBuilder sb = new StringBuilder(source.getBasedir());
sb.deleteCharAt(0);
if (sb.charAt(sb.length() - 1) != '/') {
sb.append('/');
}
return sb.toString();
}
private AWSCredentials getCredentials(AuthenticationInfo authenticationInfo) throws AuthenticationException {
if (authenticationInfo == null) {
return null;
}
String accessKey = authenticationInfo.getUserName();
String secretKey = authenticationInfo.getPassphrase();
if (accessKey == null || secretKey == null) {
throw new AuthenticationException("S3 requires a username and passphrase to be set");
}
return new AWSCredentials(accessKey, secretKey);
}
}