Issue 96: removed redundant factories and modified utilities and functions to use XML parsers directly

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1915 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-09-24 22:42:58 +00:00
parent eaa4674918
commit 9f78e8d2fc
36 changed files with 410 additions and 1086 deletions

View File

@ -46,13 +46,13 @@ public class ErrorHandler extends ParseSax.HandlerWithResult<AWSError> {
public void endElement(String uri, String name, String qName) { public void endElement(String uri, String name, String qName) {
if (qName.equals("Code")) { if (qName.equals("Code")) {
error.setCode(currentText.toString()); error.setCode(currentText.toString().trim());
} else if (qName.equals("Message")) { } else if (qName.equals("Message")) {
error.setMessage(currentText.toString()); error.setMessage(currentText.toString().trim());
} else if (qName.equalsIgnoreCase("RequestId")) { } else if (qName.equalsIgnoreCase("RequestId")) {
error.setRequestId(currentText.toString()); error.setRequestId(currentText.toString().trim());
} else if (!qName.equals("Error")) { } else if (!qName.equals("Error")) {
error.getDetails().put(qName, currentText.toString()); error.getDetails().put(qName, currentText.toString().trim());
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }

View File

@ -0,0 +1,72 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.xml;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.xml.ErrorHandler;
import org.jclouds.http.HttpException;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "s3.ErrorHandlerTest")
public class ErrorHandlerTest extends BaseHandlerTest {
public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>";
@SuppressWarnings("unchecked")
ParseSax<AWSError> createParser() {
ParseSax<AWSError> parser = (ParseSax<AWSError>) factory.create(injector
.getInstance(ErrorHandler.class));
return parser;
}
@Test
public void testErrorFromAmazonIfYouDontRemoveTransferEncodingHeader() throws HttpException {
ParseSax<AWSError> parser = createParser();
AWSError error = parser.parse(IOUtils
.toInputStream(errorFromAmazonIfYouDontRemoveTransferEncodingHeader));
assertEquals(error.getCode(), "NotImplemented");
assertEquals(error.getMessage(),
"A header you provided implies functionality that is not implemented");
assertEquals(error.getDetails().get("Header"), "Transfer-Encoding");
assertEquals(error.getRequestId(), "7C59925D75D15561");
assertEquals(error.getDetails().get("HostId"),
"fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb");
}
public static final String badRequestWhenSourceIsDestBucketOnCopy400 = "<Error><Code>InvalidRequest</Code><Message>The Source and Destination may not be the same when the MetadataDirective is Copy.</Message><RequestId>54C77CAF4D42474B</RequestId><HostId>SJecknEUUUx88/65VAKbCdKSOCkpuVTeu7ZG9in9x9NTNglGnoxdbALCfS4k/DUZ</HostId></Error>";
public static final String noSuchSourceKeyOrBucketOnCopy404 = "<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>null</Key><RequestId>9CCDF1DACA78B36F</RequestId><HostId>63cqk9YsTFBVfBfks840JVGsepPEdQM42mU+r7HN35sF4Nk5xAcWDEUPaQpK2eFU</HostId></Error>";
public static final String noSuchDestinationBucketOnCopy404 = "<Error><Code>NoSuchBucket</Code><Message>The specified bucketName does not exist</Message><BucketName>copydestination</BucketName><RequestId>4F0CF319C5535975</RequestId><HostId>hdZyHOm7VK+JI2UCdye3d6TVkKhRBIoWflldXVDTKbgipYlamy8HgPBzHrUAVQNJ</HostId></Error>";
public static final String badSign403 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<Error><Code>SignatureDoesNotMatch</Code><Message>The operation signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>47 45 54 0a 0a 0a 54 68 75 2c 20 31 39 20 4d 61 72 20 32 30 30 39 20 31 37 3a 34 38 3a 30 31 20 47 4d 54 0a 2f 61 64 72 69 61 6e 63 6f 6c 65 2e 73 33 2e 61 6d 61 7a 6f 6e 73 33 74 65 73 74 2e 66 69 6c 65 74 65 73 74 73 66 6f 72 61 64 72 69 61 6e 2f 66 69 6c 65</StringToSignBytes><RequestId>514AA22EB75A6E42</RequestId><HostId>H5nqnZkGjuKvB+seutvx5hnp1P+WAuC9c3Y7MdQCcYDr1TGwNX/mt+FHstK0pVld</HostId><SignatureProvided>Qm6Wss7e5e/eNXV50AxChH+xkLI=</SignatureProvided><StringToSign>GET\n"
+ "\n"
+ "\n"
+ "Thu, 19 Mar 2009 17:48:01 GMT\n"
+ "/adriancole.s3.amazons3test.filetestsforadrian/file</StringToSign><AWSAccessKeyId>0101100101001001</AWSAccessKeyId></Error>";
public static final String amazonHadAnError500 = "<Error><Code>InternalError</Code><Message>We encountered an internal error. Please try again.</Message><RequestId>EF6FA7A639CAFF15</RequestId><HostId>tBkX23mIeq2riHsNw2YShupMlZ9+iy3V/uN+lRhqCR4qHTE07ujFeyAUPTowvuH/</HostId></Error>";
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>NoSuchKey</Code>
<Message>The resource you requested does not exist</Message>
<Resource>/mybucket/myfoto.jpg</Resource>
<RequestId>4442587FB7D0A2F9</RequestId>
</Error>

View File

@ -24,40 +24,38 @@
package org.jclouds.aws.s3.handlers; package org.jclouds.aws.s3.handlers;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.aws.domain.AWSError; import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import javax.inject.Inject;
import javax.inject.Named;
/** /**
* Handles Retryable responses with error codes in the 3xx range * Handles Retryable responses with error codes in the 3xx range
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class AWSClientErrorRetryHandler implements HttpRetryHandler { public class AWSClientErrorRetryHandler implements HttpRetryHandler {
private final S3ParserFactory parserFactory;
private final int retryCountLimit; @Inject(optional = true)
@Named(HttpConstants.PROPERTY_HTTP_MAX_RETRIES)
private int retryCountLimit = 5;
private final S3Utils utils; private final S3Utils utils;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Inject @Inject
public AWSClientErrorRetryHandler(S3Utils utils, S3ParserFactory parserFactory, public AWSClientErrorRetryHandler(S3Utils utils) {
@Named("jclouds.http.max-retries") int retryCountLimit) {
this.utils = utils; this.utils = utils;
this.retryCountLimit = retryCountLimit;
this.parserFactory = parserFactory;
} }
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
@ -67,8 +65,7 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
byte[] content = Utils.closeConnectionButKeepContentStream(response); byte[] content = Utils.closeConnectionButKeepContentStream(response);
command.incrementRedirectCount(); command.incrementRedirectCount();
try { try {
AWSError error = utils.parseAWSErrorFromContent(parserFactory, command, response, AWSError error = utils.parseAWSErrorFromContent(command, response, new String(content));
new String(content));
if ("RequestTimeout".equals(error.getCode()) if ("RequestTimeout".equals(error.getCode())
|| "OperationAborted".equals(error.getCode())) { || "OperationAborted".equals(error.getCode())) {
return true; return true;

View File

@ -23,13 +23,13 @@
*/ */
package org.jclouds.aws.s3.handlers; package org.jclouds.aws.s3.handlers;
import javax.inject.Inject;
import javax.ws.rs.HttpMethod; import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.aws.domain.AWSError; import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.reference.S3Constants; import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
@ -37,24 +37,18 @@ import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.http.handlers.RedirectionRetryHandler; import org.jclouds.http.handlers.RedirectionRetryHandler;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import javax.inject.Inject;
import javax.inject.Named;
/** /**
* Handles Retryable responses with error codes in the 3xx range * Handles Retryable responses with error codes in the 3xx range
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class AWSRedirectionRetryHandler extends RedirectionRetryHandler { public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
private final S3ParserFactory parserFactory;
private final S3Utils utils; private final S3Utils utils;
@Inject @Inject
public AWSRedirectionRetryHandler(BackoffLimitedRetryHandler backoffHandler, S3Utils utils, public AWSRedirectionRetryHandler(BackoffLimitedRetryHandler backoffHandler, S3Utils utils) {
S3ParserFactory parserFactory, @Named("jclouds.http.max-redirects") int retryCountLimit) { super(backoffHandler);
super(backoffHandler, retryCountLimit);
this.utils = utils; this.utils = utils;
this.parserFactory = parserFactory;
} }
@Override @Override
@ -68,8 +62,8 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
} else { } else {
command.incrementRedirectCount(); command.incrementRedirectCount();
try { try {
AWSError error = utils.parseAWSErrorFromContent(parserFactory, command, response, AWSError error = utils.parseAWSErrorFromContent(command, response, new String(
new String(content)); content));
String host = error.getDetails().get(S3Constants.ENDPOINT); String host = error.getDetails().get(S3Constants.ENDPOINT);
if (host != null) { if (host != null) {
if (host.equals(command.getRequest().getEndpoint().getHost())) { if (host.equals(command.getRequest().getEndpoint().getHost())) {

View File

@ -24,11 +24,11 @@
package org.jclouds.aws.s3.handlers; package org.jclouds.aws.s3.handlers;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.aws.AWSResponseException; import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.domain.AWSError; import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.util.S3Utils; import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
@ -36,8 +36,6 @@ import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import javax.inject.Inject;
/** /**
* This will parse and set an appropriate exception on the command object. * This will parse and set an appropriate exception on the command object.
* *
@ -49,13 +47,11 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final S3ParserFactory parserFactory;
private final S3Utils utils; private final S3Utils utils;
@Inject @Inject
public ParseAWSErrorFromXmlContent(S3Utils utils, S3ParserFactory parserFactory) { public ParseAWSErrorFromXmlContent(S3Utils utils) {
this.utils = utils; this.utils = utils;
this.parserFactory = parserFactory;
} }
public void handleError(HttpCommand command, HttpResponse response) { public void handleError(HttpCommand command, HttpResponse response) {
@ -66,8 +62,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
if (content != null) { if (content != null) {
try { try {
if (content.indexOf('<') >= 0) { if (content.indexOf('<') >= 0) {
AWSError error = utils.parseAWSErrorFromContent(parserFactory, command, response, AWSError error = utils.parseAWSErrorFromContent(command, response, content);
content);
command.setException(new AWSResponseException(command, response, error)); command.setException(new AWSResponseException(command, response, error));
} else { } else {
command.setException(new HttpResponseException(command, response, content)); command.setException(new HttpResponseException(command, response, content));

View File

@ -29,17 +29,19 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.aws.domain.AWSError; import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature; import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.aws.s3.reference.S3Headers; import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.aws.s3.xml.S3ParserFactory; import org.jclouds.aws.xml.ErrorHandler;
import org.jclouds.blobstore.util.BlobStoreUtils; import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
import javax.inject.Inject;
/** /**
* Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests and responses. * Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests and responses.
@ -51,23 +53,29 @@ public class S3Utils extends BlobStoreUtils {
@Inject @Inject
RequestAuthorizeSignature signer; RequestAuthorizeSignature signer;
public AWSError parseAWSErrorFromContent(S3ParserFactory parserFactory, HttpCommand command, @Inject
HttpResponse response, InputStream content) throws HttpException { ParseSax.Factory factory;
AWSError error = parserFactory.createErrorParser().parse(content);
error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID)); @Inject
Provider<ErrorHandler> errorHandlerProvider;
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
InputStream content) throws HttpException {
AWSError error = (AWSError) factory.create(errorHandlerProvider.get()).parse(content);
if (error.getRequestId() == null)
error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID));
error.setRequestToken(response.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN)); error.setRequestToken(response.getFirstHeaderOrNull(S3Headers.REQUEST_TOKEN));
if ("SignatureDoesNotMatch".equals(error.getCode())) { if ("SignatureDoesNotMatch".equals(error.getCode())) {
error.setStringSigned(signer.createStringToSign(command.getRequest())); error.setStringSigned(signer.createStringToSign(command.getRequest()));
error.setSignature(signer.signString(error.getStringSigned())); error.setSignature(signer.signString(error.getStringSigned()));
} }
return error; return error;
} }
public AWSError parseAWSErrorFromContent(S3ParserFactory parserFactory, HttpCommand command, public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
HttpResponse response, String content) throws HttpException { String content) throws HttpException {
return parseAWSErrorFromContent(parserFactory, command, response, new ByteArrayInputStream( return parseAWSErrorFromContent(command, response, new ByteArrayInputStream(content
content.getBytes())); .getBytes()));
} }
public static String validateBucketName(String bucketName) { public static String validateBucketName(String bucketName) {

View File

@ -1,119 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.xml;
import java.util.List;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.xml.ErrorHandler;
import org.jclouds.http.functions.ParseSax;
import com.google.common.annotations.VisibleForTesting;
import javax.inject.Inject;
import javax.inject.Provider;
/**
* Creates Parsers needed to interpret S3 Server messages. This class uses guice assisted inject,
* which mandates the creation of many single-method interfaces. These interfaces are not intended
* for public api.
*
* @author Adrian Cole
*/
public class S3ParserFactory {
@Inject
private GenericParseFactory<List<BucketMetadata>> parseListAllMyBucketsFactory;
@VisibleForTesting
public static interface GenericParseFactory<T> {
ParseSax<T> create(ParseSax.HandlerWithResult<T> handler);
}
@Inject
Provider<ListAllMyBucketsHandler> ListAllMyBucketsHandlerprovider;
/**
* @return a parser used to handle {@link org.jclouds.aws.s3.commands.ListOwnedBuckets} responses
*/
public ParseSax<List<BucketMetadata>> createListBucketsParser() {
return parseListAllMyBucketsFactory.create(ListAllMyBucketsHandlerprovider.get());
}
@Inject
private GenericParseFactory<ListBucketResponse> parseListBucketFactory;
@Inject
Provider<ListBucketHandler> ListBucketHandlerprovider;
/**
* @return a parser used to handle {@link org.jclouds.aws.s3.commands.ListBucket} responses
*/
public ParseSax<ListBucketResponse> createListBucketParser() {
return parseListBucketFactory.create(ListBucketHandlerprovider.get());
}
@Inject
private GenericParseFactory<ObjectMetadata> parseCopyObjectFactory;
@Inject
Provider<CopyObjectHandler> copyObjectHandlerProvider;
/**
* @return a parser used to handle {@link org.jclouds.aws.s3.commands.CopyObject} responses
*/
public ParseSax<ObjectMetadata> createCopyObjectParser() {
return parseCopyObjectFactory.create(copyObjectHandlerProvider.get());
}
@Inject
private GenericParseFactory<AWSError> parseErrorFactory;
@Inject
Provider<ErrorHandler> errorHandlerProvider;
/**
* @return a parser used to handle error conditions.
*/
public ParseSax<AWSError> createErrorParser() {
return parseErrorFactory.create(errorHandlerProvider.get());
}
@Inject
private GenericParseFactory<AccessControlList> parseAccessControlListFactory;
@Inject
Provider<AccessControlListHandler> accessControlListHandlerProvider;
/**
* @return a parser used to handle {@link org.jclouds.aws.s3.commands.GetAccessControlList} responses
*/
public ParseSax<AccessControlList> createAccessControlListParser() {
return parseAccessControlListFactory.create(accessControlListHandlerProvider.get());
}
}

View File

@ -1,109 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.xml.config;
import java.util.List;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.xml.AccessControlListHandler;
import org.jclouds.aws.s3.xml.CopyObjectHandler;
import org.jclouds.aws.s3.xml.ListAllMyBucketsHandler;
import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.aws.xml.ErrorHandler;
import org.jclouds.command.ConfiguresResponseTransformer;
import org.jclouds.http.functions.ParseSax;
import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider;
/**
* Creates the factories needed to interpret S3 responses
*
* @author Adrian Cole
*/
@ConfiguresResponseTransformer
public class S3ParserModule extends AbstractModule {
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<AWSError>> errorTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<AWSError>>() {
};
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<List<BucketMetadata>>> listBucketsTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<List<BucketMetadata>>>() {
};
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<ListBucketResponse>> bucketTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<ListBucketResponse>>() {
};
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<ObjectMetadata>> objectMetadataTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<ObjectMetadata>>() {
};
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<AccessControlList>> accessControlListTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<AccessControlList>>() {
};
@Override
protected void configure() {
bindErrorHandler();
bindCallablesThatReturnParseResults();
bindParserImplementationsToReturnTypes();
}
protected void bindErrorHandler() {
bind(new TypeLiteral<ParseSax.HandlerWithResult<AWSError>>() {
}).to(ErrorHandler.class);
}
private void bindParserImplementationsToReturnTypes() {
bind(new TypeLiteral<ParseSax.HandlerWithResult<List<BucketMetadata>>>() {
}).to(ListAllMyBucketsHandler.class);
bind(new TypeLiteral<ParseSax.HandlerWithResult<ListBucketResponse>>() {
}).to(ListBucketHandler.class);
bind(new TypeLiteral<ParseSax.HandlerWithResult<ObjectMetadata>>() {
}).to(CopyObjectHandler.class);
bind(new TypeLiteral<ParseSax.HandlerWithResult<AccessControlList>>() {
}).to(AccessControlListHandler.class);
}
private void bindCallablesThatReturnParseResults() {
bind(listBucketsTypeLiteral).toProvider(
FactoryProvider.newFactory(listBucketsTypeLiteral,
new TypeLiteral<ParseSax<List<BucketMetadata>>>() {
}));
bind(bucketTypeLiteral).toProvider(
FactoryProvider.newFactory(bucketTypeLiteral,
new TypeLiteral<ParseSax<ListBucketResponse>>() {
}));
bind(objectMetadataTypeLiteral).toProvider(
FactoryProvider.newFactory(objectMetadataTypeLiteral,
new TypeLiteral<ParseSax<ObjectMetadata>>() {
}));
bind(accessControlListTypeLiteral).toProvider(
FactoryProvider.newFactory(accessControlListTypeLiteral,
new TypeLiteral<ParseSax<AccessControlList>>() {
}));
bind(errorTypeLiteral).toProvider(
FactoryProvider.newFactory(errorTypeLiteral, new TypeLiteral<ParseSax<AWSError>>() {
}));
}
}

View File

@ -1,28 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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 logic that assembles xml parsing callables.
* @author Adrian Cole
*/
package org.jclouds.aws.s3.xml.config;

View File

@ -1,65 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.functions;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.http.HttpException;
import org.jclouds.http.functions.ParseSax;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "s3.ErrorHandlerTest")
public class ErrorHandlerTest extends BaseHandlerTest {
public static final String errorFromAmazonIfYouDontRemoveTransferEncodingHeader = "<Error><Code>NotImplemented</Code><Message>A header you provided implies functionality that is not implemented</Message><Header>Transfer-Encoding</Header><RequestId>7C59925D75D15561</RequestId><HostId>fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb</HostId></Error>";
@Test
public void testErrorFromAmazonIfYouDontRemoveTransferEncodingHeader()
throws HttpException {
ParseSax<AWSError> parser = parserFactory.createErrorParser();
AWSError error = parser
.parse(IOUtils
.toInputStream(errorFromAmazonIfYouDontRemoveTransferEncodingHeader));
assertEquals(error.getCode(), "NotImplemented");
assertEquals(error.getMessage(),
"A header you provided implies functionality that is not implemented");
assertEquals(error.getDetails().get("Header"), "Transfer-Encoding");
assertEquals(error.getRequestId(), "7C59925D75D15561");
assertEquals(error.getDetails().get("HostId"),
"fbskVU51OZJg2yZS/wNIxoE2PmCf0ZqFd0iH6Vrzw0uKG3KmokswBytL/Bfp/GWb");
}
public static final String badRequestWhenSourceIsDestBucketOnCopy400 = "<Error><Code>InvalidRequest</Code><Message>The Source and Destination may not be the same when the MetadataDirective is Copy.</Message><RequestId>54C77CAF4D42474B</RequestId><HostId>SJecknEUUUx88/65VAKbCdKSOCkpuVTeu7ZG9in9x9NTNglGnoxdbALCfS4k/DUZ</HostId></Error>";
public static final String noSuchSourceKeyOrBucketOnCopy404 = "<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>null</Key><RequestId>9CCDF1DACA78B36F</RequestId><HostId>63cqk9YsTFBVfBfks840JVGsepPEdQM42mU+r7HN35sF4Nk5xAcWDEUPaQpK2eFU</HostId></Error>";
public static final String noSuchDestinationBucketOnCopy404 = "<Error><Code>NoSuchBucket</Code><Message>The specified bucketName does not exist</Message><BucketName>copydestination</BucketName><RequestId>4F0CF319C5535975</RequestId><HostId>hdZyHOm7VK+JI2UCdye3d6TVkKhRBIoWflldXVDTKbgipYlamy8HgPBzHrUAVQNJ</HostId></Error>";
public static final String badSign403 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<Error><Code>SignatureDoesNotMatch</Code><Message>The operation signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>47 45 54 0a 0a 0a 54 68 75 2c 20 31 39 20 4d 61 72 20 32 30 30 39 20 31 37 3a 34 38 3a 30 31 20 47 4d 54 0a 2f 61 64 72 69 61 6e 63 6f 6c 65 2e 73 33 2e 61 6d 61 7a 6f 6e 73 33 74 65 73 74 2e 66 69 6c 65 74 65 73 74 73 66 6f 72 61 64 72 69 61 6e 2f 66 69 6c 65</StringToSignBytes><RequestId>514AA22EB75A6E42</RequestId><HostId>H5nqnZkGjuKvB+seutvx5hnp1P+WAuC9c3Y7MdQCcYDr1TGwNX/mt+FHstK0pVld</HostId><SignatureProvided>Qm6Wss7e5e/eNXV50AxChH+xkLI=</SignatureProvided><StringToSign>GET\n"
+ "\n"
+ "\n"
+ "Thu, 19 Mar 2009 17:48:01 GMT\n"
+ "/adriancole.s3.amazons3test.filetestsforadrian/file</StringToSign><AWSAccessKeyId>0101100101001001</AWSAccessKeyId></Error>";
public static final String amazonHadAnError500 = "<Error><Code>InternalError</Code><Message>We encountered an internal error. Please try again.</Message><RequestId>EF6FA7A639CAFF15</RequestId><HostId>tBkX23mIeq2riHsNw2YShupMlZ9+iy3V/uN+lRhqCR4qHTE07ujFeyAUPTowvuH/</HostId></Error>";
}

View File

@ -1,77 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.functions;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.jclouds.http.functions.config.ParserModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "s3.S3ParserFactoryTest")
public class S3ParserFactoryTest {
Injector injector = null;
S3ParserFactory parserFactory = null;
@BeforeTest
void setUpInjector() {
injector = Guice.createInjector(new S3ParserModule(), new ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class);
}
@AfterTest
void tearDownInjector() {
parserFactory = null;
injector = null;
}
@Test
void testCreateListBucketsParser() {
assert parserFactory.createListBucketsParser() != null;
}
@Test
void testCreateListBucketParser() {
assert parserFactory.createListBucketParser() != null;
}
@Test
void testCreateCopyObjectParser() {
assert parserFactory.createCopyObjectParser() != null;
}
@Test
void testCreateErrorParser() {
assert parserFactory.createErrorParser() != null;
}
}

View File

@ -0,0 +1,157 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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 org.testng.Assert.assertEquals;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.reference.S3Constants;
import org.jclouds.aws.s3.reference.S3Headers;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.Jsr330;
import org.jclouds.util.Utils;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests parsing of S3 responses
*
* @author Adrian Cole
*/
@Test(groups = { "unit" }, testName = "s3.S3UtilsTest")
public class S3UtilsTest {
S3Utils utils = null;
private HttpResponse response;
private HttpCommand command;
@BeforeTest
protected void setUpInjector() {
Injector injector = Guice.createInjector(new ParserModule(), new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
"user");
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
.to("key");
}
});
utils = injector.getInstance(S3Utils.class);
response = new HttpResponse(URI.create("http://localhost")); // TODO: Get real object URL?
response.setStatusCode(400);
response.getHeaders().put(S3Headers.REQUEST_ID, "requestid");
response.getHeaders().put(S3Headers.REQUEST_TOKEN, "requesttoken");
command = new HttpCommand() {
public int getRedirectCount() {
return 0;
}
public int incrementRedirectCount() {
return 0;
}
public boolean isReplayable() {
return false;
}
public HttpRequest setHostAndPort(String host, int port) {
return null;
}
public HttpRequest setMethod(String method) {
return null;
}
public Exception getException() {
return null;
}
public int getFailureCount() {
return 0;
}
public HttpRequest getRequest() {
return null;
}
public int incrementFailureCount() {
return 0;
}
public void setException(Exception exception) {
}
};
}
@AfterTest
protected void tearDownInjector() {
utils = null;
}
@Test
public void testParseAWSErrorFromContentHttpCommandHttpResponseInputStream() {
InputStream content = getClass().getResourceAsStream("/error.xml");
AWSError error = utils.parseAWSErrorFromContent(command, response, content);
validate(error);
}
private void validate(AWSError error) {
assertEquals(error.getCode(), "NoSuchKey");
assertEquals(error.getMessage(), "The resource you requested does not exist");
assertEquals(error.getRequestToken(), "requesttoken");
assertEquals(error.getRequestId(), "4442587FB7D0A2F9");
assertEquals(error.getDetails().get("Resource"), "/mybucket/myfoto.jpg");
}
@Test
public void testParseAWSErrorFromContentHttpCommandHttpResponseString() throws HttpException,
IOException {
InputStream content = getClass().getResourceAsStream("/error.xml");
AWSError error = utils.parseAWSErrorFromContent(command, response, Utils
.toStringAndClose(content));
validate(error);
}
@Test
public void testValidateBucketName() {
// TODO
}
}

View File

@ -21,7 +21,7 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.functions; package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
@ -30,7 +30,9 @@ import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.AccessControlList; import org.jclouds.aws.s3.domain.AccessControlList;
import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI; import org.jclouds.aws.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.aws.s3.domain.AccessControlList.Permission; import org.jclouds.aws.s3.domain.AccessControlList.Permission;
import org.jclouds.aws.s3.xml.AccessControlListHandler;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -39,8 +41,10 @@ public class AccessControlListHandlerTest extends BaseHandlerTest {
public static final String aclOwnerOnly = "<AccessControlPolicy xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>"; public static final String aclOwnerOnly = "<AccessControlPolicy xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>";
public static final String aclExtreme = "<AccessControlPolicy xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI></Grantee><Permission>WRITE</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI></Grantee><Permission>READ_ACP</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Grantee><Permission>WRITE</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI></Grantee><Permission>WRITE_ACP</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AllUsers</URI></Grantee><Permission>READ</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI></Grantee><Permission>READ</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/s3/LogDelivery</URI></Grantee><Permission>WRITE</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Grantee><Permission>READ</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>"; public static final String aclExtreme = "<AccessControlPolicy xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Owner><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Owner><AccessControlList><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI></Grantee><Permission>WRITE</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI></Grantee><Permission>READ_ACP</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Grantee><Permission>WRITE</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI></Grantee><Permission>WRITE_ACP</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AllUsers</URI></Grantee><Permission>READ</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI></Grantee><Permission>READ</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"Group\"><URI>http://acs.amazonaws.com/groups/s3/LogDelivery</URI></Grantee><Permission>WRITE</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Grantee><Permission>READ</Permission></Grant><Grant><Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"CanonicalUser\"><ID>1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c</ID><DisplayName>jamesmurty</DisplayName></Grantee><Permission>FULL_CONTROL</Permission></Grant></AccessControlList></AccessControlPolicy>";
@SuppressWarnings("unchecked")
ParseSax<AccessControlList> createParser() { ParseSax<AccessControlList> createParser() {
ParseSax<AccessControlList> parser = parserFactory.createAccessControlListParser(); ParseSax<AccessControlList> parser = (ParseSax<AccessControlList>) factory.create(injector
.getInstance(AccessControlListHandler.class));
return parser; return parser;
} }

View File

@ -21,15 +21,16 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.functions; package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.ListBucketResponse; import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@Test(groups = "unit", testName = "s3.ListBucketHandlerTest") @Test(groups = "unit", testName = "s3.ListBucketHandlerTest")
@ -37,9 +38,10 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
public static final String listBucketWithPrefixAppsSlash = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adriancole.org.jclouds.aws.s3.amazons3testdelimiter</Name><Prefix>apps/</Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>apps/0</Key><LastModified>2009-05-07T18:27:08.000Z</LastModified><ETag>&quot;c82e6a0025c31c5de5947fda62ac51ab&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/1</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;944fab2c5a9a6bacf07db5e688310d7a&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/2</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;a227b8888045c8fd159fb495214000f0&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/3</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;c9caa76c3dec53e2a192608ce73eef03&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/4</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;1ce5d0dcc6154a647ea90c7bdf82a224&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/5</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;79433524d87462ee05708a8ef894ed55&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/6</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;dd00a060b28ddca8bc5a21a49e306f67&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/7</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;8cd06eca6e819a927b07a285d750b100&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/8</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;174495094d0633b92cbe46603eee6bad&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/9</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;cd8a19b26fea8a827276df0ad11c580d&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>"; public static final String listBucketWithPrefixAppsSlash = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adriancole.org.jclouds.aws.s3.amazons3testdelimiter</Name><Prefix>apps/</Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>apps/0</Key><LastModified>2009-05-07T18:27:08.000Z</LastModified><ETag>&quot;c82e6a0025c31c5de5947fda62ac51ab&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/1</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;944fab2c5a9a6bacf07db5e688310d7a&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/2</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;a227b8888045c8fd159fb495214000f0&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/3</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;c9caa76c3dec53e2a192608ce73eef03&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/4</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;1ce5d0dcc6154a647ea90c7bdf82a224&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/5</Key><LastModified>2009-05-07T18:27:09.000Z</LastModified><ETag>&quot;79433524d87462ee05708a8ef894ed55&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/6</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;dd00a060b28ddca8bc5a21a49e306f67&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/7</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;8cd06eca6e819a927b07a285d750b100&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/8</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;174495094d0633b92cbe46603eee6bad&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>apps/9</Key><LastModified>2009-05-07T18:27:10.000Z</LastModified><ETag>&quot;cd8a19b26fea8a827276df0ad11c580d&quot;</ETag><Size>8</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>";
public static final String listBucketWithSlashDelimiterAndCommonPrefixApps = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"> <Delimiter>/</Delimiter> <CommonPrefixes><Prefix>apps/</Prefix></CommonPrefixes></ListBucketResult>"; public static final String listBucketWithSlashDelimiterAndCommonPrefixApps = "<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"> <Delimiter>/</Delimiter> <CommonPrefixes><Prefix>apps/</Prefix></CommonPrefixes></ListBucketResult>";
@BeforeMethod @SuppressWarnings("unchecked")
ParseSax<ListBucketResponse> createParser() { ParseSax<ListBucketResponse> createParser() {
ParseSax<ListBucketResponse> parser = parserFactory.createListBucketParser(); ParseSax<ListBucketResponse> parser = (ParseSax<ListBucketResponse>) factory.create(injector
.getInstance(ListBucketHandler.class));
return parser; return parser;
} }
@ -56,7 +58,8 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
@Test @Test
public void testListMyBucketsWithPrefixAppsSlash() throws HttpException { public void testListMyBucketsWithPrefixAppsSlash() throws HttpException {
ListBucketResponse bucket = createParser().parse(IOUtils.toInputStream(listBucketWithPrefixAppsSlash)); ListBucketResponse bucket = createParser().parse(
IOUtils.toInputStream(listBucketWithPrefixAppsSlash));
assertEquals(bucket.getPrefix(), "apps/"); assertEquals(bucket.getPrefix(), "apps/");
assertEquals(bucket.getMaxResults(), 1000); assertEquals(bucket.getMaxResults(), 1000);
assert bucket.getMarker() == null; assert bucket.getMarker() == null;

View File

@ -39,8 +39,6 @@ import org.jclouds.aws.s3.domain.BucketMetadata;
import org.jclouds.aws.s3.domain.CanonicalUser; import org.jclouds.aws.s3.domain.CanonicalUser;
import org.jclouds.aws.s3.domain.ListBucketResponse; import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.domain.ObjectMetadata; import org.jclouds.aws.s3.domain.ObjectMetadata;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
@ -62,32 +60,33 @@ import com.google.inject.Injector;
@Test(groups = { "performance" }, testName = "s3.S3ParserTest") @Test(groups = { "performance" }, testName = "s3.S3ParserTest")
public class S3ParserTest extends PerformanceTest { public class S3ParserTest extends PerformanceTest {
Injector injector = null; Injector injector = null;
ParseSax.Factory factory;
public static final String listAllMyBucketsResultOn200 = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket><Bucket><Name>adrianjbosstest2</Name><CreationDate>2009-03-12T02:00:09.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
S3ParserFactory parserFactory = null;
@BeforeTest @BeforeTest
protected void setUpInjector() { protected void setUpInjector() {
injector = Guice.createInjector(new ParserModule(), new S3ParserModule()); injector = Guice.createInjector(new ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class); factory = injector.getInstance(ParseSax.Factory.class);
assert parserFactory != null; assert factory != null;
} }
@AfterTest @AfterTest
protected void tearDownInjector() { protected void tearDownInjector() {
parserFactory = null; factory = null;
injector = null; injector = null;
} }
public static final String listAllMyBucketsResultOn200 = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket><Bucket><Name>adrianjbosstest2</Name><CreationDate>2009-03-12T02:00:09.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
@Test @Test
void testParseListAllMyBucketsSerialResponseTime() throws HttpException { void testParseListAllMyBucketsSerialResponseTime() throws HttpException {
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)
runParseListAllMyBuckets(); runParseListAllMyBuckets();
} }
@SuppressWarnings("unchecked")
private List<BucketMetadata> runParseListAllMyBuckets() throws HttpException { private List<BucketMetadata> runParseListAllMyBuckets() throws HttpException {
return parserFactory.createListBucketsParser().parse( return (List<BucketMetadata>) factory.create(
injector.getInstance(ListAllMyBucketsHandler.class)).parse(
IOUtils.toInputStream(listAllMyBucketsResultOn200)); IOUtils.toInputStream(listAllMyBucketsResultOn200));
} }
@ -148,15 +147,15 @@ public class S3ParserTest extends PerformanceTest {
} }
private ListBucketResponse runParseListContainerResult() throws HttpException { private ListBucketResponse runParseListContainerResult() throws HttpException {
ParseSax<ListBucketResponse> parser = parserFactory.createListBucketParser(); return (ListBucketResponse) factory.create(injector.getInstance(ListBucketHandler.class))
return parser.parse(IOUtils.toInputStream(listContainerResult)); .parse(IOUtils.toInputStream(listContainerResult));
} }
public static final String successfulCopyObject200 = "<CopyObjectResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><LastModified>2009-03-19T13:23:27.000Z</LastModified><ETag>\"92836a3ea45a6984d1b4d23a747d46bb\"</ETag></CopyObjectResult>"; public static final String successfulCopyObject200 = "<CopyObjectResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><LastModified>2009-03-19T13:23:27.000Z</LastModified><ETag>\"92836a3ea45a6984d1b4d23a747d46bb\"</ETag></CopyObjectResult>";
private ObjectMetadata runParseCopyObjectResult() throws HttpException { private ObjectMetadata runParseCopyObjectResult() throws HttpException {
ParseSax<ObjectMetadata> parser = parserFactory.createCopyObjectParser(); return (ObjectMetadata) factory.create(injector.getInstance(CopyObjectHandler.class)).parse(
return parser.parse(IOUtils.toInputStream(successfulCopyObject200)); IOUtils.toInputStream(successfulCopyObject200));
} }
public void testCanParseCopyObjectResult() throws HttpException, UnsupportedEncodingException { public void testCanParseCopyObjectResult() throws HttpException, UnsupportedEncodingException {

View File

@ -1,63 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.blob.xml;
import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.http.functions.ParseSax;
import javax.inject.Inject;
import javax.inject.Provider;
/**
* Creates Parsers needed to interpret Azure Blob Service messages. This class uses guice assisted
* inject, which mandates the creation of many single-method interfaces. These interfaces are not
* intended for public api.
*
* @author Adrian Cole
*/
public class AzureBlobParserFactory extends AzureStorageParserFactory {
@Inject
private GenericParseFactory<BoundedList<ContainerMetadata>> parseContainerMetadataListFactory;
@Inject
Provider<AccountNameEnumerationResultsHandler> containerMetaListHandlerProvider;
public ParseSax<BoundedList<ContainerMetadata>> createContainerMetadataListParser() {
return parseContainerMetadataListFactory.create(containerMetaListHandlerProvider.get());
}
@Inject
private GenericParseFactory<ListBlobsResponse> parseListBlobsResponseFactory;
@Inject
Provider<ContainerNameEnumerationResultsHandler> listBlobsResponseHandlerProvider;
public ParseSax<ListBlobsResponse> createListBlobsResponseParser() {
return parseListBlobsResponseFactory.create(listBlobsResponseHandlerProvider.get());
}
}

View File

@ -1,74 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.blob.xml.config;
import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.xml.AccountNameEnumerationResultsHandler;
import org.jclouds.azure.storage.blob.xml.ContainerNameEnumerationResultsHandler;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.azure.storage.xml.config.AzureStorageParserModule;
import org.jclouds.command.ConfiguresResponseTransformer;
import org.jclouds.http.functions.ParseSax;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider;
/**
* Creates the factories needed to interpret Azure Blob Service responses
*
* @author Adrian Cole
*/
@ConfiguresResponseTransformer
public class AzureBlobParserModule extends AzureStorageParserModule {
protected final TypeLiteral<AzureStorageParserFactory.GenericParseFactory<BoundedList<ContainerMetadata>>> accountNameEnumerationResultsHandler = new TypeLiteral<AzureStorageParserFactory.GenericParseFactory<BoundedList<ContainerMetadata>>>() {
};
protected final TypeLiteral<AzureStorageParserFactory.GenericParseFactory<ListBlobsResponse>> containerNameEnumerationResultsHandler = new TypeLiteral<AzureStorageParserFactory.GenericParseFactory<ListBlobsResponse>>() {
};
@Override
protected void bindParserImplementationsToReturnTypes() {
super.bindParserImplementationsToReturnTypes();
bind(new TypeLiteral<ParseSax.HandlerWithResult<BoundedList<ContainerMetadata>>>() {
}).to(AccountNameEnumerationResultsHandler.class);
bind(new TypeLiteral<ParseSax.HandlerWithResult<ListBlobsResponse>>() {
}).to(ContainerNameEnumerationResultsHandler.class);
}
@Override
protected void bindCallablesThatReturnParseResults() {
super.bindCallablesThatReturnParseResults();
bind(accountNameEnumerationResultsHandler).toProvider(
FactoryProvider.newFactory(accountNameEnumerationResultsHandler,
new TypeLiteral<ParseSax<BoundedList<ContainerMetadata>>>() {
}));
bind(containerNameEnumerationResultsHandler).toProvider(
FactoryProvider.newFactory(containerNameEnumerationResultsHandler,
new TypeLiteral<ParseSax<ListBlobsResponse>>() {
}));
}
}

View File

@ -32,7 +32,9 @@ import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
import org.jclouds.azure.storage.domain.ArrayBoundedList; import org.jclouds.azure.storage.domain.ArrayBoundedList;
import org.jclouds.azure.storage.domain.BoundedList; import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.util.DateService;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -45,6 +47,17 @@ import com.google.common.collect.ImmutableList;
@Test(groups = "unit", testName = "azureblob.AccountNameEnumerationResultsHandlerTest") @Test(groups = "unit", testName = "azureblob.AccountNameEnumerationResultsHandlerTest")
public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest { public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
private DateService dateService;
@BeforeTest
@Override
protected void setUpInjector() {
super.setUpInjector();
dateService = injector.getInstance(DateService.class);
assert dateService != null;
}
@SuppressWarnings("unchecked")
public void testApplyInputStream() { public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/test_list_containers.xml"); InputStream is = getClass().getResourceAsStream("/test_list_containers.xml");
BoundedList<ContainerMetadata> list = new ArrayBoundedList<ContainerMetadata>(ImmutableList BoundedList<ContainerMetadata> list = new ArrayBoundedList<ContainerMetadata>(ImmutableList
@ -60,12 +73,14 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
.fromHexString("0x8CACB9BD7BACAC3")) .fromHexString("0x8CACB9BD7BACAC3"))
), null, null, 3, "video"); ), null, null, 3, "video");
ParseSax<BoundedList<ContainerMetadata>> parser = parserFactory
.createContainerMetadataListParser(); BoundedList<ContainerMetadata> result = (BoundedList<ContainerMetadata>) factory.create(
BoundedList<ContainerMetadata> result = parser.parse(is); injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list); assertEquals(result, list);
} }
@SuppressWarnings("unchecked")
public void testApplyInputStreamWithOptions() { public void testApplyInputStreamWithOptions() {
InputStream is = getClass().getResourceAsStream("/test_list_containers_options.xml"); InputStream is = getClass().getResourceAsStream("/test_list_containers_options.xml");
BoundedList<ContainerMetadata> list = new ArrayBoundedList<ContainerMetadata>(ImmutableList BoundedList<ContainerMetadata> list = new ArrayBoundedList<ContainerMetadata>(ImmutableList
@ -81,9 +96,8 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
.fromHexString("0x8CACB9BD7BACAC3")) .fromHexString("0x8CACB9BD7BACAC3"))
), "prefix", "marker", 1, "video"); ), "prefix", "marker", 1, "video");
ParseSax<BoundedList<ContainerMetadata>> parser = parserFactory BoundedList<ContainerMetadata> result = (BoundedList<ContainerMetadata>) factory.create(
.createContainerMetadataListParser(); injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
BoundedList<ContainerMetadata> result = parser.parse(is);
assertEquals(result, list); assertEquals(result, list);
} }
} }

View File

@ -1,58 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.blob.xml;
import org.jclouds.azure.storage.blob.xml.AzureBlobParserFactory;
import org.jclouds.azure.storage.blob.xml.config.AzureBlobParserModule;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.DateService;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BaseHandlerTest {
protected AzureBlobParserFactory parserFactory = null;
protected DateService dateService = null;
private Injector injector;
@BeforeTest
protected void setUpInjector() {
injector = Guice.createInjector(new AzureBlobParserModule(), new ParserModule());
parserFactory = injector.getInstance(AzureBlobParserFactory.class);
dateService = injector.getInstance(DateService.class);
assert parserFactory != null;
}
@AfterTest
protected void tearDownInjector() {
parserFactory = null;
dateService = null;
injector = null;
}
}

View File

@ -31,8 +31,11 @@ import java.net.URI;
import org.jclouds.azure.storage.blob.domain.ArrayListBlobsResponse; import org.jclouds.azure.storage.blob.domain.ArrayListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.BlobMetadata; import org.jclouds.azure.storage.blob.domain.BlobMetadata;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse; import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.util.DateService;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -44,7 +47,17 @@ import com.google.common.collect.ImmutableList;
*/ */
@Test(groups = "unit", testName = "azureblob.ContainerNameEnumerationResultsHandlerTest") @Test(groups = "unit", testName = "azureblob.ContainerNameEnumerationResultsHandlerTest")
public class ContainerNameEnumerationResultsHandlerTest extends BaseHandlerTest { public class ContainerNameEnumerationResultsHandlerTest extends BaseHandlerTest {
private DateService dateService;
@BeforeTest
@Override
protected void setUpInjector() {
super.setUpInjector();
dateService = injector.getInstance(DateService.class);
assert dateService != null;
}
@SuppressWarnings("unchecked")
public void testApplyInputStream() { public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/test_list_blobs.xml"); InputStream is = getClass().getResourceAsStream("/test_list_blobs.xml");
ListBlobsResponse list = new ArrayListBlobsResponse(URI ListBlobsResponse list = new ArrayListBlobsResponse(URI
@ -65,8 +78,10 @@ public class ContainerNameEnumerationResultsHandlerTest extends BaseHandlerTest
"text/plain; charset=UTF-8", null, null, null) "text/plain; charset=UTF-8", null, null, null)
), null, null, 4, "newblob2.txt", null, "myfolder/"); ), null, null, 4, "newblob2.txt", null, "myfolder/");
ParseSax<ListBlobsResponse> parser = parserFactory.createListBlobsResponseParser();
ListBlobsResponse result = parser.parse(is); BoundedList<ListBlobsResponse> result = (BoundedList<ListBlobsResponse>) factory.create(
injector.getInstance(ContainerNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list); assertEquals(result, list);
} }
} }

View File

@ -24,11 +24,11 @@
package org.jclouds.azure.storage.handlers; package org.jclouds.azure.storage.handlers;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.azure.storage.AzureStorageResponseException; import org.jclouds.azure.storage.AzureStorageResponseException;
import org.jclouds.azure.storage.domain.AzureStorageError; import org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.azure.storage.util.AzureStorageUtils; import org.jclouds.azure.storage.util.AzureStorageUtils;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
@ -36,8 +36,6 @@ import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import javax.inject.Inject;
/** /**
* This will parse and set an appropriate exception on the command object. * This will parse and set an appropriate exception on the command object.
* *
@ -49,13 +47,11 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final AzureStorageParserFactory parserFactory;
private final AzureStorageUtils utils; private final AzureStorageUtils utils;
@Inject @Inject
public ParseAzureStorageErrorFromXmlContent(AzureStorageUtils utils, AzureStorageParserFactory parserFactory) { public ParseAzureStorageErrorFromXmlContent(AzureStorageUtils utils) {
this.utils = utils; this.utils = utils;
this.parserFactory = parserFactory;
} }
public void handleError(HttpCommand command, HttpResponse response) { public void handleError(HttpCommand command, HttpResponse response) {
@ -66,8 +62,8 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
if (content != null) { if (content != null) {
try { try {
if (content.indexOf('<') >= 0) { if (content.indexOf('<') >= 0) {
AzureStorageError error = utils.parseAzureStorageErrorFromContent(parserFactory, command, response, AzureStorageError error = utils.parseAzureStorageErrorFromContent(command,
content); response, content);
command.setException(new AzureStorageResponseException(command, response, error)); command.setException(new AzureStorageResponseException(command, response, error));
} else { } else {
command.setException(new HttpResponseException(command, response, content)); command.setException(new HttpResponseException(command, response, content));

View File

@ -26,15 +26,17 @@ package org.jclouds.azure.storage.util;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.azure.storage.domain.AzureStorageError; import org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication; import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
import org.jclouds.azure.storage.reference.AzureStorageHeaders; import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory; import org.jclouds.azure.storage.xml.ErrorHandler;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseSax;
import javax.inject.Inject;
/** /**
* Encryption, Hashing, and IO Utilities needed to sign and verify Azure Storage requests and * Encryption, Hashing, and IO Utilities needed to sign and verify Azure Storage requests and
@ -46,11 +48,17 @@ public class AzureStorageUtils {
@Inject @Inject
SharedKeyAuthentication signer; SharedKeyAuthentication signer;
@Inject
ParseSax.Factory factory;
public AzureStorageError parseAzureStorageErrorFromContent( @Inject
AzureStorageParserFactory parserFactory, HttpCommand command, HttpResponse response, Provider<ErrorHandler> errorHandlerProvider;
InputStream content) throws HttpException {
AzureStorageError error = parserFactory.createErrorParser().parse(content); public AzureStorageError parseAzureStorageErrorFromContent(HttpCommand command,
HttpResponse response, InputStream content) throws HttpException {
AzureStorageError error = (AzureStorageError) factory.create(errorHandlerProvider.get())
.parse(content);
error.setRequestId(response.getFirstHeaderOrNull(AzureStorageHeaders.REQUEST_ID)); error.setRequestId(response.getFirstHeaderOrNull(AzureStorageHeaders.REQUEST_ID));
if ("AuthenticationFailed".equals(error.getCode())) { if ("AuthenticationFailed".equals(error.getCode())) {
error.setStringSigned(signer.createStringToSign(command.getRequest())); error.setStringSigned(signer.createStringToSign(command.getRequest()));
@ -60,11 +68,10 @@ public class AzureStorageUtils {
} }
public AzureStorageError parseAzureStorageErrorFromContent( public AzureStorageError parseAzureStorageErrorFromContent(HttpCommand command,
AzureStorageParserFactory parserFactory, HttpCommand command, HttpResponse response, HttpResponse response, String content) throws HttpException {
String content) throws HttpException { return parseAzureStorageErrorFromContent(command, response, new ByteArrayInputStream(content
return parseAzureStorageErrorFromContent(parserFactory, command, response, .getBytes()));
new ByteArrayInputStream(content.getBytes()));
} }
} }

View File

@ -1,60 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.xml;
import org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.http.functions.ParseSax;
import com.google.common.annotations.VisibleForTesting;
import javax.inject.Inject;
import javax.inject.Provider;
/**
* Creates Parsers needed to interpret Azure Storage Service messages. This class uses guice
* assisted inject, which mandates the creation of many single-method interfaces. These interfaces
* are not intended for public api.
*
* @author Adrian Cole
*/
public class AzureStorageParserFactory {
@VisibleForTesting
public static interface GenericParseFactory<T> {
ParseSax<T> create(ParseSax.HandlerWithResult<T> handler);
}
@Inject
private GenericParseFactory<AzureStorageError> parseErrorFactory;
@Inject
Provider<ErrorHandler> errorHandlerProvider;
/**
* @return a parser used to handle error conditions.
*/
public ParseSax<AzureStorageError> createErrorParser() {
return parseErrorFactory.create(errorHandlerProvider.get());
}
}

View File

@ -1,68 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.xml.config;
import org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.azure.storage.xml.ErrorHandler;
import org.jclouds.command.ConfiguresResponseTransformer;
import org.jclouds.http.functions.ParseSax;
import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider;
/**
* Creates the factories needed to interpret AzureStorage responses
*
* @author Adrian Cole
*/
@ConfiguresResponseTransformer
public class AzureStorageParserModule extends AbstractModule {
protected final TypeLiteral<AzureStorageParserFactory.GenericParseFactory<AzureStorageError>> errorTypeLiteral = new TypeLiteral<AzureStorageParserFactory.GenericParseFactory<AzureStorageError>>() {
};
@Override
protected void configure() {
bindErrorHandler();
bindCallablesThatReturnParseResults();
bindParserImplementationsToReturnTypes();
}
protected void bindParserImplementationsToReturnTypes() {
}
protected void bindCallablesThatReturnParseResults() {
bind(errorTypeLiteral).toProvider(
FactoryProvider.newFactory(errorTypeLiteral,
new TypeLiteral<ParseSax<AzureStorageError>>() {
}));
}
protected void bindErrorHandler() {
bind(new TypeLiteral<ParseSax.HandlerWithResult<AzureStorageError>>() {
}).to(ErrorHandler.class);
}
}

View File

@ -1,57 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.xml;
import org.jclouds.azure.storage.xml.config.AzureStorageParserModule;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.DateService;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BaseHandlerTest {
protected AzureStorageParserFactory parserFactory = null;
protected DateService dateService = null;
private Injector injector;
@BeforeTest
protected void setUpInjector() {
injector = Guice.createInjector(new AzureStorageParserModule(), new ParserModule());
parserFactory = injector.getInstance(AzureStorageParserFactory.class);
dateService = injector.getInstance(DateService.class);
assert parserFactory != null;
}
@AfterTest
protected void tearDownInjector() {
parserFactory = null;
dateService = null;
injector = null;
}
}

View File

@ -28,6 +28,7 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream; import java.io.InputStream;
import org.jclouds.azure.storage.domain.AzureStorageError; import org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -39,9 +40,16 @@ import org.testng.annotations.Test;
@Test(groups = "unit", testName = "azurestorage.ErrorHandlerTest") @Test(groups = "unit", testName = "azurestorage.ErrorHandlerTest")
public class ErrorHandlerTest extends BaseHandlerTest { public class ErrorHandlerTest extends BaseHandlerTest {
@SuppressWarnings("unchecked")
ParseSax<AzureStorageError> createParser() {
ParseSax<AzureStorageError> parser = (ParseSax<AzureStorageError>) factory.create(injector
.getInstance(ErrorHandler.class));
return parser;
}
public void testApplyInputStream() { public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/test_error.xml"); InputStream is = getClass().getResourceAsStream("/test_error.xml");
ParseSax<AzureStorageError> parser = parserFactory.createErrorParser(); ParseSax<AzureStorageError> parser = createParser();
AzureStorageError result = parser.parse(is); AzureStorageError result = parser.parse(is);
assertEquals(result.getCode(), "AuthenticationFailed"); assertEquals(result.getCode(), "AuthenticationFailed");
} }

View File

@ -1,52 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.queue.xml;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.http.functions.ParseSax;
import javax.inject.Inject;
import javax.inject.Provider;
/**
* Creates Parsers needed to interpret Azure Queue Service messages. This class uses guice assisted
* inject, which mandates the creation of many single-method interfaces. These interfaces are not
* intended for public api.
*
* @author Adrian Cole
*/
public class AzureQueueParserFactory extends AzureStorageParserFactory {
@Inject
private GenericParseFactory<BoundedList<QueueMetadata>> parseContainerMetadataListFactory;
@Inject
Provider<AccountNameEnumerationResultsHandler> containerMetaListHandlerProvider;
public ParseSax<BoundedList<QueueMetadata>> createContainerMetadataListParser() {
return parseContainerMetadataListFactory.create(containerMetaListHandlerProvider.get());
}
}

View File

@ -1,63 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.queue.xml.config;
import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.azure.storage.queue.xml.AccountNameEnumerationResultsHandler;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.azure.storage.xml.config.AzureStorageParserModule;
import org.jclouds.command.ConfiguresResponseTransformer;
import org.jclouds.http.functions.ParseSax;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider;
/**
* Creates the factories needed to interpret Azure Queue Service responses
*
* @author Adrian Cole
*/
@ConfiguresResponseTransformer
public class AzureQueueParserModule extends AzureStorageParserModule {
protected final TypeLiteral<AzureStorageParserFactory.GenericParseFactory<BoundedList<QueueMetadata>>> accountNameEnumerationResultsHandler = new TypeLiteral<AzureStorageParserFactory.GenericParseFactory<BoundedList<QueueMetadata>>>() {
};
@Override
protected void bindParserImplementationsToReturnTypes() {
super.bindParserImplementationsToReturnTypes();
bind(new TypeLiteral<ParseSax.HandlerWithResult<BoundedList<QueueMetadata>>>() {
}).to(AccountNameEnumerationResultsHandler.class);
}
@Override
protected void bindCallablesThatReturnParseResults() {
super.bindCallablesThatReturnParseResults();
bind(accountNameEnumerationResultsHandler).toProvider(
FactoryProvider.newFactory(accountNameEnumerationResultsHandler,
new TypeLiteral<ParseSax<BoundedList<QueueMetadata>>>() {
}));
}
}

View File

@ -31,7 +31,7 @@ import java.net.URI;
import org.jclouds.azure.storage.domain.ArrayBoundedList; import org.jclouds.azure.storage.domain.ArrayBoundedList;
import org.jclouds.azure.storage.domain.BoundedList; import org.jclouds.azure.storage.domain.BoundedList;
import org.jclouds.azure.storage.queue.domain.QueueMetadata; import org.jclouds.azure.storage.queue.domain.QueueMetadata;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.BaseHandlerTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -44,6 +44,7 @@ import com.google.common.collect.ImmutableList;
@Test(groups = "unit", testName = "azurequeue.AccountNameEnumerationResultsHandlerTest") @Test(groups = "unit", testName = "azurequeue.AccountNameEnumerationResultsHandlerTest")
public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest { public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
@SuppressWarnings("unchecked")
public void testApplyInputStream() { public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/test_list_queues.xml"); InputStream is = getClass().getResourceAsStream("/test_list_queues.xml");
BoundedList<QueueMetadata> list = new ArrayBoundedList<QueueMetadata>(ImmutableList.of( BoundedList<QueueMetadata> list = new ArrayBoundedList<QueueMetadata>(ImmutableList.of(
@ -51,21 +52,22 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
new QueueMetadata("q2", URI.create("http://myaccount.queue.core.windows.net/q2")), new QueueMetadata("q2", URI.create("http://myaccount.queue.core.windows.net/q2")),
new QueueMetadata("q3", URI.create("http://myaccount.queue.core.windows.net/q3"))), new QueueMetadata("q3", URI.create("http://myaccount.queue.core.windows.net/q3"))),
"q", null, 3, "q4"); "q", null, 3, "q4");
ParseSax<BoundedList<QueueMetadata>> parser = parserFactory BoundedList<QueueMetadata> result = (BoundedList<QueueMetadata>) factory.create(
.createContainerMetadataListParser(); injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
BoundedList<QueueMetadata> result = parser.parse(is);
assertEquals(result, list); assertEquals(result, list);
} }
@SuppressWarnings("unchecked")
public void testApplyInputStreamWithOptions() { public void testApplyInputStreamWithOptions() {
InputStream is = getClass().getResourceAsStream("/test_list_queues_options.xml"); InputStream is = getClass().getResourceAsStream("/test_list_queues_options.xml");
BoundedList<QueueMetadata> list = new ArrayBoundedList<QueueMetadata>(ImmutableList.of( BoundedList<QueueMetadata> list = new ArrayBoundedList<QueueMetadata>(ImmutableList.of(
new QueueMetadata("q4", URI.create("http://myaccount.queue.core.windows.net/q4")), new QueueMetadata("q4", URI.create("http://myaccount.queue.core.windows.net/q4")),
new QueueMetadata("q5", URI.create("http://myaccount.queue.core.windows.net/q5"))), new QueueMetadata("q5", URI.create("http://myaccount.queue.core.windows.net/q5"))),
"q", "q4", 3, null); "q", "q4", 3, null);
ParseSax<BoundedList<QueueMetadata>> parser = parserFactory
.createContainerMetadataListParser(); BoundedList<QueueMetadata> result = (BoundedList<QueueMetadata>) factory.create(
BoundedList<QueueMetadata> result = parser.parse(is); injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list); assertEquals(result, list);
} }
} }

View File

@ -1,58 +0,0 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* 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.azure.storage.queue.xml;
import org.jclouds.azure.storage.queue.xml.AzureQueueParserFactory;
import org.jclouds.azure.storage.queue.xml.config.AzureQueueParserModule;
import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.util.DateService;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BaseHandlerTest {
protected AzureQueueParserFactory parserFactory = null;
protected DateService dateService = null;
private Injector injector;
@BeforeTest
protected void setUpInjector() {
injector = Guice.createInjector(new AzureQueueParserModule(), new ParserModule());
parserFactory = injector.getInstance(AzureQueueParserFactory.class);
dateService = injector.getInstance(DateService.class);
assert parserFactory != null;
}
@AfterTest
protected void tearDownInjector() {
parserFactory = null;
dateService = null;
injector = null;
}
}

View File

@ -24,17 +24,17 @@
package org.jclouds.http.handlers; package org.jclouds.http.handlers;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.TransformingHttpCommand; import org.jclouds.http.TransformingHttpCommand;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;
/** /**
* Allow replayable request to be retried a limited number of times, and impose an exponential * Allow replayable request to be retried a limited number of times, and impose an exponential
* back-off delay before returning. * back-off delay before returning.
@ -76,16 +76,13 @@ import javax.inject.Named;
* @author James Murty * @author James Murty
*/ */
public class BackoffLimitedRetryHandler implements HttpRetryHandler { public class BackoffLimitedRetryHandler implements HttpRetryHandler {
private final int retryCountLimit; @Inject(optional = true)
@Named(HttpConstants.PROPERTY_HTTP_MAX_RETRIES)
private int retryCountLimit = 5;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Inject
public BackoffLimitedRetryHandler(@Named("jclouds.http.max-retries") int retryCountLimit) {
this.retryCountLimit = retryCountLimit;
}
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
IOUtils.closeQuietly(response.getContent()); IOUtils.closeQuietly(response.getContent());

View File

@ -23,6 +23,8 @@
*/ */
package org.jclouds.http.handlers; package org.jclouds.http.handlers;
import javax.inject.Inject;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
@ -31,7 +33,6 @@ import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import javax.inject.Inject;
/** /**
* Delegates to {@link HttpRetryHandler HttpRetryHandlers} who are annotated according to the * Delegates to {@link HttpRetryHandler HttpRetryHandlers} who are annotated according to the
@ -57,9 +58,9 @@ public class DelegatingRetryHandler implements HttpRetryHandler {
HttpRetryHandler serverErrorRetryHandler; HttpRetryHandler serverErrorRetryHandler;
public DelegatingRetryHandler() { public DelegatingRetryHandler() {
BackoffLimitedRetryHandler backOff = new BackoffLimitedRetryHandler(5); BackoffLimitedRetryHandler backOff = new BackoffLimitedRetryHandler();
this.serverErrorRetryHandler = backOff; this.serverErrorRetryHandler = backOff;
this.redirectionRetryHandler = new RedirectionRetryHandler(backOff, 5); this.redirectionRetryHandler = new RedirectionRetryHandler(backOff);
this.clientErrorRetryHandler = HttpRetryHandler.NEVER_RETRY; this.clientErrorRetryHandler = HttpRetryHandler.NEVER_RETRY;
} }

View File

@ -28,18 +28,19 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import javax.inject.Inject;
import javax.inject.Named;
/** /**
* Handles Retryable responses with error codes in the 3xx range * Handles Retryable responses with error codes in the 3xx range
@ -47,7 +48,9 @@ import javax.inject.Named;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class RedirectionRetryHandler implements HttpRetryHandler { public class RedirectionRetryHandler implements HttpRetryHandler {
protected final int retryCountLimit; @Inject(optional = true)
@Named(HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS)
protected int retryCountLimit = 5;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -55,9 +58,7 @@ public class RedirectionRetryHandler implements HttpRetryHandler {
protected final BackoffLimitedRetryHandler backoffHandler; protected final BackoffLimitedRetryHandler backoffHandler;
@Inject @Inject
public RedirectionRetryHandler(BackoffLimitedRetryHandler backoffHandler, public RedirectionRetryHandler(BackoffLimitedRetryHandler backoffHandler) {
@Named("jclouds.http.max-redirects") int retryCountLimit) {
this.retryCountLimit = retryCountLimit;
this.backoffHandler = backoffHandler; this.backoffHandler = backoffHandler;
} }

View File

@ -21,10 +21,8 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.aws.s3.functions; package org.jclouds.http.functions;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.aws.s3.xml.config.S3ParserModule;
import org.jclouds.http.functions.config.ParserModule; import org.jclouds.http.functions.config.ParserModule;
import org.testng.annotations.AfterTest; import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
@ -34,19 +32,19 @@ import com.google.inject.Injector;
public class BaseHandlerTest { public class BaseHandlerTest {
protected S3ParserFactory parserFactory = null; protected Injector injector = null;
private Injector injector; protected ParseSax.Factory factory;
@BeforeTest @BeforeTest
protected void setUpInjector() { protected void setUpInjector() {
injector = Guice.createInjector(new S3ParserModule(), new ParserModule()); injector = Guice.createInjector(new ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class); factory = injector.getInstance(ParseSax.Factory.class);
assert parserFactory != null; assert factory != null;
} }
@AfterTest @AfterTest
protected void tearDownInjector() { protected void tearDownInjector() {
parserFactory = null; factory = null;
injector = null; injector = null;
} }

View File

@ -48,7 +48,7 @@ import com.google.common.base.Function;
public class BackoffLimitedRetryHandlerTest { public class BackoffLimitedRetryHandlerTest {
private static final URI END_POINT = URI.create("http://localhost:8080"); private static final URI END_POINT = URI.create("http://localhost:8080");
BackoffLimitedRetryHandler handler = new BackoffLimitedRetryHandler(5); BackoffLimitedRetryHandler handler = new BackoffLimitedRetryHandler();
@Test @Test
void testExponentialBackoffDelay() throws InterruptedException { void testExponentialBackoffDelay() throws InterruptedException {