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) {
if (qName.equals("Code")) {
error.setCode(currentText.toString());
error.setCode(currentText.toString().trim());
} else if (qName.equals("Message")) {
error.setMessage(currentText.toString());
error.setMessage(currentText.toString().trim());
} else if (qName.equalsIgnoreCase("RequestId")) {
error.setRequestId(currentText.toString());
error.setRequestId(currentText.toString().trim());
} else if (!qName.equals("Error")) {
error.getDetails().put(qName, currentText.toString());
error.getDetails().put(qName, currentText.toString().trim());
}
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;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import javax.inject.Inject;
import javax.inject.Named;
/**
* Handles Retryable responses with error codes in the 3xx range
*
* @author Adrian Cole
*/
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;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public AWSClientErrorRetryHandler(S3Utils utils, S3ParserFactory parserFactory,
@Named("jclouds.http.max-retries") int retryCountLimit) {
public AWSClientErrorRetryHandler(S3Utils utils) {
this.utils = utils;
this.retryCountLimit = retryCountLimit;
this.parserFactory = parserFactory;
}
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
@ -67,8 +65,7 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
byte[] content = Utils.closeConnectionButKeepContentStream(response);
command.incrementRedirectCount();
try {
AWSError error = utils.parseAWSErrorFromContent(parserFactory, command, response,
new String(content));
AWSError error = utils.parseAWSErrorFromContent(command, response, new String(content));
if ("RequestTimeout".equals(error.getCode())
|| "OperationAborted".equals(error.getCode())) {
return true;

View File

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

View File

@ -24,11 +24,11 @@
package org.jclouds.aws.s3.handlers;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.util.S3Utils;
import org.jclouds.aws.s3.xml.S3ParserFactory;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
@ -36,8 +36,6 @@ import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import javax.inject.Inject;
/**
* This will parse and set an appropriate exception on the command object.
*
@ -49,13 +47,11 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
@Resource
protected Logger logger = Logger.NULL;
private final S3ParserFactory parserFactory;
private final S3Utils utils;
@Inject
public ParseAWSErrorFromXmlContent(S3Utils utils, S3ParserFactory parserFactory) {
public ParseAWSErrorFromXmlContent(S3Utils utils) {
this.utils = utils;
this.parserFactory = parserFactory;
}
public void handleError(HttpCommand command, HttpResponse response) {
@ -66,8 +62,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
if (content != null) {
try {
if (content.indexOf('<') >= 0) {
AWSError error = utils.parseAWSErrorFromContent(parserFactory, command, response,
content);
AWSError error = utils.parseAWSErrorFromContent(command, response, content);
command.setException(new AWSResponseException(command, response, error));
} else {
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.InputStream;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
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.http.HttpCommand;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import javax.inject.Inject;
import org.jclouds.http.functions.ParseSax;
/**
* Encryption, Hashing, and IO Utilities needed to sign and verify S3 requests and responses.
@ -51,23 +53,29 @@ public class S3Utils extends BlobStoreUtils {
@Inject
RequestAuthorizeSignature signer;
public AWSError parseAWSErrorFromContent(S3ParserFactory parserFactory, HttpCommand command,
HttpResponse response, InputStream content) throws HttpException {
AWSError error = parserFactory.createErrorParser().parse(content);
error.setRequestId(response.getFirstHeaderOrNull(S3Headers.REQUEST_ID));
@Inject
ParseSax.Factory factory;
@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));
if ("SignatureDoesNotMatch".equals(error.getCode())) {
error.setStringSigned(signer.createStringToSign(command.getRequest()));
error.setSignature(signer.signString(error.getStringSigned()));
}
return error;
}
public AWSError parseAWSErrorFromContent(S3ParserFactory parserFactory, HttpCommand command,
HttpResponse response, String content) throws HttpException {
return parseAWSErrorFromContent(parserFactory, command, response, new ByteArrayInputStream(
content.getBytes()));
public AWSError parseAWSErrorFromContent(HttpCommand command, HttpResponse response,
String content) throws HttpException {
return parseAWSErrorFromContent(command, response, new ByteArrayInputStream(content
.getBytes()));
}
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.
* ====================================================================
*/
package org.jclouds.aws.s3.functions;
package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals;
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.GroupGranteeURI;
import org.jclouds.aws.s3.domain.AccessControlList.Permission;
import org.jclouds.aws.s3.xml.AccessControlListHandler;
import org.jclouds.http.HttpException;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
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 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> parser = parserFactory.createAccessControlListParser();
ParseSax<AccessControlList> parser = (ParseSax<AccessControlList>) factory.create(injector
.getInstance(AccessControlListHandler.class));
return parser;
}

View File

@ -21,15 +21,16 @@
* under the License.
* ====================================================================
*/
package org.jclouds.aws.s3.functions;
package org.jclouds.aws.s3.xml;
import static org.testng.Assert.assertEquals;
import org.apache.commons.io.IOUtils;
import org.jclouds.aws.s3.domain.ListBucketResponse;
import org.jclouds.aws.s3.xml.ListBucketHandler;
import org.jclouds.http.HttpException;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@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 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> parser = parserFactory.createListBucketParser();
ParseSax<ListBucketResponse> parser = (ParseSax<ListBucketResponse>) factory.create(injector
.getInstance(ListBucketHandler.class));
return parser;
}
@ -56,7 +58,8 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
@Test
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.getMaxResults(), 1000);
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.ListBucketResponse;
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.HttpUtils;
import org.jclouds.http.functions.ParseSax;
@ -62,32 +60,33 @@ import com.google.inject.Injector;
@Test(groups = { "performance" }, testName = "s3.S3ParserTest")
public class S3ParserTest extends PerformanceTest {
Injector 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>";
S3ParserFactory parserFactory = null;
ParseSax.Factory factory;
@BeforeTest
protected void setUpInjector() {
injector = Guice.createInjector(new ParserModule(), new S3ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class);
assert parserFactory != null;
injector = Guice.createInjector(new ParserModule());
factory = injector.getInstance(ParseSax.Factory.class);
assert factory != null;
}
@AfterTest
protected void tearDownInjector() {
parserFactory = null;
factory = 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
void testParseListAllMyBucketsSerialResponseTime() throws HttpException {
for (int i = 0; i < LOOP_COUNT; i++)
runParseListAllMyBuckets();
}
@SuppressWarnings("unchecked")
private List<BucketMetadata> runParseListAllMyBuckets() throws HttpException {
return parserFactory.createListBucketsParser().parse(
return (List<BucketMetadata>) factory.create(
injector.getInstance(ListAllMyBucketsHandler.class)).parse(
IOUtils.toInputStream(listAllMyBucketsResultOn200));
}
@ -148,15 +147,15 @@ public class S3ParserTest extends PerformanceTest {
}
private ListBucketResponse runParseListContainerResult() throws HttpException {
ParseSax<ListBucketResponse> parser = parserFactory.createListBucketParser();
return parser.parse(IOUtils.toInputStream(listContainerResult));
return (ListBucketResponse) factory.create(injector.getInstance(ListBucketHandler.class))
.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>";
private ObjectMetadata runParseCopyObjectResult() throws HttpException {
ParseSax<ObjectMetadata> parser = parserFactory.createCopyObjectParser();
return parser.parse(IOUtils.toInputStream(successfulCopyObject200));
return (ObjectMetadata) factory.create(injector.getInstance(CopyObjectHandler.class)).parse(
IOUtils.toInputStream(successfulCopyObject200));
}
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.BoundedList;
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 com.google.common.collect.ImmutableList;
@ -45,6 +47,17 @@ import com.google.common.collect.ImmutableList;
@Test(groups = "unit", testName = "azureblob.AccountNameEnumerationResultsHandlerTest")
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() {
InputStream is = getClass().getResourceAsStream("/test_list_containers.xml");
BoundedList<ContainerMetadata> list = new ArrayBoundedList<ContainerMetadata>(ImmutableList
@ -60,12 +73,14 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
.fromHexString("0x8CACB9BD7BACAC3"))
), null, null, 3, "video");
ParseSax<BoundedList<ContainerMetadata>> parser = parserFactory
.createContainerMetadataListParser();
BoundedList<ContainerMetadata> result = parser.parse(is);
BoundedList<ContainerMetadata> result = (BoundedList<ContainerMetadata>) factory.create(
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list);
}
@SuppressWarnings("unchecked")
public void testApplyInputStreamWithOptions() {
InputStream is = getClass().getResourceAsStream("/test_list_containers_options.xml");
BoundedList<ContainerMetadata> list = new ArrayBoundedList<ContainerMetadata>(ImmutableList
@ -81,9 +96,8 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
.fromHexString("0x8CACB9BD7BACAC3"))
), "prefix", "marker", 1, "video");
ParseSax<BoundedList<ContainerMetadata>> parser = parserFactory
.createContainerMetadataListParser();
BoundedList<ContainerMetadata> result = parser.parse(is);
BoundedList<ContainerMetadata> result = (BoundedList<ContainerMetadata>) factory.create(
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
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.BlobMetadata;
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.domain.BoundedList;
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 com.google.common.collect.ImmutableList;
@ -44,7 +47,17 @@ import com.google.common.collect.ImmutableList;
*/
@Test(groups = "unit", testName = "azureblob.ContainerNameEnumerationResultsHandlerTest")
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() {
InputStream is = getClass().getResourceAsStream("/test_list_blobs.xml");
ListBlobsResponse list = new ArrayListBlobsResponse(URI
@ -65,8 +78,10 @@ public class ContainerNameEnumerationResultsHandlerTest extends BaseHandlerTest
"text/plain; charset=UTF-8", null, null, null)
), 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);
}
}

View File

@ -24,11 +24,11 @@
package org.jclouds.azure.storage.handlers;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.azure.storage.AzureStorageResponseException;
import org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.azure.storage.util.AzureStorageUtils;
import org.jclouds.azure.storage.xml.AzureStorageParserFactory;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
@ -36,8 +36,6 @@ import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import javax.inject.Inject;
/**
* This will parse and set an appropriate exception on the command object.
*
@ -49,13 +47,11 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
@Resource
protected Logger logger = Logger.NULL;
private final AzureStorageParserFactory parserFactory;
private final AzureStorageUtils utils;
@Inject
public ParseAzureStorageErrorFromXmlContent(AzureStorageUtils utils, AzureStorageParserFactory parserFactory) {
public ParseAzureStorageErrorFromXmlContent(AzureStorageUtils utils) {
this.utils = utils;
this.parserFactory = parserFactory;
}
public void handleError(HttpCommand command, HttpResponse response) {
@ -66,8 +62,8 @@ public class ParseAzureStorageErrorFromXmlContent implements HttpErrorHandler {
if (content != null) {
try {
if (content.indexOf('<') >= 0) {
AzureStorageError error = utils.parseAzureStorageErrorFromContent(parserFactory, command, response,
content);
AzureStorageError error = utils.parseAzureStorageErrorFromContent(command,
response, content);
command.setException(new AzureStorageResponseException(command, response, error));
} else {
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.InputStream;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
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.HttpException;
import org.jclouds.http.HttpResponse;
import javax.inject.Inject;
import org.jclouds.http.functions.ParseSax;
/**
* Encryption, Hashing, and IO Utilities needed to sign and verify Azure Storage requests and
@ -47,10 +49,16 @@ public class AzureStorageUtils {
@Inject
SharedKeyAuthentication signer;
public AzureStorageError parseAzureStorageErrorFromContent(
AzureStorageParserFactory parserFactory, HttpCommand command, HttpResponse response,
InputStream content) throws HttpException {
AzureStorageError error = parserFactory.createErrorParser().parse(content);
@Inject
ParseSax.Factory factory;
@Inject
Provider<ErrorHandler> errorHandlerProvider;
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));
if ("AuthenticationFailed".equals(error.getCode())) {
error.setStringSigned(signer.createStringToSign(command.getRequest()));
@ -60,11 +68,10 @@ public class AzureStorageUtils {
}
public AzureStorageError parseAzureStorageErrorFromContent(
AzureStorageParserFactory parserFactory, HttpCommand command, HttpResponse response,
String content) throws HttpException {
return parseAzureStorageErrorFromContent(parserFactory, command, response,
new ByteArrayInputStream(content.getBytes()));
public AzureStorageError parseAzureStorageErrorFromContent(HttpCommand command,
HttpResponse response, String content) throws HttpException {
return parseAzureStorageErrorFromContent(command, response, 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 org.jclouds.azure.storage.domain.AzureStorageError;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
import org.testng.annotations.Test;
@ -39,9 +40,16 @@ import org.testng.annotations.Test;
@Test(groups = "unit", testName = "azurestorage.ErrorHandlerTest")
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() {
InputStream is = getClass().getResourceAsStream("/test_error.xml");
ParseSax<AzureStorageError> parser = parserFactory.createErrorParser();
ParseSax<AzureStorageError> parser = createParser();
AzureStorageError result = parser.parse(is);
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.BoundedList;
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 com.google.common.collect.ImmutableList;
@ -44,6 +44,7 @@ import com.google.common.collect.ImmutableList;
@Test(groups = "unit", testName = "azurequeue.AccountNameEnumerationResultsHandlerTest")
public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
@SuppressWarnings("unchecked")
public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/test_list_queues.xml");
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("q3", URI.create("http://myaccount.queue.core.windows.net/q3"))),
"q", null, 3, "q4");
ParseSax<BoundedList<QueueMetadata>> parser = parserFactory
.createContainerMetadataListParser();
BoundedList<QueueMetadata> result = parser.parse(is);
BoundedList<QueueMetadata> result = (BoundedList<QueueMetadata>) factory.create(
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
assertEquals(result, list);
}
@SuppressWarnings("unchecked")
public void testApplyInputStreamWithOptions() {
InputStream is = getClass().getResourceAsStream("/test_list_queues_options.xml");
BoundedList<QueueMetadata> list = new ArrayBoundedList<QueueMetadata>(ImmutableList.of(
new QueueMetadata("q4", URI.create("http://myaccount.queue.core.windows.net/q4")),
new QueueMetadata("q5", URI.create("http://myaccount.queue.core.windows.net/q5"))),
"q", "q4", 3, null);
ParseSax<BoundedList<QueueMetadata>> parser = parserFactory
.createContainerMetadataListParser();
BoundedList<QueueMetadata> result = parser.parse(is);
BoundedList<QueueMetadata> result = (BoundedList<QueueMetadata>) factory.create(
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
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;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.TransformingHttpCommand;
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
* back-off delay before returning.
@ -76,16 +76,13 @@ import javax.inject.Named;
* @author James Murty
*/
public class BackoffLimitedRetryHandler implements HttpRetryHandler {
private final int retryCountLimit;
@Inject(optional = true)
@Named(HttpConstants.PROPERTY_HTTP_MAX_RETRIES)
private int retryCountLimit = 5;
@Resource
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) {
IOUtils.closeQuietly(response.getContent());

View File

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

View File

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

View File

@ -21,10 +21,8 @@
* 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.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
@ -34,19 +32,19 @@ import com.google.inject.Injector;
public class BaseHandlerTest {
protected S3ParserFactory parserFactory = null;
private Injector injector;
protected Injector injector = null;
protected ParseSax.Factory factory;
@BeforeTest
protected void setUpInjector() {
injector = Guice.createInjector(new S3ParserModule(), new ParserModule());
parserFactory = injector.getInstance(S3ParserFactory.class);
assert parserFactory != null;
injector = Guice.createInjector(new ParserModule());
factory = injector.getInstance(ParseSax.Factory.class);
assert factory != null;
}
@AfterTest
protected void tearDownInjector() {
parserFactory = null;
factory = null;
injector = null;
}

View File

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