Merge pull request #1173 from jclouds/single-use

refactored out classes only used once
This commit is contained in:
Adrian Cole 2013-01-12 18:00:02 -08:00
commit 103d327354
56 changed files with 421 additions and 1819 deletions

View File

@ -17,6 +17,7 @@
* under the License.
*/
package org.jclouds.atmos.util;
import static com.google.common.base.Preconditions.checkState;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@ -31,6 +32,7 @@ import org.jclouds.atmos.domain.AtmosObject;
import org.jclouds.atmos.filters.SignRequest;
import org.jclouds.atmos.options.PutOptions;
import org.jclouds.atmos.xml.ErrorHandler;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.crypto.Crypto;
@ -38,9 +40,9 @@ import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.Assertions;
import org.jclouds.predicates.RetryablePredicate;
import com.google.common.base.Supplier;
import com.google.common.base.Predicate;
/**
* Encryption, Hashing, and IO Utilities needed to sign and verify Atmos Storage requests and
@ -78,25 +80,23 @@ public class AtmosUtils {
sync.createFile(container, object, options);
} catch(KeyAlreadyExistsException e) {
deleteAndEnsureGone(sync, path);
deletePathAndEnsureGone(sync, path);
sync.createFile(container, object, options);
}
return path;
}
public static void deleteAndEnsureGone(final AtmosClient sync, final String path) {
try {
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
sync.deletePath(path);
return !sync.pathExists(path);
public static void deletePathAndEnsureGone(final AtmosClient sync, String path) {
checkState(new RetryablePredicate<String>(new Predicate<String>() {
public boolean apply(String in) {
try {
sync.deletePath(in);
return !sync.pathExists(in);
} catch (ContainerNotFoundException e) {
return true;
}
}, 3000)) {
throw new IllegalStateException(path + " still exists after deleting!");
}
} catch (InterruptedException e) {
throw new IllegalStateException(path + " interrupted during deletion!", e);
}
}, 3000).apply(path), "%s still exists after deleting!", path);
}
public AtmosError parseAtmosErrorFromContent(HttpCommand command, HttpResponse response, String content)

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.atmos;
import static com.google.common.base.Preconditions.checkState;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
@ -34,17 +35,18 @@ import org.jclouds.atmos.domain.DirectoryEntry;
import org.jclouds.atmos.domain.FileType;
import org.jclouds.atmos.domain.SystemMetadata;
import org.jclouds.atmos.options.ListOptions;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyAlreadyExistsException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.http.HttpResponseException;
import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.InputStreamPayload;
import org.jclouds.util.Assertions;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@ -320,17 +322,21 @@ public class AtmosClientLiveTest extends BaseBlobStoreIntegrationTest {
}
protected void deleteConsistencyAware(final String path) throws InterruptedException, ExecutionException,
protected void deleteConsistencyAware(String path) throws InterruptedException, ExecutionException,
TimeoutException {
try {
getApi().deletePath(path);
} catch (KeyNotFoundException ex) {
}
assert Assertions.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
return !getApi().pathExists(path);
checkState(new RetryablePredicate<String>(new Predicate<String>() {
public boolean apply(String in) {
try {
return !getApi().pathExists(in);
} catch (ContainerNotFoundException e) {
return true;
}
}
}, INCONSISTENCY_WINDOW);
}, INCONSISTENCY_WINDOW).apply(path), "%s still exists after deleting!", path);
}
protected void retryAndCheckSystemMetadataAndPutIfPresentReplaceStrategy(AtmosObject object) throws Exception {

View File

@ -17,6 +17,8 @@
* under the License.
*/
package org.jclouds.ec2.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
@ -28,7 +30,6 @@ import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTa
import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsValuesOfEmptyString;
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
import static org.jclouds.ec2.util.Tags.resourceToTagsAsMap;
import static org.jclouds.util.Preconditions2.checkNotEmpty;
import java.util.Map;
import java.util.Map.Entry;
@ -202,8 +203,8 @@ public class EC2ComputeService extends BaseComputeService {
*/
@VisibleForTesting
void deleteSecurityGroup(String region, String group) {
checkNotEmpty(region, "region");
checkNotEmpty(group, "group");
checkNotNull(emptyToNull(region), "region must be defined");
checkNotNull(emptyToNull(group), "group must be defined");
String groupName = namingConvention.create().sharedNameForGroup(group);
if (client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {

View File

@ -22,6 +22,7 @@ import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.emptyToNull;
import java.util.List;
import java.util.Map;
@ -36,7 +37,6 @@ import org.jclouds.ec2.domain.BlockDeviceMapping.MapNewVolumeToDevice;
import org.jclouds.ec2.domain.BlockDeviceMapping.UnmapDeviceNamed;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
@ -144,7 +144,7 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
public EC2TemplateOptions securityGroups(Iterable<String> groupNames) {
checkArgument(Iterables.size(groupNames) > 0, "you must specify at least one security group");
for (String groupId : groupNames)
Preconditions2.checkNotEmpty(groupId, "all security groups must be non-empty");
checkNotNull(emptyToNull(groupId), "all security groups must be non-empty");
this.groupNames = ImmutableSet.copyOf(groupNames);
return this;
}
@ -163,10 +163,8 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
* Specifies the keypair used to run instances with
*/
public EC2TemplateOptions keyPair(String keyPair) {
checkNotNull(keyPair, "use noKeyPair option to request boot without a keypair");
checkState(!noKeyPair, "you cannot specify both options keyPair and noKeyPair");
Preconditions2.checkNotEmpty(keyPair, "keypair must be non-empty");
this.keyPair = keyPair;
this.keyPair = checkNotNull(emptyToNull(keyPair), "use noKeyPair option to request boot without a keypair");
return this;
}

View File

@ -20,9 +20,9 @@ package org.jclouds.ec2.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.util.Preconditions2;
/**
*
@ -101,7 +101,7 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping>{
@Nullable Integer sizeInGib, @Nullable Boolean noDevice, @Nullable Boolean deleteOnTermination) {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "the deviceName must be non-empty");
checkNotNull(emptyToNull(deviceName), "deviceName must be defined");
if (sizeInGib != null) {
checkArgument(sizeInGib >= VOLUME_SIZE_MIN_VALUE && sizeInGib <= VOLUME_SIZE_MAX_VALUE,
@ -205,8 +205,7 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping>{
public MapEBSSnapshotToDevice(String deviceName, String snapshotId, @Nullable Integer sizeInGib,
@Nullable Boolean deleteOnTermination) {
super(deviceName, null, snapshotId, sizeInGib, null, deleteOnTermination);
checkNotNull(snapshotId, "snapshotId cannot be null");
Preconditions2.checkNotEmpty(snapshotId, "the snapshotId must be non-empty");
checkNotNull(emptyToNull(snapshotId), "snapshotId must be defined");
}
}
@ -220,8 +219,7 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping>{
public static class MapEphemeralDeviceToDevice extends BlockDeviceMapping {
public MapEphemeralDeviceToDevice(String deviceName, String virtualName) {
super(deviceName, virtualName, null, null, null, null);
checkNotNull(virtualName, "virtualName cannot be null");
Preconditions2.checkNotEmpty(virtualName, "the virtualName must be non-empty");
checkNotNull(emptyToNull(virtualName), "virtualName must be defined");
}
}

View File

@ -46,7 +46,7 @@ public class EC2TemplateOptionsTest {
assertEquals(options.as(EC2TemplateOptions.class), options);
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "all security groups must be non-empty")
public void testsecurityGroupsIterableBadFormat() {
EC2TemplateOptions options = new EC2TemplateOptions();
options.securityGroups(ImmutableSet.of("group1", ""));
@ -72,7 +72,7 @@ public class EC2TemplateOptionsTest {
assertEquals(options.getGroups(), ImmutableSet.of("group1", "group2"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "all security groups must be non-empty")
public void testsecurityGroupsVarArgsBadFormat() {
EC2TemplateOptions options = new EC2TemplateOptions();
options.securityGroups("mygroup", "");
@ -104,7 +104,7 @@ public class EC2TemplateOptionsTest {
assertEquals(options.getGroups(), ImmutableSet.of("group1", "group2"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "use noKeyPair option to request boot without a keypair")
public void testkeyPairBadFormat() {
EC2TemplateOptions options = new EC2TemplateOptions();
options.keyPair("");

View File

@ -21,6 +21,7 @@ package org.jclouds.openstack.nova.v2_0.compute.options;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import java.util.Arrays;
import java.util.Map;
@ -28,12 +29,12 @@ import java.util.Set;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
/**
@ -154,7 +155,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
*/
public NovaTemplateOptions securityGroupNames(Iterable<String> securityGroupNames) {
for (String groupName : checkNotNull(securityGroupNames, "securityGroupNames"))
Preconditions2.checkNotEmpty(groupName, "all security groups must be non-empty");
checkNotNull(emptyToNull(groupName), "all security groups must be non-empty");
this.securityGroupNames = Optional.<Set<String>> of(ImmutableSet.copyOf(securityGroupNames));
return this;
}

View File

@ -23,6 +23,7 @@ import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.io.BaseEncoding.base64;
import java.util.List;
@ -37,7 +38,6 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
@ -318,7 +318,7 @@ public class CreateServerOptions implements MapBinder {
*/
public CreateServerOptions securityGroupNames(Iterable<String> securityGroupNames) {
for (String groupName : checkNotNull(securityGroupNames, "securityGroupNames"))
Preconditions2.checkNotEmpty(groupName, "all security groups must be non-empty");
checkNotNull(emptyToNull(groupName), "all security groups must be non-empty");
this.securityGroupNames = ImmutableSet.copyOf(securityGroupNames);
return this;
}

View File

@ -48,7 +48,7 @@ public class NovaTemplateOptionsTest {
assertEquals(options.as(NovaTemplateOptions.class), options);
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "all security groups must be non-empty")
public void testsecurityGroupNamesIterableBadFormat() {
NovaTemplateOptions options = new NovaTemplateOptions();
options.securityGroupNames(ImmutableSet.of("group1", ""));
@ -68,7 +68,7 @@ public class NovaTemplateOptionsTest {
assertEquals(options.getSecurityGroupNames(), Optional.of(ImmutableSet.of("group1", "group2")));
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "all security groups must be non-empty")
public void testsecurityGroupNamesVarArgsBadFormat() {
NovaTemplateOptions options = new NovaTemplateOptions();
options.securityGroupNames("mygroup", "");

View File

@ -19,6 +19,7 @@
package org.jclouds.s3.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Set;
@ -42,6 +43,7 @@ import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.http.options.GetOptions;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.blobstore.functions.BlobToObject;
import org.jclouds.s3.blobstore.functions.BucketToResourceList;
@ -57,9 +59,9 @@ import org.jclouds.s3.options.ListBucketOptions;
import org.jclouds.s3.options.PutBucketOptions;
import org.jclouds.s3.options.PutObjectOptions;
import org.jclouds.s3.util.S3Utils;
import org.jclouds.util.Assertions;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@ -148,38 +150,20 @@ public class S3BlobStore extends BaseBlobStore {
}
/**
* This implementation invokes {@link #deleteAndEnsurePathGone}
*
* @param container
* bucket name
* This implementation invokes {@link #clearContainer} then {@link S3Client#deleteBucketIfEmpty} until it is true.
*/
@Override
public void deleteContainer(String container) {
clearAndDeleteContainer(container);
}
/**
* This implementation invokes {@link #clearContainer} then {@link S3Client#deleteBucketIfEmpty}
* until it is true.
*/
public void clearAndDeleteContainer(final String container) {
try {
//TODO: probably it is better to use a retryable predicate
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
try {
clearContainer(container);
return sync.deleteBucketIfEmpty(container);
} catch (ContainerNotFoundException e) {
return true;
}
protected void deletePathAndEnsureGone(String path) {
checkState(new RetryablePredicate<String>(new Predicate<String>() {
public boolean apply(String in) {
try {
clearContainer(in);
return sync.deleteBucketIfEmpty(in);
} catch (ContainerNotFoundException e) {
return true;
}
}, 30000)) {
throw new IllegalStateException(container + " still exists after deleting!");
}
} catch (InterruptedException e) {
throw new IllegalStateException(container + " interrupted during deletion!", e);
}
}, 30000).apply(path), "%s still exists after deleting!", path);
}
/**

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.s3.blobstore.config;
import static com.google.inject.Scopes.SINGLETON;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
@ -29,21 +31,19 @@ import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.config.BlobStoreMapModule;
import org.jclouds.domain.Location;
import org.jclouds.s3.S3AsyncClient;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.blobstore.S3AsyncBlobStore;
import org.jclouds.s3.blobstore.S3BlobRequestSigner;
import org.jclouds.s3.blobstore.S3BlobStore;
import org.jclouds.s3.blobstore.S3BlobStoreContext;
import org.jclouds.s3.blobstore.functions.LocationFromBucketName;
import org.jclouds.s3.blobstore.internal.BackoffOnNotFoundWhenGetBucketACL;
import org.jclouds.s3.domain.AccessControlList;
import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
/**
@ -57,8 +57,8 @@ public class S3BlobStoreContextModule extends AbstractModule {
protected void configure() {
install(new BlobStoreMapModule());
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
bind(AsyncBlobStore.class).to(S3AsyncBlobStore.class).in(Scopes.SINGLETON);
bind(BlobStore.class).to(S3BlobStore.class).in(Scopes.SINGLETON);
bind(AsyncBlobStore.class).to(S3AsyncBlobStore.class).in(SINGLETON);
bind(BlobStore.class).to(S3BlobStore.class).in(SINGLETON);
bind(new TypeLiteral<Function<String, Location>>() {
}).to(LocationFromBucketName.class);
bindRequestSigner();
@ -68,21 +68,10 @@ public class S3BlobStoreContextModule extends AbstractModule {
bind(BlobRequestSigner.class).to(new TypeLiteral<S3BlobRequestSigner<S3AsyncClient>>() {
});
}
@Provides
@Singleton
protected LoadingCache<String, AccessControlList> bucketAcls(final S3Client client) {
return CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build(
new CacheLoader<String, AccessControlList>() {
@Override
public AccessControlList load(String bucketName) {
return client.getBucketACL(bucketName);
}
@Override
public String toString() {
return "getBucketAcl()";
}
});
protected LoadingCache<String, AccessControlList> bucketAcls(BackoffOnNotFoundWhenGetBucketACL loader) {
return CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build(loader);
}
}

View File

@ -0,0 +1,71 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.s3.blobstore.internal;
import static com.google.common.base.Throwables.propagate;
import javax.inject.Inject;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.domain.AccessControlList;
import com.google.common.annotations.Beta;
import com.google.common.cache.CacheLoader;
@Beta
public class BackoffOnNotFoundWhenGetBucketACL extends CacheLoader<String, AccessControlList> {
private final S3Client client;
private final int maxTries = 5;
@Inject
BackoffOnNotFoundWhenGetBucketACL(S3Client client) {
this.client = client;
}
@Override
public AccessControlList load(String bucketName) {
ResourceNotFoundException last = null;
for (int currentTries = 0; currentTries < maxTries; currentTries++) {
try {
return client.getBucketACL(bucketName);
} catch (ResourceNotFoundException e) {
imposeBackoffExponentialDelay(100l, 200l, 2, currentTries, maxTries);
last = e;
}
}
throw last;
}
private static void imposeBackoffExponentialDelay(long period, long maxPeriod, int pow, int failureCount, int max) {
long delayMs = (long) (period * Math.pow(failureCount, pow));
delayMs = delayMs > maxPeriod ? maxPeriod : delayMs;
try {
Thread.sleep(delayMs);
} catch (InterruptedException e) {
throw propagate(e);
}
}
@Override
public String toString() {
return "getBucketAcl()";
}
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.s3.blobstore.functions;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.testng.Assert.assertEquals;
import org.jclouds.blobstore.domain.MutableStorageMetadata;
@ -25,7 +26,6 @@ import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
import org.jclouds.blobstore.domain.internal.PageSetImpl;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
@ -52,9 +52,8 @@ public class BucketsToStorageMetadataTest {
.description("us-east-1").parent(provider).build();
public void test() {
BucketsToStorageMetadata fn = new BucketsToStorageMetadata(
MoreExecutors.sameThreadExecutor(),
sameThreadExecutor(),
new BucketToResourceMetadata(Functions.forMap(ImmutableMap.<String, Location> of("mycontainer", region))));
MutableStorageMetadata expected = new MutableStorageMetadataImpl();

View File

@ -0,0 +1,82 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.s3.blobstore.internal;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertSame;
import java.util.concurrent.TimeoutException;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.domain.AccessControlList;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.util.concurrent.UncheckedExecutionException;
@Test(groups = "unit", singleThreaded = true, testName = "BackoffOnNotFoundWhenGetBucketACLTest")
public class BackoffOnNotFoundWhenGetBucketACLTest {
private S3Client mock;
@BeforeMethod
public void setUp() {
mock = createMock(S3Client.class);
}
@Test
void testMaxRetriesNotExceededReturnsValue() {
AccessControlList acl = createMock(AccessControlList.class);
int attempts = 5;
BackoffOnNotFoundWhenGetBucketACL backoff = new BackoffOnNotFoundWhenGetBucketACL(mock);
expect(mock.getBucketACL("foo")).andThrow(new ResourceNotFoundException()).times(attempts - 1);
expect(mock.getBucketACL("foo")).andReturn(acl);
replay(mock);
assertSame(backoff.load("foo"), acl);
verify(mock);
}
@Test(expectedExceptions = ResourceNotFoundException.class)
void testMaxRetriesExceededThrowsException() {
int attempts = 5;
BackoffOnNotFoundWhenGetBucketACL backoff = new BackoffOnNotFoundWhenGetBucketACL(mock);
expect(mock.getBucketACL("foo")).andThrow(new ResourceNotFoundException()).times(attempts);
replay(mock);
backoff.load("foo");
}
@Test(expectedExceptions = UncheckedExecutionException.class)
void testDoesntCatchOtherExceptions() {
BackoffOnNotFoundWhenGetBucketACL backoff = new BackoffOnNotFoundWhenGetBucketACL(mock);
expect(mock.getBucketACL("foo")).andThrow(new UncheckedExecutionException(new TimeoutException()));
replay(mock);
backoff.load("foo");
verify(mock);
}
}

View File

@ -18,12 +18,13 @@
*/
package org.jclouds.sqs.features;
import static org.jclouds.concurrent.MoreExecutors.sameThreadExecutor;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.providers.AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint;
import static org.jclouds.sqs.reference.SQSParameters.ACTION;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import javax.ws.rs.POST;
import javax.ws.rs.Path;

View File

@ -19,14 +19,16 @@
package org.jclouds.vcloud.compute.options;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import java.net.URI;
import java.util.Map;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.util.Preconditions2;
import org.jclouds.vcloud.domain.network.FenceMode;
import org.jclouds.vcloud.domain.network.IpAddressAllocationMode;
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
@ -120,8 +122,7 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable
* Specifies the customizationScript used to run instances with
*/
public VCloudTemplateOptions customizationScript(String customizationScript) {
Preconditions2.checkNotEmpty(customizationScript, "customizationScript must be non-empty");
this.customizationScript = customizationScript;
this.customizationScript = checkNotNull(emptyToNull(customizationScript), "customizationScript must be defined");
return this;
}

View File

@ -58,18 +58,12 @@ public class VCloudTemplateOptionsTest {
assertEquals(options.as(VCloudTemplateOptions.class), options);
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "customizationScript must be defined")
public void testcustomizationScriptBadFormat() {
VCloudTemplateOptions options = new VCloudTemplateOptions();
options.customizationScript("");
}
@Test
public void testNullcustomizationScript() {
VCloudTemplateOptions options = new VCloudTemplateOptions();
assertEquals(options.getCustomizationScript(), null);
}
@Test
public void testcustomizationScript() {
VCloudTemplateOptions options = new VCloudTemplateOptions();
@ -115,7 +109,7 @@ public class VCloudTemplateOptionsTest {
assertEquals(options.getDescription(), "mykeypair");
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "customizationScript must be defined")
public void testcustomizationScriptNPE() {
customizationScript(null);
}

View File

@ -19,6 +19,7 @@
package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import java.util.Set;
@ -38,10 +39,12 @@ import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.util.Assertions;
import org.jclouds.predicates.RetryablePredicate;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -254,7 +257,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
return org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
deleteAndEnsurePathGone(container);
deletePathAndEnsureGone(container);
return null;
}
@ -265,24 +268,17 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
}), service);
}
protected void deleteAndEnsurePathGone(final String container) {
try {
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
try {
clearContainer(container, recursive());
return deleteAndVerifyContainerGone(container);
} catch (ContainerNotFoundException e) {
return true;
}
protected void deletePathAndEnsureGone(String path) {
checkState(new RetryablePredicate<String>(new Predicate<String>() {
public boolean apply(String in) {
try {
clearContainer(in, recursive());
return deleteAndVerifyContainerGone(in);
} catch (ContainerNotFoundException e) {
return true;
}
}, 30000)) {
throw new IllegalStateException(container + " still exists after deleting!");
}
} catch (InterruptedException e) {
throw new IllegalStateException(container + " interrupted during deletion!", e);
}
}, 30000).apply(path), "%s still exists after deleting!", path);
}
@Override

View File

@ -19,6 +19,7 @@
package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import java.util.Set;
@ -34,10 +35,12 @@ import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.util.Assertions;
import org.jclouds.predicates.RetryablePredicate;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
/**
@ -189,28 +192,21 @@ public abstract class BaseBlobStore implements BlobStore {
* bucket name
*/
@Override
public void deleteContainer(final String container) {
clearAndDeleteContainer(container);
public void deleteContainer(String container) {
deletePathAndEnsureGone(container);
}
protected void clearAndDeleteContainer(final String container) {
try {
if (!Assertions.eventuallyTrue(new Supplier<Boolean>() {
public Boolean get() {
try {
clearContainer(container, recursive());
return deleteAndVerifyContainerGone(container);
} catch (ContainerNotFoundException e) {
return true;
}
protected void deletePathAndEnsureGone(String path) {
checkState(new RetryablePredicate<String>(new Predicate<String>() {
public boolean apply(String in) {
try {
clearContainer(in, recursive());
return deleteAndVerifyContainerGone(in);
} catch (ContainerNotFoundException e) {
return true;
}
}, 30000)) {
throw new IllegalStateException(container + " still exists after deleting!");
}
} catch (InterruptedException e) {
throw new IllegalStateException(container + " interrupted during deletion!", e);
}
}, 30000).apply(path), "%s still exists after deleting!", path);
}
@Override

View File

@ -20,11 +20,11 @@ package org.jclouds.trmk.vcloud_0_8.compute.options;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.emptyToNull;
import java.util.Map;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.util.Preconditions2;
/**
* Contains options supported in the {@code ComputeService#runNode} operation on
@ -73,10 +73,8 @@ public class TerremarkVCloudTemplateOptions extends TemplateOptions implements C
* Specifies the keypair used to run instances with
*/
public TerremarkVCloudTemplateOptions sshKeyFingerprint(String keyPair) {
checkNotNull(keyPair, "use noKeyPair option to request boot without a keypair");
checkState(!noKeyPair, "you cannot specify both options keyPair and noKeyPair");
Preconditions2.checkNotEmpty(keyPair, "keypair must be non-empty");
this.keyPair = keyPair;
this.keyPair = checkNotNull(emptyToNull(keyPair), "use noKeyPair option to request boot without a keypair");
return this;
}

View File

@ -19,11 +19,11 @@
package org.jclouds.trmk.vcloud_0_8.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import java.util.List;
import org.jclouds.util.Preconditions2;
import com.google.common.collect.Lists;
/**
@ -43,8 +43,7 @@ public class VAppConfiguration {
*
*/
public VAppConfiguration changeNameTo(String name) {
Preconditions2.checkNotEmpty(name, "name must be specified");
this.name = name;
this.name = checkNotNull(emptyToNull(name), "name must be defined");
return this;
}

View File

@ -45,7 +45,7 @@ public class TerremarkVCloudTemplateOptionsTest {
assertEquals(options.as(TerremarkVCloudTemplateOptions.class), options);
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "use noKeyPair option to request boot without a keypair")
public void testkeyPairBadFormat() {
TerremarkVCloudTemplateOptions options = new TerremarkVCloudTemplateOptions();
options.sshKeyFingerprint("");

View File

@ -19,13 +19,13 @@
package org.jclouds.compute.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import java.util.Set;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
@ -191,7 +191,7 @@ public class NodePredicates {
* @return predicate
*/
public static Predicate<NodeMetadata> inGroup(final String group) {
Preconditions2.checkNotEmpty(group, "group must be defined");
checkNotNull(emptyToNull(group), "group must be defined");
return new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata nodeMetadata) {
@ -231,7 +231,7 @@ public class NodePredicates {
* @return predicate
*/
public static Predicate<NodeMetadata> runningInGroup(final String group) {
Preconditions2.checkNotEmpty(group, "group must be defined");
checkNotNull(emptyToNull(group), "group must be defined");
return new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata nodeMetadata) {

View File

@ -19,6 +19,7 @@
package org.jclouds.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.collect.Iterables.get;
import static org.testng.Assert.assertEquals;
@ -31,7 +32,6 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.rest.HttpClient;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
@ -64,7 +64,7 @@ public class ComputeTestUtils {
}
public static void checkSecretKeyFile(String secretKeyFile) {
Preconditions2.checkNotEmpty(secretKeyFile, "System property: [test.ssh.keyfile] set to an empty string");
checkNotNull(emptyToNull(secretKeyFile), "System property: [test.ssh.keyfile] set to an empty string");
if (!new File(secretKeyFile).exists()) {
throw new IllegalStateException("secretKeyFile not found at: " + secretKeyFile);
}

View File

@ -18,22 +18,24 @@
*/
package org.jclouds.compute.callables;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static com.google.inject.name.Names.named;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
import static org.jclouds.scriptbuilder.domain.Statements.exec;
import static org.testng.Assert.assertEquals;
import org.jclouds.Constants;
import org.jclouds.compute.config.ComputeServiceProperties;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.scriptbuilder.InitScript;
@ -47,40 +49,29 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.eventbus.EventBus;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.name.Names;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true, testName = "RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilCompleteTest")
public class RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilCompleteTest {
Injector injector = Guice.createInjector(new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()),
new AbstractModule() {
protected void configure() {
bindConstant().annotatedWith(named(PROPERTY_USER_THREADS)).to(1);
bindConstant().annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(named(TIMEOUT_SCRIPT_COMPLETE)).to(100);
install(new FactoryModuleBuilder().build(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class));
}
});
EventBus eventBus = new EventBus();
BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory statusFactory = Guice.createInjector(
new ExecutorServiceModule(MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor()),
new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE))
.to(100);
install(new FactoryModuleBuilder()
.build(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class));
}
}).getInstance(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class);
BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory statusFactory = injector
.getInstance(BlockUntilInitScriptStatusIsZeroThenReturnOutput.Factory.class);
// fail faster than normal
Timeouts timeouts = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE)).to(100l);
}
}).getInstance(Timeouts.class);
Timeouts timeouts = injector.getInstance(Timeouts.class);
@Test(expectedExceptions = IllegalStateException.class)
public void testWithoutInitThrowsIllegalStateException() {

View File

@ -30,6 +30,7 @@ import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.Constants.PROPERTY_API;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
@ -48,7 +49,6 @@ import java.util.Set;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.apis.Apis;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -61,6 +61,7 @@ import org.jclouds.events.config.EventBusModule;
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.lifecycle.Closer;
import org.jclouds.lifecycle.config.LifeCycleModule;
import org.jclouds.logging.config.LoggingModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
@ -71,6 +72,7 @@ import org.jclouds.providers.internal.UpdateProviderMetadataFromProperties;
import org.jclouds.rest.ConfiguresCredentialStore;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestApiMetadata;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.config.CredentialStoreModule;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.config.RestModule;
@ -84,10 +86,10 @@ import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.ExecutionList;
import com.google.inject.Guice;
@ -490,8 +492,7 @@ public class ContextBuilder {
return input.getClass().isAnnotationPresent(SingleThreaded.class);
}
})) {
modules.add(new ExecutorServiceModule(MoreExecutors.sameThreadExecutor(), MoreExecutors
.sameThreadExecutor()));
modules.add(new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()));
} else {
modules.add(new ExecutorServiceModule());
}

View File

@ -19,10 +19,10 @@
package org.jclouds.apis;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import org.jclouds.View;
import org.jclouds.rest.RestApiMetadata;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
@ -53,7 +53,7 @@ public class ApiPredicates {
* @return the apis with the given id
*/
public static Predicate<ApiMetadata> id(final String id) {
Preconditions2.checkNotEmpty(id, "id must be defined");
checkNotNull(emptyToNull(id), "id must be defined");
return new Predicate<ApiMetadata>() {
/**
* {@inheritDoc}

View File

@ -1,58 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cache;
import java.util.Map;
import com.google.common.annotations.Beta;
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.ListenableFuture;
/**
* A {@link CacheLoader} which forwards all its method calls to another {@link CacheLoader}.
* Subclasses should override one or more methods to modify the behavior of the backing cache as
* desired per the <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
*
* @author Adrian Cole
* @since 1.5
*/
@Beta
public abstract class ForwardingCacheLoader<K, V> extends CacheLoader<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingCacheLoader() {
}
protected abstract CacheLoader<K, V> delegate();
@Override
public V load(K key) throws Exception {
return delegate().load(key);
}
@Override
public ListenableFuture<V> reload(K key, V oldValue) throws Exception {
return delegate().reload(key, oldValue);
}
@Override
public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
return delegate().loadAll(keys);
}
}

View File

@ -1,196 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cache;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.cache.internal.BackoffExponentiallyAndRetryOnThrowableCacheLoader;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.cache.CacheLoader;
/**
* <p>
* A decorator of {@link CacheLoader} instances having any combination of the following features:
*
* <ul>
* <li>exponential backoff based on a particular Throwable type
* </ul>
*
* These features are all optional; cache loaders can be created using all or none of them. By
* default, the input cache loader is returned unaffected.
*
* <p>
* Usage example:
*
* <pre>
* @code
*
* CacheLoader<Key, Graph> loader = RetryingCacheLoaderDecorator.newDecorator()
* .on(ResourceNotFoundException.class).exponentiallyBackoff()
* .decorate(
* new CacheLoader<Key, Graph>() {
* public Graph load(Key key) throws AnyException {
* return createOnFlakeyConnection(key);
* }
* });}
* </pre>
*
* @param <K>
* the base key type for all cache loaders created by this decorator
* @param <V>
* the base value type for all cache loaders created by this decorator
* @author Adrian Cole
* @since 1.5
*/
@Beta
public class RetryingCacheLoaderDecorator<K, V> {
protected RetryingCacheLoaderDecorator() {
}
/**
* Constructs a new {@code RetryingCacheLoaderDecorator} instance with default settings, and no
* retrying any kind.
*/
// we can resolve generic type during decorate, as opposed to here
public static RetryingCacheLoaderDecorator<Object, Object> newDecorator() {
return new RetryingCacheLoaderDecorator<Object, Object>();
}
/**
* Determines the action to carry out on a particular throwable.
*
*/
public OnThrowableBuilder<K, V> on(Class<? extends Throwable> retryableThrowable) {
return new OnThrowableBuilder<K, V>(retryableThrowable);
}
public static class OnThrowableBuilder<K, V> {
private Class<? extends Throwable> retryableThrowable;
private OnThrowableBuilder(Class<? extends Throwable> retryableThrowable) {
this.retryableThrowable = checkNotNull(retryableThrowable, "retryableThrowable");
}
/**
* For each attempt, exponentially backoff
*/
public BackoffExponentiallyAndRetryOnThrowableCacheLoaderDecorator<K, V> exponentiallyBackoff() {
return new BackoffExponentiallyAndRetryOnThrowableCacheLoaderDecorator<K, V>(retryableThrowable);
}
}
public static class BackoffExponentiallyAndRetryOnThrowableCacheLoaderDecorator<K, V> extends
RetryingCacheLoaderDecorator<K, V> {
private long periodMs = 100l;
private long maxPeriodMs = 200l;
private int maxTries = 5;
private final Class<? extends Throwable> retryableThrowable;
private BackoffExponentiallyAndRetryOnThrowableCacheLoaderDecorator(Class<? extends Throwable> retryableThrowable) {
this.retryableThrowable = checkNotNull(retryableThrowable, "retryableThrowable");
}
/**
* The initial period in milliseconds to delay between tries. with each try this period will
* increase exponentially.
* <p/>
* default: {@code 100}
*
*/
public BackoffExponentiallyAndRetryOnThrowableCacheLoaderDecorator<K, V> periodMs(long periodMs) {
checkArgument(periodMs > 1, "maxTries must be positive: %d", periodMs);
this.periodMs = periodMs;
return this;
}
/**
* The initial period in milliseconds to delay between tries. with each try this period will
* increase exponentially.
* <p/>
* default: {@code 200}
*
*/
public BackoffExponentiallyAndRetryOnThrowableCacheLoaderDecorator<K, V> maxPeriodMs(long maxPeriodMs) {
checkArgument(maxPeriodMs > periodMs, "maxPeriodMs must be equal to or greater than periodMs: %d %d",
maxPeriodMs, periodMs);
this.maxPeriodMs = maxPeriodMs;
return this;
}
/**
* The maximum attempts to try on the given exception type
* <p/>
* default: {@code 5}
*
*/
public BackoffExponentiallyAndRetryOnThrowableCacheLoaderDecorator<K, V> maxTries(int maxTries) {
checkArgument(maxTries > 1, "maxTries must be more than one: %d", maxTries);
this.maxTries = maxTries;
return this;
}
@Override
public <K1 extends K, V1 extends V> CacheLoader<K1, V1> decorate(CacheLoader<K1, V1> loader) {
return new BackoffExponentiallyAndRetryOnThrowableCacheLoader<K1, V1>(retryableThrowable, periodMs,
maxPeriodMs, maxTries, super.decorate(loader));
}
@Override
protected Objects.ToStringHelper string() {
return Objects.toStringHelper(this).add("retryableThrowable", retryableThrowable).add("periodMs", periodMs).add("maxPeriodMs",
maxPeriodMs).add("maxTries", maxTries);
}
}
/**
* Decorates a cacheloader, or returns the same value, if no retrying features were requested.
*
* <p>
* This method does not alter the state of this {@code RetryingCacheLoaderDecorator} instance, so
* it can be invoked again to create multiple independent cache loaders.
*
* @param loader
* the cache loader used to obtain new values
* @return a cache loader having the requested features
*/
public <K1 extends K, V1 extends V> CacheLoader<K1, V1> decorate(CacheLoader<K1, V1> loader) {
return (CacheLoader<K1, V1>) loader;
}
/**
* Returns a string representation for this RetryingCacheLoaderDecorator instance. The exact form
* of the returned string is not specified.
*/
@Override
public String toString() {
return string().toString();
}
/**
* append any state that should be considered in {@link #toString} here.
*/
protected Objects.ToStringHelper string() {
return Objects.toStringHelper(this);
}
}

View File

@ -1,139 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cache.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeoutException;
import org.jclouds.cache.ForwardingCacheLoader;
import org.jclouds.util.Throwables2;
import com.google.common.annotations.Beta;
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Exponentially backs off, if we encounter an exception of the given type during any of the
* following methods:
* <ul>
* <li>load
* <li>reload
* <li>loadAll
* </ul>
*
* @param <K>
* the key type of the cache loader
* @param <V>
* the value type of the cache loader
* @author Adrian Cole
* @since 1.5
*/
@Beta
public class BackoffExponentiallyAndRetryOnThrowableCacheLoader<K, V> extends ForwardingCacheLoader<K, V> {
private final Class<? extends Throwable> retryableThrowable;
private final long periodMs;
private final long maxPeriodMs;
private final int maxTries;
private final CacheLoader<K, V> loader;
/**
*
* @param retryableThrowable
* the exception which we can retry
* @param periodMs
* initial period, which exponentially increases with each try, specified in
* milliseconds
* @param maxPeriodMs
* maximum period duration, specified in milliseconds
* @param maxTries
* maximum amount of tries
* @param loader
* the loader we are able to retry
*/
public BackoffExponentiallyAndRetryOnThrowableCacheLoader(Class<? extends Throwable> retryableThrowable, long periodMs,
long maxPeriodMs, int maxTries, CacheLoader<K, V> loader) {
this.retryableThrowable = checkNotNull(retryableThrowable, "retryableThrowable");
checkArgument(maxTries > 1, "maxTries must be more than one: %d", maxTries);
this.maxTries = maxTries;
checkArgument(periodMs > 0, "periodMs must be positive: %d", periodMs);
this.periodMs = periodMs;
checkArgument(maxPeriodMs > periodMs, "maxPeriodMs must be equal to or greater than periodMs: %d %d",
maxPeriodMs, periodMs);
this.maxPeriodMs = maxPeriodMs;
this.loader = checkNotNull(loader, "loader");
}
@Override
protected CacheLoader<K, V> delegate() {
return loader;
}
// TODO: refactor into a better closure in java pattern, if one exists
@Override
public V load(final K key) throws Exception {
return backoffExponentiallyAndRetryOnThrowable(new Callable<V>() {
@Override
public V call() throws Exception {
try {
return BackoffExponentiallyAndRetryOnThrowableCacheLoader.super.load(key);
} catch (Exception e) {
TimeoutException te = Throwables2.getFirstThrowableOfType(e,
TimeoutException.class);
if (te != null) {
throw te;
}
throw e;
}
}
});
}
@Override
public ListenableFuture<V> reload(final K key, final V oldValue) throws Exception {
return backoffExponentiallyAndRetryOnThrowable(new Callable<ListenableFuture<V>>() {
@Override
public ListenableFuture<V> call() throws Exception {
return BackoffExponentiallyAndRetryOnThrowableCacheLoader.super.reload(key, oldValue);
}
});
}
@Override
public Map<K, V> loadAll(final Iterable<? extends K> keys) throws Exception {
return backoffExponentiallyAndRetryOnThrowable(new Callable<Map<K, V>>() {
@Override
public Map<K, V> call() throws Exception {
return BackoffExponentiallyAndRetryOnThrowableCacheLoader.super.loadAll(keys);
}
});
}
private <T> T backoffExponentiallyAndRetryOnThrowable(Callable<T> callable) throws Exception {
return new BackoffExponentiallyAndRetryOnThrowableCallable<T>(retryableThrowable, periodMs, maxPeriodMs,
maxTries, callable).call();
}
}

View File

@ -1,99 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cache.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.concurrent.Callable;
import org.jclouds.util.Throwables2;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.base.Throwables;
import com.google.common.collect.ForwardingObject;
/**
* Exponentially backs off, if we encounter an exception of the given type during
* {@link Callable#call}
*
* @author Adrian Cole
* @since 1.5
*/
@Beta
class BackoffExponentiallyAndRetryOnThrowableCallable<T> extends ForwardingObject implements Callable<T> {
private final Class<? extends Throwable> retryableThrowable;
private final long periodMs;
private final long maxPeriodMs;
private final int maxTries;
private final Callable<T> callable;
BackoffExponentiallyAndRetryOnThrowableCallable(Class<? extends Throwable> retryableThrowable, long periodMs,
long maxPeriodMs, int maxTries, Callable<T> callable) {
this.retryableThrowable = checkNotNull(retryableThrowable, "retryableThrowable");
checkArgument(maxTries > 1, "maxTries must be more than one: %d", maxTries);
this.maxTries = maxTries;
checkArgument(periodMs > 0, "periodMs must be positive: %d", periodMs);
this.periodMs = periodMs;
checkArgument(maxPeriodMs > periodMs, "maxPeriodMs must be equal to or greater than periodMs: %d %d",
maxPeriodMs, periodMs);
this.maxPeriodMs = maxPeriodMs;
this.callable = checkNotNull(callable, "callable");
}
@Override
protected Callable<T> delegate() {
return callable;
}
@Override
public T call() throws Exception {
Exception currentException = null;
for (int currentTries = 0; currentTries < maxTries; currentTries++) {
try {
return delegate().call();
} catch (Exception e) {
currentException = e;
if (Throwables2.getFirstThrowableOfType(e, retryableThrowable) != null) {
imposeBackoffExponentialDelay(periodMs, maxPeriodMs, 2, currentTries, maxTries);
} else {
throw e;
}
}
}
throw currentException;
}
private void imposeBackoffExponentialDelay(long period, long maxPeriod, int pow, int failureCount, int max) {
long delayMs = (long) (period * Math.pow(failureCount, pow));
delayMs = delayMs > maxPeriod ? maxPeriod : delayMs;
try {
Thread.sleep(delayMs);
} catch (InterruptedException e) {
Throwables.propagate(e);
}
}
@Override
public String toString() {
return Objects.toStringHelper("").add("retryableThrowable", retryableThrowable).add("periodMs", periodMs).add(
"maxPeriodMs", maxPeriodMs).add("maxTries", maxTries).add("callable", callable).toString();
}
}

View File

@ -1,214 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.
*/
/*
* Copyright (C) 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.concurrent;
import java.util.List;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
/**
* functions related to or replacing those in
* {@link com.google.common.util.concurrent.MoreExecutors}
*
* @author Adrian Cole
*/
@Beta
public class MoreExecutors {
/**
* Taken from @link com.google.common.util.concurrent.MoreExecutors} as it was hidden and
* therefore incapable of instanceof checks.
*
*
* Creates an executor service that runs each task in the thread that invokes {@code
* execute/submit}, as in {@link CallerRunsPolicy} This applies both to individually submitted
* tasks and to collections of tasks submitted via {@code invokeAll} or {@code invokeAny}. In the
* latter case, tasks will run serially on the calling thread. Tasks are run to completion before
* a {@code Future} is returned to the caller (unless the executor has been shutdown).
*
* <p>
* Although all tasks are immediately executed in the thread that submitted the task, this
* {@code ExecutorService} imposes a small locking overhead on each task submission in order to
* implement shutdown and termination behavior.
*
* <p>
* The implementation deviates from the {@code ExecutorService} specification with regards to the
* {@code shutdownNow} method. First, "best-effort" with regards to canceling running tasks is
* implemented as "no-effort". No interrupts or other attempts are made to stop threads executing
* tasks. Second, the returned list will always be empty, as any submitted task is considered to
* have started execution. This applies also to tasks given to {@code invokeAll} or {@code
* invokeAny} which are pending serial execution, even the subset of the tasks that have not yet
* started execution. It is unclear from the {@code ExecutorService} specification if these
* should be included, and it's much easier to implement the interpretation that they not be.
* Finally, a call to {@code shutdown} or {@code shutdownNow} may result in concurrent calls to
* {@code invokeAll/invokeAny} throwing RejectedExecutionException, although a subset of the
* tasks may already have been executed.
*/
public static ExecutorService sameThreadExecutor() {
return new SameThreadExecutorService();
}
// See sameThreadExecutor javadoc for behavioral notes.
@SingleThreaded
public static class SameThreadExecutorService extends AbstractExecutorService {
/**
* Lock used whenever accessing the state variables (runningTasks, shutdown,
* terminationCondition) of the executor
*/
private final Lock lock = new ReentrantLock();
/** Signaled after the executor is shutdown and running tasks are done */
private final Condition termination = lock.newCondition();
private SameThreadExecutorService() {
}
/*
* Conceptually, these two variables describe the executor being in one of three states: -
* Active: shutdown == false - Shutdown: runningTasks > 0 and shutdown == true - Terminated:
* runningTasks == 0 and shutdown == true
*/
private int runningTasks = 0;
private boolean shutdown = false;
@Override
public void execute(Runnable command) {
startTask();
try {
command.run();
} finally {
endTask();
}
}
@Override
public boolean isShutdown() {
lock.lock();
try {
return shutdown;
} finally {
lock.unlock();
}
}
@Override
public void shutdown() {
lock.lock();
try {
shutdown = true;
} finally {
lock.unlock();
}
}
// See sameThreadExecutor javadoc for unusual behavior of this method.
@Override
public List<Runnable> shutdownNow() {
shutdown();
return ImmutableList.of();
}
@Override
public boolean isTerminated() {
lock.lock();
try {
return shutdown && runningTasks == 0;
} finally {
lock.unlock();
}
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
lock.lock();
try {
for (;;) {
if (isTerminated()) {
return true;
} else if (nanos <= 0) {
return false;
} else {
nanos = termination.awaitNanos(nanos);
}
}
} finally {
lock.unlock();
}
}
/**
* Checks if the executor has been shut down and increments the running task count.
*
* @throws RejectedExecutionException
* if the executor has been previously shutdown
*/
private void startTask() {
lock.lock();
try {
if (isShutdown()) {
throw new RejectedExecutionException("Executor already shutdown");
}
runningTasks++;
} finally {
lock.unlock();
}
}
/**
* Decrements the running task count.
*/
private void endTask() {
lock.lock();
try {
runningTasks--;
if (isTerminated()) {
termination.signalAll();
}
} finally {
lock.unlock();
}
}
}
}

View File

@ -34,8 +34,6 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger;
@ -83,8 +81,8 @@ public class ExecutorServiceModule extends AbstractModule {
@Inject
public ExecutorServiceModule(@Named(PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named(PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads) {
this.userExecutorFromConstructor = addToStringOnSubmit(checkNotGuavaSameThreadExecutor(userThreads));
this.ioExecutorFromConstructor = addToStringOnSubmit(checkNotGuavaSameThreadExecutor(ioThreads));
this.userExecutorFromConstructor = addToStringOnSubmit(userThreads);
this.ioExecutorFromConstructor = addToStringOnSubmit(ioThreads);
}
private ExecutorService addToStringOnSubmit(ExecutorService executor) {
@ -94,18 +92,6 @@ public class ExecutorServiceModule extends AbstractModule {
return executor;
}
private ExecutorService checkNotGuavaSameThreadExecutor(ExecutorService executor) {
// we detect behavior based on the class
if (executor != null && !(executor.getClass().isAnnotationPresent(SingleThreaded.class))
&& executor.getClass().getSimpleName().indexOf("SameThread") != -1) {
Logger.CONSOLE.warn(
"please switch from %s to %s or annotate your same threaded executor with @SingleThreaded", executor
.getClass().getName(), MoreExecutors.SameThreadExecutorService.class.getName());
return MoreExecutors.sameThreadExecutor();
}
return executor;
}
public ExecutorServiceModule() {
this(null, null);
}

View File

@ -18,13 +18,16 @@
*/
package org.jclouds.lifecycle.config;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static com.google.inject.matcher.Matchers.any;
import static java.util.Arrays.asList;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
@ -34,14 +37,12 @@ import javax.annotation.PreDestroy;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.lifecycle.Closer;
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ExecutionList;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.TypeEncounter;
@ -103,10 +104,10 @@ public class LifeCycleModule extends AbstractModule {
protected void bindPostInjectionInvoke(final Closer closer, final ExecutionList list) {
bindListener(any(), new TypeListener() {
public <I> void hear(TypeLiteral<I> injectableType, TypeEncounter<I> encounter) {
Set<Method> methods = Sets.newHashSet();
Set<Method> methods = newHashSet();
Class<? super I> type = injectableType.getRawType();
while (type != null) {
methods.addAll(Arrays.asList(type.getDeclaredMethods()));
methods.addAll(asList(type.getDeclaredMethods()));
type = type.getSuperclass();
}
for (final Method method : methods) {
@ -150,12 +151,12 @@ public class LifeCycleModule extends AbstractModule {
method.invoke(injectee);
} catch (InvocationTargetException ie) {
Throwable e = ie.getTargetException();
throw Throwables.propagate(e);
throw propagate(e);
} catch (IllegalAccessException e) {
throw Throwables.propagate(e);
throw propagate(e);
}
}
}, MoreExecutors.sameThreadExecutor());
}, sameThreadExecutor());
}
});
}

View File

@ -18,11 +18,13 @@
*/
package org.jclouds.providers;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import org.jclouds.Context;
import org.jclouds.View;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.apis.ApiPredicates;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
@ -104,7 +106,7 @@ public class ProviderPredicates {
* @return the providers with the given id
*/
public static Predicate<ProviderMetadata> id(final String id) {
Preconditions2.checkNotEmpty(id, "id must be defined");
checkNotNull(emptyToNull(id), "id must be defined");
return new Predicate<ProviderMetadata>() {
/**
* {@inheritDoc}

View File

@ -1,44 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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 com.google.common.base.Supplier;
/**
*
* @author Adrian Cole
*/
public class Assertions {
public static boolean eventuallyTrue(Supplier<Boolean> assertion, long inconsistencyMillis)
throws InterruptedException {
for (int i = 0; i < 30; i++) {
if (!assertion.get()) {
Thread.sleep(inconsistencyMillis / 30);
continue;
}
return true;
}
return false;
}
}

View File

@ -1,51 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.net.URL;
import com.google.common.io.Resources;
public class ClassLoadingUtils {
public ClassLoadingUtils() {
//Utility Class
}
/**
* Returns the url of a resource.
* 1. The context class is being used.
* 2. The thread context class loader is being used.
* If both approach fail, returns null.
*
* @param contextClass
* @param resourceName
* @return
*/
public static URL loadResource(Class<?> contextClass, String resourceName) {
URL url = null;
if (contextClass != null) {
url = Resources.getResource(contextClass, resourceName);
}
if (url == null && Thread.currentThread().getContextClassLoader() != null) {
url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
}
return url;
}
}

View File

@ -1,60 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.security.SecureRandom;
import com.google.common.base.Supplier;
/**
* Cheap, lightweight, low-security password generator.
*
* @see <a href=
* "http://www.java-forums.org/java-lang/7355-how-create-lightweight-low-security-password-generator.html"
* />
*/
public enum PasswordGenerator implements Supplier<String> {
INSTANCE;
/** Minimum length for a decent password */
public static final int MIN_LENGTH = 10;
/** The random number generator. */
protected static final SecureRandom r = new SecureRandom();
/*
* Set of characters that is valid. Must be printable, memorable, and
* "won't break HTML" (i.e., not ' <', '>', '&', '=', ...). or break shell
* commands (i.e., not ' <', '>', '$', '!', ...). I, L and O are good to
* leave out, as are numeric zero and one.
*/
public static final char[] goodChar = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q',
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '@', };
@Override
public String get() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < MIN_LENGTH; i++) {
sb.append(goodChar[r.nextInt(goodChar.length)]);
}
return sb.toString();
}
}

View File

@ -1,44 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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 static com.google.common.base.Preconditions.checkArgument;
/**
* Preconditions not in guava.
*
* @author Adrian Cole
*/
public class Preconditions2 {
/**
* Will throw an exception if the argument is null or empty. Accepts a custom error message.
*
* @param nullableString
* string to verify. Can be null or empty.
* @param message
* message to show in case of exception
*/
public static void checkNotEmpty(String nullableString, String message) {
checkArgument(nullableString != null && nullableString.length() > 0, message);
}
}

View File

@ -1,82 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cache;
import static org.easymock.EasyMock.createMockBuilder;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertSame;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Unit test for {@link ForwardingCacheLoader}.
*
* @author Adrian Cole
*/
@Test(testName = "ForwardingCacheLoaderTest", singleThreaded = true)
public class ForwardingCacheLoaderTest {
private CacheLoader<String, Boolean> forward;
private CacheLoader<String, Boolean> mock;
@SuppressWarnings("unchecked")
@BeforeMethod
public void setUp() {
// add mocked methods for default forwarded ones
mock = createMockBuilder(CacheLoader.class).addMockedMethods("loadAll", "reload").createMock();
forward = new ForwardingCacheLoader<String, Boolean>() {
@Override
protected CacheLoader<String, Boolean> delegate() {
return mock;
}
};
}
public void testLoad() throws Exception {
expect(mock.load("key")).andReturn(Boolean.TRUE);
replay(mock);
assertSame(Boolean.TRUE, forward.load("key"));
verify(mock);
}
public void testReload() throws Exception {
ListenableFuture<Boolean> trueF = Futures.immediateFuture(true);
expect(mock.reload("key", false)).andReturn(trueF);
replay(mock);
assertSame(forward.reload("key", false), trueF);
verify(mock);
}
public void testLoadAll() throws Exception {
expect(mock.loadAll(ImmutableList.of("key"))).andReturn(ImmutableMap.of("key", Boolean.TRUE));
replay(mock);
assertEquals(ImmutableMap.of("key", Boolean.TRUE), forward.loadAll(ImmutableList.of("key")));
verify(mock);
}
}

View File

@ -1,85 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cache;
import static org.easymock.EasyMock.createMockBuilder;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.fail;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.cache.CacheLoader;
/**
* Unit tests for RetryingCacheLoaderDecorator.
*
* @author Adrian Cole
*/
@Test(testName = "ForwardingCacheLoaderTest", singleThreaded = true)
public class RetryingCacheLoaderDecoratorTest {
private CacheLoader<String, Boolean> mock;
@SuppressWarnings("unchecked")
@BeforeMethod
public void setUp() {
// add mocked methods for default forwarded ones
mock = createMockBuilder(CacheLoader.class).addMockedMethods("loadAll", "reload").createMock();
}
public void testNewDecoratorDecorateSameWhenNoParams() throws Exception {
assertSame(mock, RetryingCacheLoaderDecorator.newDecorator().decorate(mock));
}
@Test
void testDefaultMaxTriesIs5() throws Exception {
CacheLoader<String, Boolean> backoff = RetryingCacheLoaderDecorator.newDecorator().on(
ResourceNotFoundException.class).exponentiallyBackoff().decorate(mock);
expect(mock.load("foo")).andThrow(new ResourceNotFoundException()).times(4);
expect(mock.load("foo")).andReturn(Boolean.TRUE);
replay(mock);
assertSame(backoff.load("foo"), Boolean.TRUE);
verify(mock);
}
@Test
void testMaxRetriesExceededThrowsException() throws Exception {
CacheLoader<String, Boolean> backoff = RetryingCacheLoaderDecorator.newDecorator()
.on(ResourceNotFoundException.class).exponentiallyBackoff()
.decorate(mock);
expect(mock.load("foo")).andThrow(new ResourceNotFoundException()).times(5);
replay(mock);
try {
backoff.load("foo");
fail();
} catch (ResourceNotFoundException e) {
}
verify(mock);
}
}

View File

@ -1,97 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cache.internal;
import static org.easymock.EasyMock.createMockBuilder;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.fail;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.cache.CacheLoader;
@Test(groups = "unit", singleThreaded = true, testName = "BackoffExponentiallyAndRetryOnThrowableCacheLoaderTest")
public class BackoffExponentiallyAndRetryOnThrowableCacheLoaderTest {
private CacheLoader<String, Boolean> mock;
@SuppressWarnings("unchecked")
@BeforeMethod
public void setUp() {
// add mocked methods for default forwarded ones
mock = createMockBuilder(CacheLoader.class).addMockedMethods("loadAll", "reload").createMock();
}
@Test
void testMaxRetriesNotExceededReturnsValue() throws Exception {
int attempts = 3;
BackoffExponentiallyAndRetryOnThrowableCacheLoader<String, Boolean> backoff = new BackoffExponentiallyAndRetryOnThrowableCacheLoader<String, Boolean>(
ResourceNotFoundException.class, 50l, 500l, attempts, mock);
expect(mock.load("foo")).andThrow(new ResourceNotFoundException()).times(attempts - 1);
expect(mock.load("foo")).andReturn(Boolean.TRUE);
replay(mock);
assertSame(backoff.load("foo"), Boolean.TRUE);
verify(mock);
}
@Test
void testMaxRetriesExceededThrowsException() throws Exception {
int attempts = 3;
BackoffExponentiallyAndRetryOnThrowableCacheLoader<String, Boolean> backoff = new BackoffExponentiallyAndRetryOnThrowableCacheLoader<String, Boolean>(
ResourceNotFoundException.class, 50l, 500l, attempts, mock);
expect(mock.load("foo")).andThrow(new ResourceNotFoundException()).times(attempts);
replay(mock);
try {
backoff.load("foo");
fail();
} catch (ResourceNotFoundException e) {
}
verify(mock);
}
@Test
void testThrowsTimeoutException() throws Exception {
int attempts = 3;
BackoffExponentiallyAndRetryOnThrowableCacheLoader<String, Boolean> backoff = new BackoffExponentiallyAndRetryOnThrowableCacheLoader<String, Boolean>(
ResourceNotFoundException.class, 50l, 500l, attempts, mock);
expect(mock.load("foo")).andThrow(new ExecutionException(new TimeoutException()));
replay(mock);
try {
backoff.load("foo");
fail();
} catch (TimeoutException e) {
}
verify(mock);
}
}

View File

@ -1,75 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cache.internal;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import java.util.concurrent.Callable;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "BackoffExponentiallyAndRetryOnThrowableCallableTest", singleThreaded = true)
public class BackoffExponentiallyAndRetryOnThrowableCallableTest {
private Callable<String> mock;
@SuppressWarnings("unchecked")
@BeforeMethod
public void setUp() {
mock = createMock(Callable.class);
}
@Test
void testMaxRetriesNotExceededReturnsValue() throws Exception {
int attempts = 3;
BackoffExponentiallyAndRetryOnThrowableCallable<String> backoff = new BackoffExponentiallyAndRetryOnThrowableCallable<String>(
ResourceNotFoundException.class, 50l, 500l, attempts, mock);
expect(mock.call()).andThrow(new ResourceNotFoundException()).times(attempts - 1);
expect(mock.call()).andReturn("foo");
replay(mock);
assertEquals(backoff.call(), "foo");
verify(mock);
}
@Test
void testMaxRetriesExceededThrowsException() throws Exception {
int attempts = 3;
BackoffExponentiallyAndRetryOnThrowableCallable<String> backoff = new BackoffExponentiallyAndRetryOnThrowableCallable<String>(
ResourceNotFoundException.class, 50l, 500l, attempts, mock);
expect(mock.call()).andThrow(new ResourceNotFoundException()).times(attempts);
replay(mock);
try {
backoff.call();
fail();
} catch (ResourceNotFoundException e) {
}
verify(mock);
}
}

View File

@ -1,250 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.concurrent;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Maps.newHashMap;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
import static org.testng.Assert.assertEquals;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import org.jclouds.logging.Logger;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* Tests behavior of FutureIterables
*
* @author Adrian Cole
*/
@Test(groups = "performance", enabled = false, sequential = true, testName = "FutureIterablesPerformanceTest")
public class FutureIterablesPerformanceTest {
ExecutorService ioFunctionExecutor = newCachedThreadPool();
@Test(enabled = false)
public void testMakeListenableDoesntSerializeFutures() throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION;
long expectedMin = IO_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = runCallables(chainExecutor);
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
@Test(enabled = false)
public void testAwaitCompletionUsingSameThreadExecutorDoesntSerializeFutures()
throws InterruptedException, ExecutionException, TimeoutException {
long expectedMax = IO_DURATION;
long expectedMin = IO_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = runCallables(chainExecutor);
Map<String, Exception> exceptions = awaitCompletion(responses, MoreExecutors.sameThreadExecutor(), null,
Logger.CONSOLE, "test same thread");
assertEquals(exceptions.size(), 0);
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
@Test(enabled = false)
public void whenCachedThreadPoolIsUsedForChainAndListenerMaxDurationIsSumOfCallableAndListener()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT * 4 + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = userthreads;
ExecutorService listenerExecutor = userthreads;
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenCachedThreadPoolIsUsedForChainButSameThreadForListenerMaxDurationIsSumOfCallableAndListener()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = userthreads;
ExecutorService listenerExecutor = MoreExecutors.sameThreadExecutor();
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenSameThreadIsUsedForChainButCachedThreadPoolForListenerMaxDurationIsIOAndSumOfAllListeners()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + (LISTENER_DURATION * COUNT);
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
ExecutorService listenerExecutor = userthreads;
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
@Test(enabled = false)
public void whenSameThreadIsUsedForChainAndListenerMaxDurationIsIOAndSumOfAllListeners()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + (LISTENER_DURATION * COUNT);
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
ExecutorService listenerExecutor = MoreExecutors.sameThreadExecutor();
checkThresholdsUsingCompose(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
public static final int FUDGE = 5;
public static final int COUNT = 100;
public static final int IO_DURATION = 50;
public static final int LISTENER_DURATION = 100;
private void checkThresholdsUsingCompose(long expectedMin, long expectedMax, long expectedOverhead,
ExecutorService chainExecutor, final ExecutorService listenerExecutor) {
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = newHashMap();
for (int i = 0; i < COUNT; i++)
responses.put(i + "", org.jclouds.concurrent.Futures.compose(org.jclouds.concurrent.Futures.makeListenable(
simultateIO(), chainExecutor), new Function<Long, Long>() {
@Override
public Long apply(Long from) {
try {
Thread.sleep(LISTENER_DURATION);
} catch (InterruptedException e) {
propagate(e);
}
return System.currentTimeMillis();
}
}, listenerExecutor));
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
private Map<String, Future<Long>> runCallables(ExecutorService chainExecutor) {
Map<String, Future<Long>> responses = newHashMap();
for (int i = 0; i < COUNT; i++)
responses.put(i + "", org.jclouds.concurrent.Futures.makeListenable(simultateIO(), chainExecutor));
return responses;
}
private Future<Long> simultateIO() {
return ioFunctionExecutor.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
Thread.sleep(IO_DURATION);
return System.currentTimeMillis();
}
});
}
public static long getMaxIn(Map<String, Future<Long>> responses) {
Iterable<Long> collection = Iterables.transform(responses.values(), new Function<Future<Long>, Long>() {
@Override
public Long apply(Future<Long> from) {
try {
return from.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
});
long time = Collections.max(Sets.newHashSet(collection));
return time;
}
public static long getMinIn(Map<String, Future<Long>> responses) {
Iterable<Long> collection = Iterables.transform(responses.values(), new Function<Future<Long>, Long>() {
@Override
public Long apply(Future<Long> from) {
try {
return from.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
});
long time = Collections.min(Sets.newHashSet(collection));
return time;
}
private static void checkTimeThresholds(long expectedMin, long expectedMax, long expectedOverhead, long start,
Map<String, Future<Long>> responses) {
long time = getMaxIn(responses) - start;
assert time >= expectedMax && time < expectedMax + expectedOverhead : String.format("expectedMax %d, max %d",
expectedMax, time);
time = getMinIn(responses) - start;
assert time >= expectedMin && time < expectedMin + expectedOverhead : String.format("expectedMin %d, min %d",
expectedMin, time);
time = getMaxIn(responses) - start;
assert time >= expectedMax && time < expectedMax + expectedOverhead : String.format("expectedMax %d, max %d",
expectedMax, time);
}
}

View File

@ -18,13 +18,16 @@
*/
package org.jclouds.concurrent;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
@ -35,7 +38,6 @@ import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
/**
* Tests behavior of FutureIterables
@ -54,17 +56,17 @@ public class FutureIterablesTest {
@Override
public Future<String> apply(String input) {
counter.incrementAndGet();
return com.google.common.util.concurrent.Futures.immediateFailedFuture(new AuthorizationException());
return immediateFailedFuture(new AuthorizationException());
}
}, MoreExecutors.sameThreadExecutor(), null, Logger.CONSOLE, "");
}, sameThreadExecutor(), null, Logger.CONSOLE, "");
fail("Expected AuthorizationException");
} catch (AuthorizationException e) {
assertEquals(counter.get(), 2);
}
}
public void testNormalExceptionPropagatesAsTransformParallelExceptionAndTries5XPerElement() {
final AtomicInteger counter = new AtomicInteger();
@ -74,10 +76,10 @@ public class FutureIterablesTest {
@Override
public Future<String> apply(String input) {
counter.incrementAndGet();
return com.google.common.util.concurrent.Futures.immediateFailedFuture(new RuntimeException());
return immediateFailedFuture(new RuntimeException());
}
}, MoreExecutors.sameThreadExecutor(), null, Logger.CONSOLE, "");
}, sameThreadExecutor(), null, Logger.CONSOLE, "");
fail("Expected TransformParallelException");
} catch (TransformParallelException e) {
assertEquals(e.getFromToException().size(), 2);
@ -89,21 +91,21 @@ public class FutureIterablesTest {
public void testAwaitCompletionTimeout() throws Exception {
final long timeoutMs = 1000;
ExecutorService executorService = Executors.newSingleThreadExecutor();
Map<Void, Future<?>> responses = Maps.newHashMap();
Map<Void, Future<?>> responses = newHashMap();
try {
responses.put(null, executorService.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2 * timeoutMs);
} catch (InterruptedException ie) {
// triggered during shutdown
}
@Override
public void run() {
try {
Thread.sleep(2 * timeoutMs);
} catch (InterruptedException ie) {
// triggered during shutdown
}
}
}));
Map<Void, Exception> errors = FutureIterables.awaitCompletion(
responses, executorService, timeoutMs, Logger.CONSOLE,
/*prefix=*/ "");
Map<Void, Exception> errors = FutureIterables.awaitCompletion(responses, executorService, timeoutMs,
Logger.CONSOLE,
/* prefix= */"");
if (!errors.isEmpty()) {
throw errors.values().iterator().next();
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.concurrent;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
@ -41,7 +42,7 @@ import com.google.common.util.concurrent.ExecutionList;
*/
@Test(groups = "unit")
public class FuturesTest {
ExecutorService executorService = MoreExecutors.sameThreadExecutor();
ExecutorService executorService = sameThreadExecutor();
@Test
public void testCallGetAndRunRunnableRunsListOnRuntimeException() throws InterruptedException, ExecutionException {

View File

@ -19,6 +19,11 @@
package org.jclouds.rest.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static com.google.inject.name.Names.named;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_MAX_RETRIES;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
@ -43,10 +48,8 @@ import org.custommonkey.xmlunit.DifferenceConstants;
import org.custommonkey.xmlunit.DifferenceListener;
import org.custommonkey.xmlunit.NodeDetail;
import org.custommonkey.xmlunit.XMLUnit;
import org.jclouds.Constants;
import org.jclouds.ContextBuilder;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.date.internal.DateServiceDateCodecFactory;
@ -88,7 +91,6 @@ import com.google.inject.Binder;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
/**
*
@ -193,7 +195,7 @@ public abstract class BaseRestApiExpectTest<S> {
@Inject
public ExpectHttpCommandExecutorService(Function<HttpRequest, HttpResponse> fn, HttpUtils utils,
ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioExecutor,
@Named(PROPERTY_IO_WORKER_THREADS) ExecutorService ioExecutor,
IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire) {
super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
@ -228,10 +230,8 @@ public abstract class BaseRestApiExpectTest<S> {
@Override
public void configure() {
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).toInstance(
MoreExecutors.sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).toInstance(
MoreExecutors.sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(named(PROPERTY_USER_THREADS)).toInstance(sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).toInstance(sameThreadExecutor());
bind(new TypeLiteral<Function<HttpRequest, HttpResponse>>() {
}).toInstance(fn);
bind(HttpCommandExecutorService.class).to(ExpectHttpCommandExecutorService.class);
@ -564,7 +564,7 @@ public abstract class BaseRestApiExpectTest<S> {
*/
protected Properties setupProperties() {
Properties props = new Properties();
props.put(Constants.PROPERTY_MAX_RETRIES, 1);
props.put(PROPERTY_MAX_RETRIES, 1);
return props;
}
}

View File

@ -19,8 +19,12 @@
package org.jclouds.rest.internal;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.hash.Hashing.md5;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static com.google.inject.name.Names.named;
import static org.easymock.EasyMock.createMock;
import static org.eclipse.jetty.http.HttpHeaders.TRANSFER_ENCODING;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.io.ByteSources.asByteSource;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@ -30,8 +34,6 @@ import java.util.Date;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.jclouds.Constants;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
import org.jclouds.http.HttpCommandExecutorService;
@ -40,7 +42,6 @@ import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.reflect.Invokable;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.util.Strings2;
@ -49,12 +50,12 @@ import org.testng.annotations.Test;
import com.google.common.collect.Multimap;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
/**
*
@ -81,10 +82,8 @@ public abstract class BaseRestApiTest {
@Override
protected void configure() {
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).toInstance(
MoreExecutors.sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).toInstance(
MoreExecutors.sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(named(PROPERTY_USER_THREADS)).toInstance(sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).toInstance(sameThreadExecutor());
bind(HttpCommandExecutorService.class).toInstance(mock);
}
}

View File

@ -18,7 +18,8 @@
*/
package org.jclouds.gae.config;
import org.jclouds.concurrent.MoreExecutors;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
@ -49,7 +50,7 @@ public class GoogleAppEngineConfigurationModule extends AbstractModule {
private final Module executorServiceModule;
public GoogleAppEngineConfigurationModule() {
this(new ExecutorServiceModule(MoreExecutors.sameThreadExecutor(), MoreExecutors.sameThreadExecutor()));
this(new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor()));
}
/**

View File

@ -20,15 +20,11 @@
package org.jclouds.virtualbox;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import static org.jclouds.scriptbuilder.domain.Statements.findPid;
import static org.jclouds.scriptbuilder.domain.Statements.kill;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import java.io.File;
import java.net.URI;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
@ -36,18 +32,14 @@ import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.compute.callables.RunScriptOnNode.Factory;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.rest.annotations.BuildVersion;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.StatementList;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.jclouds.virtualbox.config.VirtualBoxConstants;
import org.jclouds.virtualbox.domain.HardDisk;
@ -81,10 +73,8 @@ import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.net.HostAndPort;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Injector;
import com.google.inject.Key;
@ -138,7 +128,7 @@ public class BaseVirtualBoxClientLiveTest extends BaseComputeServiceContextLiveT
@Inject
protected LoadingCache<Image, Master> mastersCache;
private final ExecutorService singleThreadExec = MoreExecutors.sameThreadExecutor();
private final ExecutorService singleThreadExec = sameThreadExecutor();
private String masterName;
@Override

View File

@ -18,7 +18,9 @@
*/
package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.emptyToNull;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
@ -66,7 +68,6 @@ import org.jclouds.ec2.compute.EC2ComputeService;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import org.jclouds.util.Preconditions2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
@ -119,7 +120,7 @@ public class AWSEC2ComputeService extends EC2ComputeService {
@VisibleForTesting
void deletePlacementGroup(String region, String group) {
Preconditions2.checkNotEmpty(group, "group");
checkNotNull(emptyToNull(group), "group must be defined");
// placementGroupName must be unique within an account per
// http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?using_cluster_computing.html
String placementGroup = String.format("jclouds#%s#%s", group, region);

View File

@ -22,6 +22,7 @@ import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Strings.emptyToNull;
import java.util.Map;
import java.util.Set;
@ -33,7 +34,6 @@ import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
@ -148,9 +148,8 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
* Specifies the keypair used to run instances with
*/
public AWSEC2TemplateOptions placementGroup(String placementGroup) {
checkNotNull(placementGroup, "use noPlacementGroup option to request boot without a keypair");
checkNotNull(emptyToNull(placementGroup), "use noPlacementGroup option instead of passing null");
checkState(!noPlacementGroup, "you cannot specify both options placementGroup and noPlacementGroup");
Preconditions2.checkNotEmpty(placementGroup, "placementGroup must be non-empty");
this.placementGroup = placementGroup;
return this;
}
@ -168,9 +167,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
* Specifies the subnetId used to run instances in
*/
public AWSEC2TemplateOptions subnetId(String subnetId) {
checkNotNull(subnetId, "subnetId cannot be null");
Preconditions2.checkNotEmpty(subnetId, "subnetId must be non-empty");
this.subnetId = subnetId;
this.subnetId = checkNotNull(emptyToNull(subnetId), "subnetId must be defined");
return this;
}
@ -204,7 +201,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
public AWSEC2TemplateOptions securityGroupIds(Iterable<String> groupIds) {
checkArgument(Iterables.size(groupIds) > 0, "you must specify at least one security group");
for (String groupId : groupIds)
Preconditions2.checkNotEmpty(groupId, "all security groups must be non-empty");
checkNotNull(emptyToNull(groupId), "all security groups must be non-empty");
this.groupIds = ImmutableSet.copyOf(groupIds);
return this;
}

View File

@ -50,7 +50,7 @@ public class AWSEC2TemplateOptionsTest {
assertEquals(options.as(AWSEC2TemplateOptions.class), options);
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "all security groups must be non-empty")
public void testsecurityGroupIdsIterableBadFormat() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
options.securityGroupIds(ImmutableSet.of("groupId1", ""));
@ -76,7 +76,7 @@ public class AWSEC2TemplateOptionsTest {
assertEquals(options.getGroupIds(), ImmutableSet.of("groupId1", "groupId2"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "all security groups must be non-empty")
public void testsecurityGroupIdsVarArgsBadFormat() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
options.securityGroupIds("mygroupId", "");
@ -107,7 +107,7 @@ public class AWSEC2TemplateOptionsTest {
assertEquals(options.getGroupIds(), ImmutableSet.of("groupId1", "groupId2"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "all security groups must be non-empty")
public void testsecurityGroupsIterableBadFormat() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
options.securityGroups(ImmutableSet.of("group1", ""));
@ -133,7 +133,7 @@ public class AWSEC2TemplateOptionsTest {
assertEquals(options.getGroups(), ImmutableSet.of("group1", "group2"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "all security groups must be non-empty")
public void testsecurityGroupsVarArgsBadFormat() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
options.securityGroups("mygroup", "");
@ -164,7 +164,7 @@ public class AWSEC2TemplateOptionsTest {
assertEquals(options.getGroups(), ImmutableSet.of("group1", "group2"));
}
@Test(expectedExceptions = IllegalArgumentException.class)
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "use noKeyPair option to request boot without a keypair")
public void testkeyPairBadFormat() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
options.keyPair("");

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.aws.s3.blobstore.config;
import java.util.concurrent.TimeUnit;
import org.jclouds.aws.s3.AWSS3AsyncClient;
import org.jclouds.aws.s3.blobstore.AWSS3AsyncBlobStore;
import org.jclouds.aws.s3.blobstore.AWSS3BlobStore;
@ -28,18 +26,11 @@ import org.jclouds.aws.s3.blobstore.strategy.MultipartUploadStrategy;
import org.jclouds.aws.s3.blobstore.strategy.internal.ParallelMultipartUploadStrategy;
import org.jclouds.aws.s3.blobstore.strategy.internal.SequentialMultipartUploadStrategy;
import org.jclouds.blobstore.BlobRequestSigner;
import org.jclouds.cache.RetryingCacheLoaderDecorator;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.blobstore.S3AsyncBlobStore;
import org.jclouds.s3.blobstore.S3BlobRequestSigner;
import org.jclouds.s3.blobstore.S3BlobStore;
import org.jclouds.s3.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.s3.domain.AccessControlList;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
@ -64,23 +55,4 @@ public class AWSS3BlobStoreContextModule extends S3BlobStoreContextModule {
bind(BlobRequestSigner.class).to(new TypeLiteral<S3BlobRequestSigner<AWSS3AsyncClient>>() {
});
}
@Override
protected LoadingCache<String, AccessControlList> bucketAcls(final S3Client client) {
CacheLoader<String, AccessControlList> loader = RetryingCacheLoaderDecorator.newDecorator()
.on(ResourceNotFoundException.class).exponentiallyBackoff()
.decorate(
new CacheLoader<String, AccessControlList>() {
@Override
public AccessControlList load(String bucketName) {
return client.getBucketACL(bucketName);
}
@Override
public String toString() {
return "getBucketAcl()";
}
});
return CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build(loader);
}
}

View File

@ -18,14 +18,17 @@
*/
package org.jclouds.scriptbuilder.functionloader;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.ShellToken;
import org.jclouds.util.ClassLoadingUtils;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.io.Resources.getResource;
import static java.lang.String.format;
import static org.jclouds.scriptbuilder.domain.ShellToken.SH;
import java.io.IOException;
import org.jclouds.scriptbuilder.domain.OsFamily;
import com.google.common.io.Resources;
/**
* A {@link FunctionLoader} implementation which loads the target function from the classpath.
*/
@ -45,9 +48,8 @@ public enum BasicFunctionLoader implements FunctionLoader {
@Override
public String loadFunction(String function, OsFamily family) throws FunctionNotFoundException {
try {
return Resources.toString(ClassLoadingUtils.loadResource(
BasicFunctionLoader.class, String.format("/functions/%s.%s", function, ShellToken.SH.to(family))),
Charsets.UTF_8);
return Resources.toString(
getResource(BasicFunctionLoader.class, format("/functions/%s.%s", function, SH.to(family))), UTF_8);
} catch (IOException e) {
throw new FunctionNotFoundException(function, family, e);
}

View File

@ -22,6 +22,7 @@ import static com.google.common.base.Charsets.UTF_8;
import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Map;
import javax.inject.Singleton;
@ -29,7 +30,6 @@ import javax.inject.Singleton;
import org.jclouds.crypto.Sha512Crypt;
import org.jclouds.crypto.SshKeys;
import org.jclouds.scriptbuilder.statements.login.AdminAccess.Configuration;
import org.jclouds.util.PasswordGenerator;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
@ -59,9 +59,45 @@ public class DefaultConfiguration implements Configuration {
}
}
};
private final Supplier<String> passwordGenerator = PasswordGenerator.INSTANCE;
private final Function<String, String> cryptFunction = Sha512Crypt.function();
/**
* Cheap, lightweight, low-security password generator.
*
* @see <a href=
* "http://www.java-forums.org/java-lang/7355-how-create-lightweight-low-security-password-generator.html" />
*/
public enum PasswordGenerator implements Supplier<String> {
INSTANCE;
/** Minimum length for a decent password */
public static final int MIN_LENGTH = 10;
/** The random number generator. */
protected static final SecureRandom r = new SecureRandom();
/*
* Set of characters that is valid. Must be printable, memorable, and "won't break HTML" (i.e., not ' <', '>',
* '&', '=', ...). or break shell commands (i.e., not ' <', '>', '$', '!', ...). I, L and O are good to leave out,
* as are numeric zero and one.
*/
public static final char[] goodChar = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-',
'@', };
@Override
public String get() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < MIN_LENGTH; i++) {
sb.append(goodChar[r.nextInt(goodChar.length)]);
}
return sb.toString();
}
}
private final Function<String, String> cryptFunction = Sha512Crypt.function();
@Override
public Supplier<String> defaultAdminUsername() {
return defaultAdminUsername;
@ -74,7 +110,7 @@ public class DefaultConfiguration implements Configuration {
@Override
public Supplier<String> passwordGenerator() {
return passwordGenerator;
return PasswordGenerator.INSTANCE;
}
@Override