Issue 148 Issue 9 cleanup javadoc, removed use of string.replaceAll

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2664 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2010-01-18 20:28:37 +00:00
parent 2776d12093
commit 27de8ac105
46 changed files with 435 additions and 175 deletions

View File

@ -18,6 +18,9 @@
*/ */
package org.jclouds.atmosonline.saas.filters; package org.jclouds.atmosonline.saas.filters;
import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
import static org.jclouds.util.Patterns.TWO_SPACE_PATTERN;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
@ -64,7 +67,7 @@ public class SignRequest implements HttpRequestFilter {
Logger logger = Logger.NULL; Logger logger = Logger.NULL;
@Resource @Resource
@Named(HttpConstants.SIGNATURE_LOGGER) @Named(HttpConstants.LOGGER_SIGNATURE)
Logger signatureLog = Logger.NULL; Logger signatureLog = Logger.NULL;
@Inject @Inject
@ -143,8 +146,11 @@ public class SignRequest implements HttpRequestFilter {
// For headers with values that span multiple lines, convert them into one line by // For headers with values that span multiple lines, convert them into one line by
// replacing any // replacing any
// newline characters and extra embedded white spaces in the value. // newline characters and extra embedded white spaces in the value.
for (String value : request.getHeaders().get(header)) for (String value : request.getHeaders().get(header)) {
toSign.append(value.replaceAll("\r?\n", "").replaceAll(" ", " ")).append(" "); value = Utils.replaceAll(value, TWO_SPACE_PATTERN, " ");
value = Utils.replaceAll(value, NEWLINE_PATTERN, "");
toSign.append(value).append(' ');
}
toSign.deleteCharAt(toSign.lastIndexOf(" ")); toSign.deleteCharAt(toSign.lastIndexOf(" "));
// Concatenate all headers together, using newlines (\n) separating each header from the // Concatenate all headers together, using newlines (\n) separating each header from the
// next one. // next one.

View File

@ -22,6 +22,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.ec2.EC2AsyncClient; import org.jclouds.aws.ec2.EC2AsyncClient;
import com.google.common.base.CaseFormat;
/** /**
* *
* The current state of the instance.. * The current state of the instance..
@ -62,7 +64,7 @@ public enum InstanceState {
STOPPED; STOPPED;
public String value() { public String value() {
return name().toLowerCase().replaceAll("_", "-"); return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()));
} }
@Override @Override
@ -71,7 +73,8 @@ public enum InstanceState {
} }
public static InstanceState fromValue(String state) { public static InstanceState fromValue(String state) {
return valueOf(checkNotNull(state, "state").replaceAll("-", "_").toUpperCase()); return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state,
"state")));
} }
public static InstanceState fromValue(int v) { public static InstanceState fromValue(int v) {

View File

@ -78,7 +78,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
private final Provider<String> dateService; private final Provider<String> dateService;
private final EncryptionService encryptionService; private final EncryptionService encryptionService;
@Resource @Resource
@Named(HttpConstants.SIGNATURE_LOGGER) @Named(HttpConstants.LOGGER_SIGNATURE)
private Logger signatureLog = Logger.NULL; private Logger signatureLog = Logger.NULL;
@Inject @Inject

View File

@ -52,7 +52,7 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
&& (response.getStatusCode() == 301 || response.getStatusCode() == 307)) { && (response.getStatusCode() == 301 || response.getStatusCode() == 307)) {
byte[] content = HttpUtils.closeClientButKeepContentStream(response); byte[] content = HttpUtils.closeClientButKeepContentStream(response);
if (command.getRequest().getMethod() == HttpMethod.HEAD) { if (command.getRequest().getMethod() == HttpMethod.HEAD) {
command.redirectAsGet(); command.changeToGETRequest();
return true; return true;
} else { } else {
command.incrementRedirectCount(); command.incrementRedirectCount();
@ -66,7 +66,7 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
// http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287&#72287 // http://developer.amazonwebservices.com/connect/thread.jspa?messageID=72287&#72287
return backoffHandler.shouldRetryRequest(command, response); return backoffHandler.shouldRetryRequest(command, response);
} else { } else {
command.redirect(host, command.getRequest().getEndpoint().getPort()); command.changeHostAndPortTo(host, command.getRequest().getEndpoint().getPort());
} }
return true; return true;
} else { } else {

View File

@ -19,6 +19,7 @@
package org.jclouds.aws.s3.filters; package org.jclouds.aws.s3.filters;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -69,7 +70,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
private final EncryptionService encryptionService; private final EncryptionService encryptionService;
@Resource @Resource
@Named(HttpConstants.SIGNATURE_LOGGER) @Named(HttpConstants.LOGGER_SIGNATURE)
Logger signatureLog = Logger.NULL; Logger signatureLog = Logger.NULL;
@Inject @Inject
@ -138,8 +139,9 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
for (String header : headers) { for (String header : headers) {
if (header.startsWith("x-amz-")) { if (header.startsWith("x-amz-")) {
toSign.append(header.toLowerCase()).append(":"); toSign.append(header.toLowerCase()).append(":");
for (String value : request.getHeaders().get(header)) for (String value : request.getHeaders().get(header)) {
toSign.append(value.replaceAll("\r?\n", "")).append(","); toSign.append(Utils.replaceAll(value, NEWLINE_PATTERN, "")).append(",");
}
toSign.deleteCharAt(toSign.lastIndexOf(",")); toSign.deleteCharAt(toSign.lastIndexOf(","));
toSign.append("\n"); toSign.append("\n");
} }

View File

@ -30,6 +30,7 @@ import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.rest.InvocationContext; import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -63,7 +64,7 @@ public class ParseObjectMetadataFromHeaders implements
BlobMetadata base = blobMetadataParser.apply(from); BlobMetadata base = blobMetadataParser.apply(from);
MutableObjectMetadata to = blobToObjectMetadata.apply(base); MutableObjectMetadata to = blobToObjectMetadata.apply(base);
addETagTo(from, to); addETagTo(from, to);
to.setContentMD5(encryptionService.fromHexString(to.getETag().replaceAll("\"", ""))); to.setContentMD5(encryptionService.fromHexString(Utils.replaceAll(to.getETag(), '"', "")));
to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL)); to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL));
to.setContentDisposition(from.getFirstHeaderOrNull("Content-Disposition")); to.setContentDisposition(from.getFirstHeaderOrNull("Content-Disposition"));
to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING)); to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING));

View File

@ -23,6 +23,7 @@ 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 java.util.regex.Pattern;
import javax.inject.Inject; import javax.inject.Inject;
@ -33,7 +34,7 @@ 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.util.Patterns;
/** /**
* 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.
@ -60,16 +61,17 @@ public class S3Utils extends BlobStoreUtils {
.getBytes())); .getBytes()));
} }
public static final Pattern BUCKET_NAME_PATTERN = Pattern.compile("^[a-z0-9][-_.a-z0-9]+");
// TODO add validatorparam so that this is actually used
public static String validateBucketName(String bucketName) { public static String validateBucketName(String bucketName) {
checkNotNull(bucketName, "bucketName"); checkNotNull(bucketName, "bucketName");
checkArgument(bucketName.matches("^[a-z0-9].*"),
"bucketName name must start with a number or letter");
checkArgument( checkArgument(
bucketName.matches("^[-_.a-z0-9]+"), BUCKET_NAME_PATTERN.matcher(bucketName).matches(),
"bucketName name can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)"); "bucketName name must start with a number or letter and can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)");
checkArgument(bucketName.length() > 2 && bucketName.length() < 256, checkArgument(bucketName.length() > 2 && bucketName.length() < 256,
"bucketName name must be between 3 and 255 characters long"); "bucketName name must be between 3 and 255 characters long");
checkArgument(!HttpUtils.IP_PATTERN.matcher(bucketName).matches(), checkArgument(!Patterns.IP_PATTERN.matcher(bucketName).matches(),
"bucketName name cannot be ip address style"); "bucketName name cannot be ip address style");
return bucketName; return bucketName;
} }

View File

@ -32,6 +32,7 @@ import org.jclouds.aws.s3.domain.internal.TreeSetListBucketResponse;
import org.jclouds.date.DateService; import org.jclouds.date.DateService;
import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.Utils;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -100,7 +101,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim()); currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
} else if (qName.equals("ETag")) { } else if (qName.equals("ETag")) {
currentETag = currentText.toString().trim(); currentETag = currentText.toString().trim();
currentMD5 = encryptionService.fromHexString(currentETag.replaceAll("\"", "")); currentMD5 = encryptionService.fromHexString(Utils.replaceAll(currentETag,'"', ""));
} else if (qName.equals("Size")) { } else if (qName.equals("Size")) {
currentSize = new Long(currentText.toString().trim()); currentSize = new Long(currentText.toString().trim());
} else if (qName.equals("Owner")) { } else if (qName.equals("Owner")) {

View File

@ -94,10 +94,10 @@ public class S3UtilsTest {
return false; return false;
} }
public void redirect(String host, int port) { public void changeHostAndPortTo(String host, int port) {
} }
public void redirectAsGet() { public void changeToGETRequest() {
} }
public Exception getException() { public Exception getException() {
@ -121,7 +121,7 @@ public class S3UtilsTest {
} }
@Override @Override
public void redirectPath(String newPath) { public void changePathTo(String newPath) {
} }
}; };

View File

@ -31,8 +31,10 @@ import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_M
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
import java.util.regex.Pattern;
import org.jclouds.http.HttpPropertiesBuilder; import org.jclouds.http.HttpPropertiesBuilder;
import org.jclouds.util.Utils;
/** /**
* Builds properties used in AzureBlob Connections * Builds properties used in AzureBlob Connections
@ -60,12 +62,15 @@ public class AzureBlobPropertiesBuilder extends HttpPropertiesBuilder {
withCredentials(id, secret); withCredentials(id, secret);
} }
public static final Pattern ACCOUNT_PATTERN = Pattern.compile("\\{account\\}");
public AzureBlobPropertiesBuilder withCredentials(String id, String secret) { public AzureBlobPropertiesBuilder withCredentials(String id, String secret) {
properties properties
.setProperty(PROPERTY_AZURESTORAGE_ACCOUNT, checkNotNull(id, "azureStorageAccount")); .setProperty(PROPERTY_AZURESTORAGE_ACCOUNT, checkNotNull(id, "azureStorageAccount"));
properties.setProperty(PROPERTY_AZURESTORAGE_KEY, checkNotNull(secret, "azureStorageKey")); properties.setProperty(PROPERTY_AZURESTORAGE_KEY, checkNotNull(secret, "azureStorageKey"));
String endpoint = properties.getProperty(PROPERTY_AZUREBLOB_ENDPOINT); String endpoint = properties.getProperty(PROPERTY_AZUREBLOB_ENDPOINT);
properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, endpoint.replaceAll("\\{account\\}", id)); properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, Utils.replaceAll(endpoint,
ACCOUNT_PATTERN, id));
return this; return this;
} }
@ -74,8 +79,8 @@ public class AzureBlobPropertiesBuilder extends HttpPropertiesBuilder {
"azureStorageAccount"); "azureStorageAccount");
properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, checkNotNull(endpoint, "endpoint") properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString()); .toString());
properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, endpoint.toString().replaceAll( properties.setProperty(PROPERTY_AZUREBLOB_ENDPOINT, Utils.replaceAll(
"\\{account\\}", account)); endpoint.toASCIIString(), ACCOUNT_PATTERN, account));
return this; return this;
} }

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.azure.storage.filters; package org.jclouds.azure.storage.filters;
import static org.jclouds.util.Patterns.NEWLINE_PATTERN;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
@ -62,7 +64,7 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
private final Provider<String> timeStampProvider; private final Provider<String> timeStampProvider;
private final EncryptionService encryptionService; private final EncryptionService encryptionService;
@Resource @Resource
@Named(HttpConstants.SIGNATURE_LOGGER) @Named(HttpConstants.LOGGER_SIGNATURE)
Logger signatureLog = Logger.NULL; Logger signatureLog = Logger.NULL;
@Inject @Inject
@ -130,8 +132,9 @@ public class SharedKeyAuthentication implements HttpRequestFilter {
for (String header : headers) { for (String header : headers) {
if (header.startsWith("x-ms-")) { if (header.startsWith("x-ms-")) {
toSign.append(header.toLowerCase()).append(":"); toSign.append(header.toLowerCase()).append(":");
for (String value : request.getHeaders().get(header)) for (String value : request.getHeaders().get(header)) {
toSign.append(value.replaceAll("\r?\n", "")).append(","); toSign.append(Utils.replaceAll(value, NEWLINE_PATTERN, "")).append(",");
}
toSign.deleteCharAt(toSign.lastIndexOf(",")); toSign.deleteCharAt(toSign.lastIndexOf(","));
toSign.append("\n"); toSign.append("\n");
} }

View File

@ -23,10 +23,12 @@ import static org.jclouds.azure.storage.reference.AzureStorageConstants.PROPERTY
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
import java.util.regex.Pattern;
import org.jclouds.azure.storage.queue.reference.AzureQueueConstants; import org.jclouds.azure.storage.queue.reference.AzureQueueConstants;
import org.jclouds.azure.storage.reference.AzureStorageConstants; import org.jclouds.azure.storage.reference.AzureStorageConstants;
import org.jclouds.http.HttpPropertiesBuilder; import org.jclouds.http.HttpPropertiesBuilder;
import org.jclouds.util.Utils;
/** /**
* Builds properties used in AzureQueue Connections * Builds properties used in AzureQueue Connections
@ -52,14 +54,16 @@ public class AzureQueuePropertiesBuilder extends HttpPropertiesBuilder {
withCredentials(id, secret); withCredentials(id, secret);
} }
public static final Pattern ACCOUNT_PATTERN = Pattern.compile("\\{account\\}");
public AzureQueuePropertiesBuilder withCredentials(String id, String secret) { public AzureQueuePropertiesBuilder withCredentials(String id, String secret) {
properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT, checkNotNull(id, properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_ACCOUNT, checkNotNull(id,
"azureStorageAccount")); "azureStorageAccount"));
properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY, checkNotNull(secret, properties.setProperty(AzureStorageConstants.PROPERTY_AZURESTORAGE_KEY, checkNotNull(secret,
"azureStorageKey")); "azureStorageKey"));
String endpoint = properties.getProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT); String endpoint = properties.getProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT);
properties.setProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT, endpoint.replaceAll( properties.setProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT, Utils.replaceAll(
"\\{account\\}", id)); endpoint, ACCOUNT_PATTERN, id));
return this; return this;
} }
@ -69,8 +73,8 @@ public class AzureQueuePropertiesBuilder extends HttpPropertiesBuilder {
"azureStorageAccount"); "azureStorageAccount");
properties.setProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT, checkNotNull( properties.setProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT, checkNotNull(
endpoint, "endpoint").toString()); endpoint, "endpoint").toString());
properties.setProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT, endpoint.toString() properties.setProperty(AzureQueueConstants.PROPERTY_AZUREQUEUE_ENDPOINT, Utils.replaceAll(
.replaceAll("\\{account\\}", account)); endpoint.toASCIIString(), ACCOUNT_PATTERN, account));
return this; return this;
} }

View File

@ -24,6 +24,7 @@ import javax.inject.Inject;
import org.jclouds.blobstore.options.GetOptions; import org.jclouds.blobstore.options.GetOptions;
import org.jclouds.date.DateService; import org.jclouds.date.DateService;
import org.jclouds.util.Utils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -40,14 +41,14 @@ public class HttpGetOptionsListToGetOptions implements
org.jclouds.blobstore.options.GetOptions to = new org.jclouds.blobstore.options.GetOptions(); org.jclouds.blobstore.options.GetOptions to = new org.jclouds.blobstore.options.GetOptions();
if (from.length != 0) { if (from.length != 0) {
if (from[0].getIfMatch() != null) { if (from[0].getIfMatch() != null) {
to.ifETagMatches(from[0].getIfMatch().replaceAll("\"", "")); to.ifETagMatches(Utils.replaceAll(from[0].getIfMatch(), '"', ""));
} }
if (from[0].getIfModifiedSince() != null) { if (from[0].getIfModifiedSince() != null) {
Date time = dateService.rfc822DateParse(from[0].getIfModifiedSince()); Date time = dateService.rfc822DateParse(from[0].getIfModifiedSince());
to.ifModifiedSince(time); to.ifModifiedSince(time);
} }
if (from[0].getIfNoneMatch() != null) { if (from[0].getIfNoneMatch() != null) {
to.ifETagDoesntMatch(from[0].getIfNoneMatch().replaceAll("\"", "")); to.ifETagDoesntMatch(Utils.replaceAll(from[0].getIfNoneMatch(), '"', ""));
} }
if (from[0].getIfUnmodifiedSince() != null) { if (from[0].getIfUnmodifiedSince() != null) {
Date time = dateService.rfc822DateParse(from[0].getIfUnmodifiedSince()); Date time = dateService.rfc822DateParse(from[0].getIfUnmodifiedSince());

View File

@ -415,10 +415,10 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
return false; return false;
} }
public void redirect(String host, int port) { public void changeHostAndPortTo(String host, int port) {
} }
public void redirectAsGet() { public void changeToGETRequest() {
} }
public Exception getException() { public Exception getException() {
@ -442,7 +442,7 @@ public class StubAsyncBlobStore implements AsyncBlobStore {
} }
@Override @Override
public void redirectPath(String newPath) { public void changePathTo(String newPath) {
} }
}, response); }, response);
} }

View File

@ -39,7 +39,7 @@ public class ComputeServiceContextFactory extends
* *
* @throws IOException * @throws IOException
* if the default properties file cannot be loaded * if the default properties file cannot be loaded
* @see #init * @see RestContextFactory#getProperties
*/ */
public ComputeServiceContextFactory() throws IOException { public ComputeServiceContextFactory() throws IOException {
super("compute.properties"); super("compute.properties");
@ -47,7 +47,7 @@ public class ComputeServiceContextFactory extends
/** /**
* *
* Initializes the {@code ComputeServiceContext) definitions from the specified properties. * Initializes the {@code ComputeServiceContext} definitions from the specified properties.
*/ */
@Inject @Inject
public ComputeServiceContextFactory(Properties properties) { public ComputeServiceContextFactory(Properties properties) {

View File

@ -28,13 +28,11 @@ import java.util.Map;
public interface Size { public interface Size {
/** /**
* provider-specific identifier (m1.small, etc) * provider-specific identifier (m1.small, etc)
*
*/ */
String getId(); String getId();
/** /**
* Name provided by the provider (Small CPU, etc) * Name provided by the provider (Small CPU, etc)
*
*/ */
String getName(); String getName();
@ -59,10 +57,7 @@ public interface Size {
Long getBandwidth(); Long getBandwidth();
/** /**
*
* Hourly price of this server in USD, estimated if monthly. * Hourly price of this server in USD, estimated if monthly.
*
* @return
*/ */
Float getPrice(); Float getPrice();

View File

@ -24,15 +24,15 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* *
* This class or method has a timeout used for synchronous calls. * This class or method has a timeout used for synchronous calls.
* *
* @see SyncClient
* @see TimeUnit * @see TimeUnit
* @see ListenableFuture#get(long,TimeUnit) * @see Future#get(long,TimeUnit)
* @author Adrian Cole * @author Adrian Cole
*/ */
@Target( { TYPE, METHOD }) @Target( { TYPE, METHOD })

View File

@ -23,6 +23,7 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.SimpleTimeZone; import java.util.SimpleTimeZone;
import java.util.regex.Pattern;
import net.jcip.annotations.GuardedBy; import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe; import net.jcip.annotations.ThreadSafe;
@ -134,14 +135,19 @@ public class SimpleDateFormatDateService implements DateService {
} }
} }
public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern
.compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]");
private String trimNanosToMillis(String toParse) { private String trimNanosToMillis(String toParse) {
if (toParse.matches(".*[0-9][0-9][0-9][0-9][0-9][0-9]")) if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches())
toParse = toParse.substring(0, toParse.length() - 3) + 'Z'; toParse = toParse.substring(0, toParse.length() - 3) + 'Z';
return toParse; return toParse;
} }
public static final Pattern SECOND_PATTERN = Pattern.compile(".*[0-2][0-9]:00");
private String trimTZ(String toParse) { private String trimTZ(String toParse) {
if (toParse.length() == 25 && toParse.matches(".*[0-2][0-9]:00")) if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches())
toParse = toParse.substring(0, toParse.length() - 6) + 'Z'; toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
return toParse; return toParse;
} }

View File

@ -18,8 +18,6 @@
*/ */
package org.jclouds.http; package org.jclouds.http;
/** /**
* Command whose endpoint is an http service. * Command whose endpoint is an http service.
* *
@ -27,43 +25,68 @@ package org.jclouds.http;
*/ */
public interface HttpCommand { public interface HttpCommand {
/**
* increments the current number of redirect attempts for this command.
*
* @see getRedirectCount
*/
int incrementRedirectCount(); int incrementRedirectCount();
/**
* This displays the current number of redirect attempts for this command.
*
* @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS
*/
int getRedirectCount(); int getRedirectCount();
/**
* Commands need to be replayed, if redirected or on a retryable error. Typically, this implies
* the payload carried is not a streaming type.
*/
boolean isReplayable(); boolean isReplayable();
/** /**
* to allow redirects to work * change the destination of the current http command. typically used in handling redirects.
*/ */
void redirect(String host, int port); void changeHostAndPortTo(String host, int port);
/** /**
* to allow redirects to work on methods that were HEAD * change method from GET to HEAD. typically used in handling redirects.
*/ */
void redirectAsGet(); void changeToGETRequest();
/** /**
* change the path of the service * change the path of the service. typically used in handling redirects.
*/ */
void redirectPath(String newPath); void changePathTo(String newPath);
/**
* increment the current failure count.
*
* @see getFailureCount
*/
int incrementFailureCount(); int incrementFailureCount();
/**
* This displays the current number of error retries for this command.
*
* @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES
*/
int getFailureCount(); int getFailureCount();
/**
* The request associated with this command.
*/
HttpRequest getRequest(); HttpRequest getRequest();
/** /**
* * Used to prevent a command from being re-executed, or having its response parsed.
* Used to prevent a command from being re-executed.
*
* Any calls to {@link execute} following this will return the below exception.
*
* @param exception
*/ */
void setException(Exception exception); void setException(Exception exception);
/**
* @see setException
*/
Exception getException(); Exception getException();
} }

View File

@ -19,24 +19,54 @@
package org.jclouds.http; package org.jclouds.http;
/** /**
* // TODO: Adrian: Document this! * Constants used in http services.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface HttpConstants { public interface HttpConstants {
public static final String PROPERTY_HTTP_PROXY_SYSTEM = "jclouds.http.proxy.system";
public static final String PROPERTY_HTTP_MAX_RETRIES = "jclouds.http.max-retries";
public static final String PROPERTY_HTTP_MAX_REDIRECTS = "jclouds.http.max-redirects";
public static final String HTTP_HEADERS_LOGGER = "jclouds.http.headers";
public static final String HTTP_WIRE_LOGGER = "jclouds.http.wire";
public static final String SIGNATURE_LOGGER = "jclouds.signature";
/** /**
* Boolean property.
* <p/>
* Whether or not to use the proxy setup from the underlying operating system.
*/
public static final String PROPERTY_HTTP_PROXY_SYSTEM = "jclouds.http.proxy.system";
/**
* Integer property.
* <p/>
* Commands are retried, if the problem on the server side was a resolvable conflict. However,
* the maximum tries of a single command is bounded.
*/
public static final String PROPERTY_HTTP_MAX_RETRIES = "jclouds.http.max-retries";
/**
* Integer property.
* <p/>
* Commands are limited to only a certain amount of redirects.
*/
public static final String PROPERTY_HTTP_MAX_REDIRECTS = "jclouds.http.max-redirects";
/**
* Long property.
* <p/>
* longest time a single request can take before throwing an exception. * longest time a single request can take before throwing an exception.
*/ */
public static final String PROPERTY_HTTP_REQUEST_TIMEOUT = "jclouds.http.request.timeout"; public static final String PROPERTY_HTTP_REQUEST_TIMEOUT = "jclouds.http.request.timeout";
/** /**
* allow mismatch between hostname and ssl cerificate. * Boolean property.
* <p/>
* allow mismatch between hostname and ssl cerificate. Set to true in DNS-based services like
* Amazon S3.
*/ */
public static final String PROPERTY_HTTP_RELAX_HOSTNAME = "jclouds.http.relax-hostname"; public static final String PROPERTY_HTTP_RELAX_HOSTNAME = "jclouds.http.relax-hostname";
/**
* Name of the logger that records all http headers from the client and the server.
*/
public static final String LOGGER_HTTP_HEADERS = "jclouds.http.headers";
/**
* Name of the logger that records the content sent to and from the server.
*/
public static final String LOGGER_HTTP_WIRE = "jclouds.http.wire";
/**
* Name of the logger that records the steps of the request signing process of the HTTP-service.
*/
public static final String LOGGER_SIGNATURE = "jclouds.signature";
} }

View File

@ -26,7 +26,6 @@ import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREAD
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS; import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE; import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES; import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES;
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS;
import java.util.Properties; import java.util.Properties;
@ -40,34 +39,49 @@ import com.google.common.annotations.VisibleForTesting;
public class HttpPropertiesBuilder { public class HttpPropertiesBuilder {
/** /**
* allow mismatches between the certificate and the hostname of ssl requests. * @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_RELAX_HOSTNAME
*/ */
public HttpPropertiesBuilder relaxSSLHostname(boolean relax) { public HttpPropertiesBuilder relaxSSLHostname(boolean relax) {
properties.setProperty(PROPERTY_HTTP_RELAX_HOSTNAME, relax+""); properties.setProperty(PROPERTY_HTTP_RELAX_HOSTNAME, relax + "");
return this; return this;
} }
/**
* @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_PROXY_SYSTEM
*/
public HttpPropertiesBuilder useSystemProxies(boolean useSystemProxies) { public HttpPropertiesBuilder useSystemProxies(boolean useSystemProxies) {
properties.setProperty(PROPERTY_HTTP_PROXY_SYSTEM, useSystemProxies + ""); properties.setProperty(PROPERTY_HTTP_PROXY_SYSTEM, useSystemProxies + "");
return this; return this;
} }
/**
* @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES
*/
public HttpPropertiesBuilder withHttpMaxRetries(int httpMaxRetries) { public HttpPropertiesBuilder withHttpMaxRetries(int httpMaxRetries) {
properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, Integer.toString(httpMaxRetries)); properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, Integer.toString(httpMaxRetries));
return this; return this;
} }
/**
* @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS
*/
public HttpPropertiesBuilder withHttpMaxRedirects(int httpMaxRedirects) { public HttpPropertiesBuilder withHttpMaxRedirects(int httpMaxRedirects) {
properties.setProperty(PROPERTY_HTTP_MAX_REDIRECTS, Integer.toString(httpMaxRedirects)); properties.setProperty(PROPERTY_HTTP_MAX_REDIRECTS, Integer.toString(httpMaxRedirects));
return this; return this;
} }
/**
* @see org.jclouds.http.HttpConstants.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE
*/
public HttpPropertiesBuilder withPoolMaxClientReuse(int poolMaxClientReuse) { public HttpPropertiesBuilder withPoolMaxClientReuse(int poolMaxClientReuse) {
properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, Integer properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, Integer
.toString(poolMaxClientReuse)); .toString(poolMaxClientReuse));
return this; return this;
} }
/**
* @see org.jclouds.http.HttpConstants.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES
*/
public HttpPropertiesBuilder withPoolMaxSessionFailures(int poolMaxSessionFailures) { public HttpPropertiesBuilder withPoolMaxSessionFailures(int poolMaxSessionFailures) {
properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, Integer properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, Integer
.toString(poolMaxSessionFailures)); .toString(poolMaxSessionFailures));
@ -75,13 +89,9 @@ public class HttpPropertiesBuilder {
} }
public HttpPropertiesBuilder withPoolRequestInvokerThreads(int poolRequestInvokerThreads) { /**
properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, Integer * @see org.jclouds.http.HttpConstants.pool.PoolConstants.PROPERTY_POOL_IO_WORKER_THREADS
.toString(poolRequestInvokerThreads)); */
return this;
}
public HttpPropertiesBuilder withPoolIoWorkerThreads(int poolIoWorkerThreads) { public HttpPropertiesBuilder withPoolIoWorkerThreads(int poolIoWorkerThreads) {
properties properties
.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, Integer.toString(poolIoWorkerThreads)); .setProperty(PROPERTY_POOL_IO_WORKER_THREADS, Integer.toString(poolIoWorkerThreads));
@ -89,6 +99,9 @@ public class HttpPropertiesBuilder {
} }
/**
* @see org.jclouds.http.HttpConstants.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS
*/
public HttpPropertiesBuilder withPoolMaxClients(int poolMaxClients) { public HttpPropertiesBuilder withPoolMaxClients(int poolMaxClients) {
properties.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, Integer.toString(poolMaxClients)); properties.setProperty(PROPERTY_POOL_MAX_CONNECTIONS, Integer.toString(poolMaxClients));
return this; return this;

View File

@ -40,7 +40,6 @@ import com.google.inject.internal.Nullable;
public class HttpRequest extends HttpMessage { public class HttpRequest extends HttpMessage {
private List<HttpRequestFilter> requestFilters = Lists.newArrayList(); private List<HttpRequestFilter> requestFilters = Lists.newArrayList();
private String method; private String method;
private URI endpoint; private URI endpoint;
private Payload payload; private Payload payload;

View File

@ -19,6 +19,13 @@
package org.jclouds.http; package org.jclouds.http;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.util.Patterns.CHAR_TO_ENCODED_PATTERN;
import static org.jclouds.util.Patterns.PATTERN_THAT_BREAKS_URI;
import static org.jclouds.util.Patterns.PLUS_PATTERN;
import static org.jclouds.util.Patterns.STAR_PATTERN;
import static org.jclouds.util.Patterns.URI_PATTERN;
import static org.jclouds.util.Patterns.URL_ENCODED_PATTERN;
import static org.jclouds.util.Patterns._7E_PATTERN;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@ -29,32 +36,26 @@ import java.net.URI;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.common.base.Function;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.SortedSetMultimap; import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap; import com.google.common.collect.TreeMultimap;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables; import com.google.common.io.Closeables;
/**
* @author Adrian Cole
*/
public class HttpUtils { public class HttpUtils {
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
public static final Pattern PATTERN_THAT_BREAKS_URI = Pattern.compile("[a-z0-9]+://.*/.*@.*"); // slash
@Resource
protected static Logger logger = Logger.NULL;
/** /**
* Web browsers do not always handle '+' characters well, use the well-supported '%20' instead. * Web browsers do not always handle '+' characters well, use the well-supported '%20' instead.
@ -63,10 +64,12 @@ public class HttpUtils {
if (isUrlEncoded(in)) if (isUrlEncoded(in))
return in; return in;
try { try {
String returnVal = URLEncoder.encode(in, "UTF-8").replaceAll("\\+", "%20").replaceAll( String returnVal = URLEncoder.encode(in, "UTF-8");
"\\*", "%2A").replaceAll("%7E", "~"); returnVal = Utils.replaceAll(returnVal, '+', PLUS_PATTERN, "%20");
returnVal = Utils.replaceAll(returnVal, '*', STAR_PATTERN, "%2A");
returnVal = Utils.replaceAll(returnVal, _7E_PATTERN, "~");
for (char c : skipEncode) { for (char c : skipEncode) {
returnVal = returnVal.replaceAll(plainToEncodedChars.get(c + ""), c + ""); returnVal = Utils.replaceAll(returnVal, CHAR_TO_ENCODED_PATTERN.get(c), c + "");
} }
return returnVal; return returnVal;
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
@ -75,20 +78,9 @@ public class HttpUtils {
} }
public static boolean isUrlEncoded(String in) { public static boolean isUrlEncoded(String in) {
return in.matches(".*%[a-fA-F0-9][a-fA-F0-9].*"); return URL_ENCODED_PATTERN.matcher(in).matches();
} }
static Map<String, String> plainToEncodedChars = new MapMaker()
.makeComputingMap(new Function<String, String>() {
public String apply(String plain) {
try {
return URLEncoder.encode(plain, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Bad encoding on input: " + plain, e);
}
}
});
public static String urlDecode(String in) { public static String urlDecode(String in) {
try { try {
return URLDecoder.decode(in, "UTF-8"); return URLDecoder.decode(in, "UTF-8");
@ -107,7 +99,7 @@ public class HttpUtils {
response.setContent(new ByteArrayInputStream(data)); response.setContent(new ByteArrayInputStream(data));
return data; return data;
} catch (IOException e) { } catch (IOException e) {
logger.error(e, "Error consuming input"); Throwables.propagate(e);
} finally { } finally {
Closeables.closeQuietly(response.getContent()); Closeables.closeQuietly(response.getContent());
} }
@ -124,7 +116,7 @@ public class HttpUtils {
int port = redirectURI.getPort() > 0 ? redirectURI.getPort() : redirectURI.getScheme() int port = redirectURI.getPort() > 0 ? redirectURI.getPort() : redirectURI.getScheme()
.equals("https") ? 443 : 80; .equals("https") ? 443 : 80;
String host = redirectURI.getHost(); String host = redirectURI.getHost();
checkState(!host.matches("[/]"), String.format( checkState(host.indexOf('/') == -1, String.format(
"header %s didn't parse an http host correctly: [%s]", hostHeader, host)); "header %s didn't parse an http host correctly: [%s]", hostHeader, host));
URI endPoint = URI.create(String.format("%s://%s:%d", scheme, host, port)); URI endPoint = URI.create(String.format("%s://%s:%d", scheme, host, port));
return endPoint; return endPoint;
@ -165,8 +157,8 @@ public class HttpUtils {
String rest = matcher.group(4); String rest = matcher.group(4);
String account = matcher.group(2); String account = matcher.group(2);
String key = matcher.group(3); String key = matcher.group(3);
return URI return URI.create(String.format("%s://%s:%s@%s", scheme, urlEncode(account),
.create(String.format("%s://%s:%s@%s", scheme, urlEncode(account), urlEncode(key), rest)); urlEncode(key), rest));
} else { } else {
throw new IllegalArgumentException("bad syntax"); throw new IllegalArgumentException("bad syntax");
} }
@ -175,10 +167,6 @@ public class HttpUtils {
} }
} }
public static final Pattern IP_PATTERN = Pattern
.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"
+ "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b");
public static void logRequest(Logger logger, HttpRequest request, String prefix) { public static void logRequest(Logger logger, HttpRequest request, String prefix) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("%s %s", prefix, request.getRequestLine().toString()); logger.debug("%s %s", prefix, request.getRequestLine().toString());

View File

@ -83,7 +83,7 @@ public class TransformingHttpCommandImpl<T> implements TransformingHttpCommand<T
* <p /> * <p />
* This also removes the Host header in order to avoid ssl problems. * This also removes the Host header in order to avoid ssl problems.
*/ */
public void redirect(String host, int port) { public void changeHostAndPortTo(String host, int port) {
UriBuilder builder = UriBuilder.fromUri(request.getEndpoint()); UriBuilder builder = UriBuilder.fromUri(request.getEndpoint());
builder.host(host); builder.host(host);
builder.port(port); builder.port(port);
@ -96,7 +96,7 @@ public class TransformingHttpCommandImpl<T> implements TransformingHttpCommand<T
* *
* @param method * @param method
*/ */
public void redirectAsGet() { public void changeToGETRequest() {
request.setMethod(HttpMethod.GET); request.setMethod(HttpMethod.GET);
} }
@ -130,7 +130,7 @@ public class TransformingHttpCommandImpl<T> implements TransformingHttpCommand<T
} }
@Override @Override
public void redirectPath(String newPath) { public void changePathTo(String newPath) {
request.replacePath(newPath); request.replacePath(newPath);
} }

View File

@ -67,12 +67,12 @@ public class RedirectionRetryHandler implements HttpRetryHandler {
if (redirectionUrl.getHost().equals(command.getRequest().getEndpoint().getHost()) if (redirectionUrl.getHost().equals(command.getRequest().getEndpoint().getHost())
&& redirectionUrl.getPort() == command.getRequest().getEndpoint().getPort()) { && redirectionUrl.getPort() == command.getRequest().getEndpoint().getPort()) {
if (!redirectionUrl.getPath().equals(command.getRequest().getEndpoint().getPath())) { if (!redirectionUrl.getPath().equals(command.getRequest().getEndpoint().getPath())) {
command.redirectPath(redirectionUrl.getPath()); command.changePathTo(redirectionUrl.getPath());
} else { } else {
return backoffHandler.shouldRetryRequest(command, response); return backoffHandler.shouldRetryRequest(command, response);
} }
} else { } else {
command.redirect(redirectionUrl.getHost(), redirectionUrl.getPort()); command.changeHostAndPortTo(redirectionUrl.getHost(), redirectionUrl.getPort());
} }
return true; return true;
} else { } else {

View File

@ -50,7 +50,7 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Resource @Resource
@Named(HttpConstants.HTTP_HEADERS_LOGGER) @Named(HttpConstants.LOGGER_HTTP_HEADERS)
protected Logger headerLog = Logger.NULL; protected Logger headerLog = Logger.NULL;
private final HttpWire wire; private final HttpWire wire;

View File

@ -37,7 +37,7 @@ import org.jclouds.logging.internal.Wire;
public class HttpWire extends Wire { public class HttpWire extends Wire {
@Resource @Resource
@Named(HttpConstants.HTTP_WIRE_LOGGER) @Named(HttpConstants.LOGGER_HTTP_WIRE)
Logger wireLog = Logger.NULL; Logger wireLog = Logger.NULL;
@Inject @Inject

View File

@ -37,7 +37,7 @@ import org.jclouds.logging.internal.Wire;
public class SignatureWire extends Wire { public class SignatureWire extends Wire {
@Resource @Resource
@Named(HttpConstants.SIGNATURE_LOGGER) @Named(HttpConstants.LOGGER_SIGNATURE)
Logger signatureLog = Logger.NULL; Logger signatureLog = Logger.NULL;
@Inject @Inject

View File

@ -19,14 +19,35 @@
package org.jclouds.http.pool; package org.jclouds.http.pool;
/** /**
* // TODO: Adrian: Document this! * Properties used in pooling http engines
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface PoolConstants { public interface PoolConstants {
/**
* Integer property. default (12)
* <p/>
* Limits the amount of connections per host.
*/
public static final String PROPERTY_POOL_MAX_CONNECTIONS = "jclouds.pool.max_connections"; public static final String PROPERTY_POOL_MAX_CONNECTIONS = "jclouds.pool.max_connections";
/**
* Integer property. default (12)
* <p/>
* Amount of threads servicing the I/O of http connections
*/
public static final String PROPERTY_POOL_IO_WORKER_THREADS = "jclouds.http.pool.io_worker_threads"; public static final String PROPERTY_POOL_IO_WORKER_THREADS = "jclouds.http.pool.io_worker_threads";
public static final String PROPERTY_POOL_REQUEST_INVOKER_THREADS = "jclouds.http.pool.request_invoker_threads";
/**
* Integer property. default (2)
* <p/>
* Maximum amount of http session failures before a pool is disabled.
*/
public static final String PROPERTY_POOL_MAX_SESSION_FAILURES = "jclouds.http.pool.max_session_failures"; public static final String PROPERTY_POOL_MAX_SESSION_FAILURES = "jclouds.http.pool.max_session_failures";
/**
* Integer property. default (75)
* <p/>
* Maximum amount of times to re-use an http connection. Services like Amazon S3 throw errors if
* connections are reused too many times.
*/
public static final String PROPERTY_POOL_MAX_CONNECTION_REUSE = "jclouds.http.pool.max_connection_reuse"; public static final String PROPERTY_POOL_MAX_CONNECTION_REUSE = "jclouds.http.pool.max_connection_reuse";
} }

View File

@ -20,6 +20,7 @@ package org.jclouds.rest.internal;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Utils.replaceTokens;
import java.io.InputStream; import java.io.InputStream;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
@ -436,7 +437,7 @@ public class RestAnnotationProcessor<T> {
String key = indexOfFirstEquals == -1 ? parts[partIndex] : parts[partIndex].substring( String key = indexOfFirstEquals == -1 ? parts[partIndex] : parts[partIndex].substring(
0, indexOfFirstEquals); 0, indexOfFirstEquals);
String value = indexOfFirstEquals == -1 ? null : parts[partIndex] String value = indexOfFirstEquals == -1 ? null : parts[partIndex]
.substring(indexOfFirstEquals+1); .substring(indexOfFirstEquals + 1);
map.put(key, value); map.put(key, value);
} }
} }
@ -902,13 +903,6 @@ public class RestAnnotationProcessor<T> {
} }
private String replaceTokens(String value, Collection<Entry<String, String>> tokenValues) {
for (Entry<String, String> tokenValue : tokenValues) {
value = value.replaceAll("\\{" + tokenValue.getKey() + "\\}", tokenValue.getValue());
}
return value;
}
private Map<String, String> convertUnsafe(Multimap<String, String> in) { private Map<String, String> convertUnsafe(Multimap<String, String> in) {
Map<String, String> out = Maps.newLinkedHashMap(); Map<String, String> out = Maps.newLinkedHashMap();
for (Entry<String, String> entry : in.entries()) { for (Entry<String, String> entry : in.entries()) {

View File

@ -0,0 +1,79 @@
/**
*
* 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.util;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.regex.Pattern;
import com.google.common.base.Function;
import com.google.common.collect.MapMaker;
/**
*
* @author Adrian Cole
*/
public class Patterns {
public static final Pattern TWO_SPACE_PATTERN = Pattern.compile(" ");
public static final Pattern URL_ENCODED_PATTERN = Pattern.compile(".*%[a-fA-F0-9][a-fA-F0-9].*");
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
public static final Pattern PATTERN_THAT_BREAKS_URI = Pattern.compile("[a-z0-9]+://.*/.*@.*");
public static final Pattern PLUS_PATTERN = Pattern.compile("\\+");
public static final Pattern STAR_PATTERN = Pattern.compile("\\*");
public static final Pattern _7E_PATTERN = Pattern.compile("%7E");
public static final Pattern NEWLINE_PATTERN = Pattern.compile("\r?\n");
public static final Pattern SLASH_PATTERN = Pattern.compile("[/]");
public static final Pattern IP_PATTERN = Pattern
.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"
+ "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b");
public static final Pattern LEADING_SLASHES = Pattern.compile("^[/]+");
public static final Pattern TRAILING_SLASHES = Pattern.compile("[/]*$");
public final static Map<Character, Pattern> CHAR_TO_ENCODED_PATTERN = new MapMaker()
.makeComputingMap(new Function<Character, Pattern>() {
public Pattern apply(Character plain) {
try {
String encoded = URLEncoder.encode(plain + "", "UTF-8");
return Pattern.compile(encoded);
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Bad encoding on input: " + plain, e);
}
}
});
public final static Map<Character, Pattern> CHAR_TO_PATTERN = new MapMaker()
.makeComputingMap(new Function<Character, Pattern>() {
public Pattern apply(Character plain) {
return Pattern.compile(plain + "");
}
});
public final static Map<String, Pattern> TOKEN_TO_PATTERN = new MapMaker()
.makeComputingMap(new Function<String, Pattern>() {
public Pattern apply(String tokenValue) {
return Pattern.compile("\\{" + tokenValue + "\\}");
}
});
}

View File

@ -19,12 +19,16 @@
package org.jclouds.util; package org.jclouds.util;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Patterns.CHAR_TO_PATTERN;
import static org.jclouds.util.Patterns.TOKEN_TO_PATTERN;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -46,6 +50,33 @@ import com.google.common.io.OutputSupplier;
public class Utils { public class Utils {
public static final String UTF8_ENCODING = "UTF-8"; public static final String UTF8_ENCODING = "UTF-8";
public static String replaceTokens(String value, Collection<Entry<String, String>> tokenValues) {
for (Entry<String, String> tokenValue : tokenValues) {
value = replaceAll(value, TOKEN_TO_PATTERN.get(tokenValue.getKey()), tokenValue.getValue());
}
return value;
}
public static String replaceAll(String returnVal, Pattern pattern, String replace) {
Matcher m = pattern.matcher(returnVal);
returnVal = m.replaceAll(replace);
return returnVal;
}
public static String replaceAll(String input, char ifMatch, Pattern pattern, String replacement) {
if (input.indexOf(ifMatch) != -1) {
input = pattern.matcher(input).replaceAll(replacement);
}
return input;
}
public static String replaceAll(String input, char match, String replacement) {
if (input.indexOf(match) != -1) {
input = CHAR_TO_PATTERN.get(match).matcher(input).replaceAll(replacement);
}
return input;
}
/** /**
* Returns a factory that will supply instances of {@link OutputStream} that read from the given * Returns a factory that will supply instances of {@link OutputStream} that read from the given
* outputStream. * outputStream.
@ -80,7 +111,6 @@ public class Utils {
@Resource @Resource
protected static Logger logger = Logger.NULL; protected static Logger logger = Logger.NULL;
public static String toStringAndClose(InputStream input) throws IOException { public static String toStringAndClose(InputStream input) throws IOException {
try { try {
return new String(ByteStreams.toByteArray(input), Charsets.UTF_8); return new String(ByteStreams.toByteArray(input), Charsets.UTF_8);

View File

@ -36,7 +36,6 @@ public class HttpPropertiesBuilderTest {
int poolMaxClientReuse = 3932; int poolMaxClientReuse = 3932;
int poolMaxClients = 3382; int poolMaxClients = 3382;
int poolMaxSessionFailures = 857; int poolMaxSessionFailures = 857;
int poolRequestInvokerThreads = 8362;
HttpPropertiesBuilder builder = new HttpPropertiesBuilder(new Properties()); HttpPropertiesBuilder builder = new HttpPropertiesBuilder(new Properties());
builder.withHttpMaxRetries(httpMaxRetries); builder.withHttpMaxRetries(httpMaxRetries);
@ -45,6 +44,5 @@ public class HttpPropertiesBuilderTest {
builder.withPoolMaxClientReuse(poolMaxClientReuse); builder.withPoolMaxClientReuse(poolMaxClientReuse);
builder.withPoolMaxClients(poolMaxClients); builder.withPoolMaxClients(poolMaxClients);
builder.withPoolMaxSessionFailures(poolMaxSessionFailures); builder.withPoolMaxSessionFailures(poolMaxSessionFailures);
builder.withPoolRequestInvokerThreads(poolRequestInvokerThreads);
} }
} }

View File

@ -158,7 +158,7 @@ public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorServic
HttpRequest request = command.getRequest(); HttpRequest request = command.getRequest();
String hostHeader = request.getFirstHeaderOrNull(HttpHeaders.HOST); String hostHeader = request.getFirstHeaderOrNull(HttpHeaders.HOST);
if (hostHeader != null) { if (hostHeader != null) {
command.redirect(hostHeader, request.getEndpoint().getPort()); command.changeHostAndPortTo(hostHeader, request.getEndpoint().getPort());
} }
} }

View File

@ -208,16 +208,29 @@ public class NioHttpCommandConnectionPool extends HttpCommandConnectionPool<NHtt
class NHttpClientConnectionPoolSessionRequestCallback implements SessionRequestCallback { class NHttpClientConnectionPoolSessionRequestCallback implements SessionRequestCallback {
/**
* {@inheritDoc}
*/
@Override
public void completed(SessionRequest request) { public void completed(SessionRequest request) {
} }
/**
* @see releaseConnectionAndSetResponseException
*/
@Override
public void cancelled(SessionRequest request) { public void cancelled(SessionRequest request) {
releaseConnectionAndSetResponseException(request, new CancellationException( releaseConnectionAndSetResponseException(request, new CancellationException(
"Cancelled request: " + request.getRemoteAddress())); "Cancelled request: " + request.getRemoteAddress()));
} }
private void releaseConnectionAndSetResponseException(SessionRequest request, Exception e) { /**
* Releases a connection and associates the current exception with the request using the
* session.
*/
@VisibleForTesting
void releaseConnectionAndSetResponseException(SessionRequest request, Exception e) {
allConnections.release(); allConnections.release();
TransformingHttpCommand<?> frequest = (TransformingHttpCommand<?>) request.getAttachment(); TransformingHttpCommand<?> frequest = (TransformingHttpCommand<?>) request.getAttachment();
if (frequest != null) { if (frequest != null) {
@ -225,6 +238,12 @@ public class NioHttpCommandConnectionPool extends HttpCommandConnectionPool<NHtt
} }
} }
/**
* Disables the pool, if {@code maxSessionFailures} is reached}
*
* @see releaseConnectionAndSetResponseException
*/
@Override
public void failed(SessionRequest request) { public void failed(SessionRequest request) {
int count = currentSessionFailures.getAndIncrement(); int count = currentSessionFailures.getAndIncrement();
releaseConnectionAndSetResponseException(request, request.getException()); releaseConnectionAndSetResponseException(request, request.getException());
@ -237,6 +256,10 @@ public class NioHttpCommandConnectionPool extends HttpCommandConnectionPool<NHtt
} }
/**
* @see releaseConnectionAndSetResponseException
*/
@Override
public void timeout(SessionRequest request) { public void timeout(SessionRequest request) {
releaseConnectionAndSetResponseException(request, new TimeoutException("Timeout on: " releaseConnectionAndSetResponseException(request, new TimeoutException("Timeout on: "
+ request.getRemoteAddress())); + request.getRemoteAddress()));

View File

@ -63,7 +63,7 @@ public class NioHttpCommandExecutionHandler implements NHttpRequestExecutionHand
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Resource @Resource
@Named(HttpConstants.HTTP_HEADERS_LOGGER) @Named(HttpConstants.LOGGER_HTTP_HEADERS)
protected Logger headerLog = Logger.NULL; protected Logger headerLog = Logger.NULL;
@Inject @Inject

View File

@ -18,12 +18,15 @@
*/ */
package org.jclouds.mezeo.pcs2.blobstore.functions; package org.jclouds.mezeo.pcs2.blobstore.functions;
import java.util.regex.Pattern;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
import org.jclouds.mezeo.pcs2.domain.FileInfo; import org.jclouds.mezeo.pcs2.domain.FileInfo;
import org.jclouds.util.Utils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -32,10 +35,12 @@ import com.google.common.base.Function;
*/ */
@Singleton @Singleton
public class FileInfoToBlobMetadata implements Function<FileInfo, MutableBlobMetadata> { public class FileInfoToBlobMetadata implements Function<FileInfo, MutableBlobMetadata> {
public static final Pattern OBJECTS_PATTERN = Pattern.compile(".*objects/");
public MutableBlobMetadata apply(FileInfo from) { public MutableBlobMetadata apply(FileInfo from) {
MutableBlobMetadata to = new MutableBlobMetadataImpl(); MutableBlobMetadata to = new MutableBlobMetadataImpl();
if (from.getUrl() != null) { if (from.getUrl() != null) {
to.setId(from.getUrl().getPath().replaceAll(".*objects/", "")); to.setId(Utils.replaceAll(from.getUrl().getPath(), OBJECTS_PATTERN, ""));
} }
to.setUri(from.getUrl()); to.setUri(from.getUrl());
to.setName(from.getName()); to.setName(from.getName());

View File

@ -22,6 +22,7 @@ import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.regex.Pattern;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -34,6 +35,7 @@ import org.jclouds.mezeo.pcs2.domain.ResourceInfo;
import org.jclouds.mezeo.pcs2.domain.internal.ContainerInfoImpl; import org.jclouds.mezeo.pcs2.domain.internal.ContainerInfoImpl;
import org.jclouds.mezeo.pcs2.domain.internal.ContainerListImpl; import org.jclouds.mezeo.pcs2.domain.internal.ContainerListImpl;
import org.jclouds.mezeo.pcs2.domain.internal.FileInfoImpl; import org.jclouds.mezeo.pcs2.domain.internal.FileInfoImpl;
import org.jclouds.util.Utils;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -171,12 +173,14 @@ public class ContainerHandler extends ParseSax.HandlerWithResult<ContainerList>
} else if (qName.equals("metadata-item")) { } else if (qName.equals("metadata-item")) {
int index = attributes.getIndex("xlink:href"); int index = attributes.getIndex("xlink:href");
if (index != -1) { if (index != -1) {
String key = attributes.getValue(index).replaceAll(".*/metadata/", ""); String key = Utils.replaceAll(attributes.getValue(index), METADATA_PATTERN, "");
metadataItems.put(key.toLowerCase(), URI.create(attributes.getValue(index))); metadataItems.put(key.toLowerCase(), URI.create(attributes.getValue(index)));
} }
} }
} }
public final Pattern METADATA_PATTERN = Pattern.compile(".*/metadata/");
@Override @Override
public void endElement(String uri, String name, String qName) { public void endElement(String uri, String name, String qName) {
if (qName.equals("contents")) { if (qName.equals("contents")) {

View File

@ -21,6 +21,7 @@ package org.jclouds.mezeo.pcs2.xml;
import java.net.URI; import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern;
import javax.inject.Inject; import javax.inject.Inject;
@ -28,6 +29,7 @@ import org.jclouds.date.DateService;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.mezeo.pcs2.domain.FileInfoWithMetadata; import org.jclouds.mezeo.pcs2.domain.FileInfoWithMetadata;
import org.jclouds.mezeo.pcs2.domain.internal.FileInfoWithMetadataImpl; import org.jclouds.mezeo.pcs2.domain.internal.FileInfoWithMetadataImpl;
import org.jclouds.util.Utils;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -37,6 +39,9 @@ import com.google.common.collect.Maps;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class FileHandler extends ParseSax.HandlerWithResult<FileInfoWithMetadata> { public class FileHandler extends ParseSax.HandlerWithResult<FileInfoWithMetadata> {
private static final Pattern CONTENT_PATTERN = Pattern.compile("/content");
private static final Pattern METADATA_PATTERN = Pattern.compile(".*/metadata/");
protected Map<String, URI> metadataItems = Maps.newHashMap(); protected Map<String, URI> metadataItems = Maps.newHashMap();
protected URI currentUrl; protected URI currentUrl;
@ -82,7 +87,8 @@ public class FileHandler extends ParseSax.HandlerWithResult<FileInfoWithMetadata
int index = attributes.getIndex("xlink:href"); int index = attributes.getIndex("xlink:href");
if (index != -1) { if (index != -1) {
currentContent = URI.create(attributes.getValue(index)); currentContent = URI.create(attributes.getValue(index));
currentUrl = URI.create(attributes.getValue(index).replaceAll("/content", "")); currentUrl = URI.create(Utils.replaceAll(attributes.getValue(index), CONTENT_PATTERN,
""));
} }
} else if (qName.equals("permissions")) { } else if (qName.equals("permissions")) {
int index = attributes.getIndex("xlink:href"); int index = attributes.getIndex("xlink:href");
@ -109,12 +115,11 @@ public class FileHandler extends ParseSax.HandlerWithResult<FileInfoWithMetadata
int index = attributes.getIndex("xlink:href"); int index = attributes.getIndex("xlink:href");
if (index != -1) { if (index != -1) {
currentMetadata = URI.create(attributes.getValue(index)); currentMetadata = URI.create(attributes.getValue(index));
} }
} else if (qName.equals("metadata-item")) { } else if (qName.equals("metadata-item")) {
int index = attributes.getIndex("xlink:href"); int index = attributes.getIndex("xlink:href");
if (index != -1) { if (index != -1) {
String key = attributes.getValue(index).replaceAll(".*/metadata/", ""); String key = Utils.replaceAll(attributes.getValue(index), METADATA_PATTERN, "");
metadataItems.put(key.toLowerCase(), URI.create(attributes.getValue(index))); metadataItems.put(key.toLowerCase(), URI.create(attributes.getValue(index)));
} }
} }

View File

@ -28,6 +28,7 @@ import org.jclouds.rackspace.cloudfiles.blobstore.functions.ResourceToObjectInfo
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata; import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
import org.jclouds.rest.InvocationContext; import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.Utils;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -58,7 +59,8 @@ public class ParseObjectInfoFromHeaders implements
MutableObjectInfoWithMetadata to = blobToObjectInfo.apply(base); MutableObjectInfoWithMetadata to = blobToObjectInfo.apply(base);
String eTagHeader = from.getFirstHeaderOrNull("Etag"); String eTagHeader = from.getFirstHeaderOrNull("Etag");
if (eTagHeader != null) { if (eTagHeader != null) {
to.setHash(encryptionService.fromHexString(eTagHeader.replaceAll("\"", ""))); String hashString = Utils.replaceAll(eTagHeader, '"', "");
to.setHash(encryptionService.fromHexString(hashString));
} }
return to; return to;
} }

View File

@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.jclouds.scriptbuilder.util.Utils; import org.jclouds.scriptbuilder.util.Utils;
@ -182,8 +183,10 @@ public class CreateRunScript implements Statement {
"echo %s%s%s>>%s{lf}", quote, line, quote, runScript))); "echo %s%s%s>>%s{lf}", quote, line, quote, runScript)));
} }
public static final Pattern REDIRECT_FD_PATTERN = Pattern.compile(".*[0-2]>>.*");
static String addSpaceToEnsureWeDontAccidentallyRedirectFd(String line) { static String addSpaceToEnsureWeDontAccidentallyRedirectFd(String line) {
return line.matches(".*[0-2]>>.*") ? line.replace(">>", " >>") : line; return REDIRECT_FD_PATTERN.matcher(line).matches() ? line.replace(">>", " >>") : line;
} }
} }

View File

@ -20,6 +20,8 @@ package org.jclouds.vfs.provider.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.util.Patterns.LEADING_SLASHES;
import static org.jclouds.util.Patterns.TRAILING_SLASHES;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -31,6 +33,7 @@ import java.nio.channels.Channels;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern;
import org.apache.commons.vfs.FileName; import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileNotFolderException; import org.apache.commons.vfs.FileNotFolderException;
@ -58,6 +61,7 @@ import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.IsDirectoryStrategy; import org.jclouds.blobstore.strategy.IsDirectoryStrategy;
import org.jclouds.blobstore.strategy.internal.MarkersIsDirectoryStrategy; import org.jclouds.blobstore.strategy.internal.MarkersIsDirectoryStrategy;
import org.jclouds.blobstore.util.BlobStoreUtils; import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.util.Utils;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
@ -75,6 +79,7 @@ public class BlobStoreFileObject extends AbstractFileObject {
private static final IsDirectoryStrategy isDirectoryStrategy = new MarkersIsDirectoryStrategy(); private static final IsDirectoryStrategy isDirectoryStrategy = new MarkersIsDirectoryStrategy();
private static final ResourceMetadataToRelativePathResourceMetadata resource2Directory = new ResourceMetadataToRelativePathResourceMetadata(); private static final ResourceMetadataToRelativePathResourceMetadata resource2Directory = new ResourceMetadataToRelativePathResourceMetadata();
private static final Logger logger = Logger.getLogger(BlobStoreFileObject.class); private static final Logger logger = Logger.getLogger(BlobStoreFileObject.class);
private static final Pattern UNDESCRIBED = Pattern.compile("[^/]*//*");
public BlobStoreFileObject(FileName fileName, BlobStoreFileSystem fileSystem, public BlobStoreFileObject(FileName fileName, BlobStoreFileSystem fileSystem,
BlobStore blobStore, String container) throws FileSystemException { BlobStore blobStore, String container) throws FileSystemException {
@ -138,7 +143,7 @@ public class BlobStoreFileObject extends AbstractFileObject {
} }
String getNameTrimLeadingSlashes() { String getNameTrimLeadingSlashes() {
return getName().getPath().replaceAll("^[/]+", ""); return Utils.replaceAll(getName().getPath(), LEADING_SLASHES, "");
} }
@Override @Override
@ -176,7 +181,7 @@ public class BlobStoreFileObject extends AbstractFileObject {
if (isDirectoryStrategy.execute(md)) { if (isDirectoryStrategy.execute(md)) {
md = resource2Directory.apply(md); md = resource2Directory.apply(md);
} }
String childName = md.getName().replaceAll("[^/]*//*", ""); String childName = Utils.replaceAll(md.getName(), UNDESCRIBED, "");
BlobStoreFileObject fo = (BlobStoreFileObject) FileObjectUtils BlobStoreFileObject fo = (BlobStoreFileObject) FileObjectUtils
.getAbstractFileObject(getFileSystem().resolveFile( .getAbstractFileObject(getFileSystem().resolveFile(
getFileSystem().getFileSystemManager().resolveName(getName(), getFileSystem().getFileSystemManager().resolveName(getName(),
@ -323,7 +328,7 @@ public class BlobStoreFileObject extends AbstractFileObject {
} }
public String trimLeadingAndTrailingSlashes(String in) { public String trimLeadingAndTrailingSlashes(String in) {
return in.replaceAll("^[/]*", "").replaceAll("[/]*$", ""); return Utils.replaceAll(Utils.replaceAll(in, LEADING_SLASHES, ""), TRAILING_SLASHES, "");
} }
@Override @Override

View File

@ -19,6 +19,7 @@
package org.jclouds.vcloud.terremark.binders; package org.jclouds.vcloud.terremark.binders;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Utils.replaceTokens;
import java.util.Map; import java.util.Map;
@ -29,6 +30,10 @@ import javax.inject.Singleton;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder; import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToStringPayload; import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.util.Patterns;
import org.jclouds.util.Utils;
import com.google.common.collect.ImmutableMap;
/** /**
* *
@ -51,14 +56,11 @@ public class BindAddInternetServiceToXmlPayload implements MapBinder {
String port = checkNotNull(postParams.get("port"), "port parameter not present"); String port = checkNotNull(postParams.get("port"), "port parameter not present");
String enabled = checkNotNull(postParams.get("enabled"), "enabled parameter not present"); String enabled = checkNotNull(postParams.get("enabled"), "enabled parameter not present");
String description = postParams.get("description"); String description = postParams.get("description");
String payload = replaceTokens(xmlTemplate, ImmutableMap.of("name", name, "protocol",
String payload = xmlTemplate.replaceAll("\\{name\\}", name); protocol, "port", port, "enabled", enabled));
payload = payload.replaceAll("\\{protocol\\}", protocol); payload = Utils.replaceAll(payload, Patterns.TOKEN_TO_PATTERN.get("description"),
payload = payload.replaceAll("\\{port\\}", port); description == null ? "" : String.format("\n <Description>%s</Description>",
payload = payload.replaceAll("\\{enabled\\}", enabled); description));
payload = payload.replaceAll("\\{description\\}", description == null ? "" : String.format(
"\n <Description>%s</Description>", description));
stringBinder.bindToRequest(request, payload); stringBinder.bindToRequest(request, payload);
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.vcloud.terremark.binders; package org.jclouds.vcloud.terremark.binders;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Utils.replaceTokens;
import java.util.Map; import java.util.Map;
@ -29,6 +30,10 @@ import javax.inject.Singleton;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder; import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToStringPayload; import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.util.Patterns;
import org.jclouds.util.Utils;
import com.google.common.collect.ImmutableMap;
/** /**
* *
@ -52,13 +57,11 @@ public class BindAddNodeServiceToXmlPayload implements MapBinder {
String enabled = checkNotNull(postParams.get("enabled"), "enabled parameter not present"); String enabled = checkNotNull(postParams.get("enabled"), "enabled parameter not present");
String description = postParams.get("description"); String description = postParams.get("description");
String payload = xmlTemplate.replaceAll("\\{ipAddress\\}", ipAddress); String payload = replaceTokens(xmlTemplate, ImmutableMap.of("name", name, "ipAddress",
payload = payload.replaceAll("\\{name\\}", name); ipAddress, "port", port, "enabled", enabled));
payload = payload.replaceAll("\\{port\\}", port); payload = Utils.replaceAll(payload, Patterns.TOKEN_TO_PATTERN.get("description"),
payload = payload.replaceAll("\\{enabled\\}", enabled); description == null ? "" : String.format("\n <Description>%s</Description>",
payload = payload.replaceAll("\\{description\\}", description == null ? "" : String.format( description));
"\n <Description>%s</Description>", description));
stringBinder.bindToRequest(request, payload); stringBinder.bindToRequest(request, payload);
} }

View File

@ -21,6 +21,7 @@ package org.jclouds.vcloud.terremark.domain;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -36,6 +37,8 @@ public class VAppConfiguration {
private List<Long> disks = Lists.newArrayList(); private List<Long> disks = Lists.newArrayList();
private List<Integer> disksToDelete = Lists.newArrayList(); private List<Integer> disksToDelete = Lists.newArrayList();
public static final Pattern NAME_PATTERN = Pattern.compile("^[a-zA-Z][-a-zA-Z0-9]+");
/** /**
* The vApp name has the following requirements: Name can use uppercase and/or lowercase letters. * The vApp name has the following requirements: Name can use uppercase and/or lowercase letters.
* Name can contain numbers or hyphens (-). Name may only begin with a letter. A maximum of 15 * Name can contain numbers or hyphens (-). Name may only begin with a letter. A maximum of 15
@ -44,7 +47,7 @@ public class VAppConfiguration {
*/ */
public VAppConfiguration changeNameTo(String name) { public VAppConfiguration changeNameTo(String name) {
checkArgument( checkArgument(
name.matches("^[a-zA-Z][-a-zA-Z0-9]+"), NAME_PATTERN.matcher(name).matches(),
"Name can use uppercase and/or lowercase letters, numbers or hyphens (-). Name may only begin with a letter."); "Name can use uppercase and/or lowercase letters, numbers or hyphens (-). Name may only begin with a letter.");
checkArgument(name.length() <= 15, "A maximum of 15 characters are allowed."); checkArgument(name.length() <= 15, "A maximum of 15 characters are allowed.");
this.name = name; this.name = name;

View File

@ -19,6 +19,7 @@
package org.jclouds.vcloud.terremark.functions; package org.jclouds.vcloud.terremark.functions;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.regex.Pattern;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -34,6 +35,8 @@ import com.google.common.base.Function;
*/ */
@Singleton @Singleton
public class ReturnVoidOnDeleteDefaultIp implements Function<Exception, Void> { public class ReturnVoidOnDeleteDefaultIp implements Function<Exception, Void> {
public static final Pattern MESSAGE_PATTERN = Pattern
.compile(".*Cannot release this Public IP as it is default oubound IP.*");
static final Void v; static final Void v;
static { static {
@ -50,10 +53,8 @@ public class ReturnVoidOnDeleteDefaultIp implements Function<Exception, Void> {
public Void apply(Exception from) { public Void apply(Exception from) {
if (from instanceof HttpResponseException) { if (from instanceof HttpResponseException) {
HttpResponseException hre = (HttpResponseException) from; HttpResponseException hre = (HttpResponseException) from;
if (hre.getResponse().getStatusCode() == 503 if (hre.getResponse().getStatusCode() == 503 || hre.getResponse().getStatusCode() == 401
|| hre.getResponse().getStatusCode() == 401 || MESSAGE_PATTERN.matcher(hre.getMessage()).matches())
|| hre.getMessage().matches(
".*Cannot release this Public IP as it is default oubound IP.*"))
return v; return v;
} }
return null; return null;