Merge branch 'master' of github.com:jclouds/jclouds into 1.5.x
* 'master' of github.com:jclouds/jclouds:
Issue 915: don't create full path on useradd
Issue 889: fixes error msg on aborting early wait for node-running.
update sshj to 0.8.0, fixing power-of-2 bug reported by me and fixed by aled
Issue 926: cleaned up usage of authentication client
removed awkward test, as this is now addressed at a higher level. Ex. malformed date string creation can be tested in jclouds-core
Issue 647: normalized use of IllegalArgumentException
Added a 'clear container' admin function to cf-tweetstore-spring
Added a 'clear container' admin function to runatcloud-tweetstore
Added a 'clear container' admin function to rhcloud-tweetstore
Added a 'clear container' admin function to gae-tweetstore-spring
Added a 'clear container' admin function to gae-tweetstore
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java
index aaa1c6f..c8b5152 100644
--- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java
+++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java
@@ -46,18 +46,29 @@
public interface AuthenticationAsyncClient {
/**
- * @see AuthenticationClient#authenticateTenantWithCredentials(String,PasswordCredentials)
+ * @see AuthenticationClient#authenticateWithTenantNameAndCredentials(String,PasswordCredentials)
*/
@POST
@SelectJson("access")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/tokens")
@MapBinder(BindAuthToJsonPayload.class)
- ListenableFuture<Access> authenticateTenantWithCredentials(@PayloadParam("tenantName") String tenantId,
+ ListenableFuture<Access> authenticateWithTenantNameAndCredentials(@PayloadParam("tenantName") String tenantName,
+ PasswordCredentials passwordCredentials);
+
+ /**
+ * @see AuthenticationClient#authenticateWithTenantIdAndCredentials(String,PasswordCredentials)
+ */
+ @POST
+ @SelectJson("access")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/tokens")
+ @MapBinder(BindAuthToJsonPayload.class)
+ ListenableFuture<Access> authenticateWithTenantIdAndCredentials(@PayloadParam("tenantId") String tenantId,
PasswordCredentials passwordCredentials);
/**
- * @see AuthenticationClient#authenticateTenantWithCredentials(String,ApiAccessKeyCredentials)
+ * @see AuthenticationClient#authenticateWithTenantNameAndCredentials(String,ApiAccessKeyCredentials)
*/
@POST
@SelectJson("access")
@@ -66,17 +77,17 @@
@MapBinder(BindAuthToJsonPayload.class)
// TODO: is tenantName permanent? or should we switch to tenantId at some point. seems most tools
// still use tenantName
- ListenableFuture<Access> authenticateTenantWithCredentials(@PayloadParam("tenantName") String tenantId,
+ ListenableFuture<Access> authenticateWithTenantNameAndCredentials(@PayloadParam("tenantName") String tenantName,
ApiAccessKeyCredentials apiAccessKeyCredentials);
/**
- * @see AuthenticationClient#authenticateTenantWithCredentials(String,ApiAccessKeyCredentials)
+ * @see AuthenticationClient#authenticateWithTenantIdAndCredentials(String,ApiAccessKeyCredentials)
*/
@POST
@SelectJson("access")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/tokens")
@MapBinder(BindAuthToJsonPayload.class)
- ListenableFuture<Access> authenticateTenantWithTenantIdAndCredentials(@PayloadParam("tenantId") String tenantId,
+ ListenableFuture<Access> authenticateWithTenantIdAndCredentials(@PayloadParam("tenantId") String tenantId,
ApiAccessKeyCredentials apiAccessKeyCredentials);
}
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java
index 2d8c042..167f6bb 100644
--- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java
+++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java
@@ -42,19 +42,26 @@
*
* @return access with token
*/
- Access authenticateTenantWithCredentials(String tenantId, PasswordCredentials passwordCredentials);
+ Access authenticateWithTenantNameAndCredentials(String tenantId, PasswordCredentials passwordCredentials);
/**
* Authenticate to generate a token.
*
* @return access with token
*/
- Access authenticateTenantWithCredentials(String tenantId, ApiAccessKeyCredentials passwordCredentials);
+ Access authenticateWithTenantIdAndCredentials(String tenantId, PasswordCredentials passwordCredentials);
+
+ /**
+ * Authenticate to generate a token.
+ *
+ * @return access with token
+ */
+ Access authenticateWithTenantNameAndCredentials(String tenantId, ApiAccessKeyCredentials passwordCredentials);
/**
* Authenticate to generate a token.
*
* @return access with token
*/
- Access authenticateTenantWithTenantIdAndCredentials(String tenantId, ApiAccessKeyCredentials passwordCredentials);
+ Access authenticateWithTenantIdAndCredentials(String tenantId, ApiAccessKeyCredentials passwordCredentials);
}
\ No newline at end of file
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java
index 035be75..d1aa97f 100644
--- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java
+++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java
@@ -42,7 +42,7 @@
public Access apply(Credentials input) {
if (input.identity.indexOf(':') == -1) {
throw new AuthorizationException(String.format("Identity %s does not match format tenantName:accessKey",
- input.identity), null);
+ input.identity), null);
}
String tenantId = input.identity.substring(0, input.identity.indexOf(':'));
@@ -50,12 +50,12 @@
String passwordOrSecretKey = input.credential;
ApiAccessKeyCredentials apiAccessKeyCredentials = ApiAccessKeyCredentials.createWithAccessKeyAndSecretKey(
- usernameOrAccessKey, passwordOrSecretKey);
+ usernameOrAccessKey, passwordOrSecretKey);
Access access;
- if(tenantId.matches("[0-9]*")) {
- access = client.authenticateTenantWithTenantIdAndCredentials(tenantId, apiAccessKeyCredentials);
+ if (tenantId.matches("^[0-9]+$")) {
+ access = client.authenticateWithTenantIdAndCredentials(tenantId, apiAccessKeyCredentials);
} else {
- access = client.authenticateTenantWithCredentials(tenantId, apiAccessKeyCredentials);
+ access = client.authenticateWithTenantNameAndCredentials(tenantId, apiAccessKeyCredentials);
}
return access;
}
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticatePasswordCredentials.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticatePasswordCredentials.java
index 0c59e02..aa997aa 100644
--- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticatePasswordCredentials.java
+++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticatePasswordCredentials.java
@@ -17,6 +17,7 @@
* under the License.
*/
package org.jclouds.openstack.keystone.v2_0.functions;
+
import javax.inject.Inject;
import org.jclouds.domain.Credentials;
@@ -39,16 +40,22 @@
public Access apply(Credentials input) {
if (input.identity.indexOf(':') == -1) {
throw new AuthorizationException(String.format("Identity %s does not match format tenantId:username",
- input.identity), null);
+ input.identity), null);
}
-
+
String tenantId = input.identity.substring(0, input.identity.indexOf(':'));
String usernameOrAccessKey = input.identity.substring(input.identity.indexOf(':') + 1);
String passwordOrSecretKey = input.credential;
PasswordCredentials passwordCredentials = PasswordCredentials.createWithUsernameAndPassword(usernameOrAccessKey,
- passwordOrSecretKey);
- return client.authenticateTenantWithCredentials(tenantId, passwordCredentials);
+ passwordOrSecretKey);
+ Access access;
+ if (tenantId.matches("^[0-9]+$")) {
+ access = client.authenticateWithTenantIdAndCredentials(tenantId, passwordCredentials);
+ } else {
+ access = client.authenticateWithTenantNameAndCredentials(tenantId, passwordCredentials);
+ }
+ return access;
}
@Override
diff --git a/compute/src/main/java/org/jclouds/compute/strategy/CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java b/compute/src/main/java/org/jclouds/compute/strategy/CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java
index 38612f5..67f48be 100644
--- a/compute/src/main/java/org/jclouds/compute/strategy/CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java
+++ b/compute/src/main/java/org/jclouds/compute/strategy/CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java
@@ -47,6 +47,7 @@
import com.google.common.base.Function;
import com.google.common.base.Predicate;
+import com.google.common.base.Stopwatch;
import com.google.common.collect.Multimap;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
@@ -127,16 +128,26 @@
try {
if (options.shouldBlockUntilRunning()) {
try {
+ Stopwatch stopwatch = new Stopwatch().start();
if (!nodeRunning.apply(node)) {
+ long timeWaited = stopwatch.elapsedMillis();
+ long earlyReturnGrace = 10; // sleeps can sometimes return milliseconds early
+
if (node.get() == null) {
node.set(originalNode);
throw new IllegalStateException(format("api response for node(%s) was null, so we can't customize",
originalId));
+ } else if (timeWaited < (timeouts.nodeRunning - earlyReturnGrace)) {
+ throw new IllegalStateException(
+ format(
+ "node(%s) didn't achieve the state running, so we couldn't customize; aborting prematurely after %d seconds with final state: %s",
+ originalId, timeWaited / 1000, node.get().getState()));
+ } else {
+ throw new IllegalStateException(
+ format(
+ "node(%s) didn't achieve the state running within %d seconds, so we couldn't customize; final state: %s",
+ originalId, timeouts.nodeRunning / 1000, node.get().getState()));
}
- throw new IllegalStateException(
- format(
- "node(%s) didn't achieve the state running within %d seconds, so we couldn't customize; final state: %s",
- originalId, timeouts.nodeRunning / 1000, node.get().getState()));
}
} catch (IllegalStateException e) {
if (node.get().getState() == NodeState.TERMINATED) {
diff --git a/compute/src/test/java/org/jclouds/compute/callables/RunScriptOnNodeUsingSshTest.java b/compute/src/test/java/org/jclouds/compute/callables/RunScriptOnNodeUsingSshTest.java
index 7030c05..2a6bed2 100644
--- a/compute/src/test/java/org/jclouds/compute/callables/RunScriptOnNodeUsingSshTest.java
+++ b/compute/src/test/java/org/jclouds/compute/callables/RunScriptOnNodeUsingSshTest.java
@@ -126,7 +126,7 @@
expect(sshClient.getUsername()).andReturn("tester");
expect(sshClient.getHostAddress()).andReturn("somewhere.example.com");
expect(
- sshClient.exec("sudo sh <<'RUN_SCRIPT_AS_ROOT_SSH'\n" + "mkdir -p /home/users/testuser\n"
+ sshClient.exec("sudo sh <<'RUN_SCRIPT_AS_ROOT_SSH'\n" + "mkdir -p /home/users\n"
+ "useradd -s /bin/bash -m -d /home/users/testuser testuser\n"
+ "chown -R testuser /home/users/testuser\n" + "RUN_SCRIPT_AS_ROOT_SSH\n")).andReturn(
new ExecResponse("done", null, 0));
diff --git a/compute/src/test/java/org/jclouds/compute/strategy/CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest.java b/compute/src/test/java/org/jclouds/compute/strategy/CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest.java
index 9e3db80..9b36d3a 100644
--- a/compute/src/test/java/org/jclouds/compute/strategy/CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest.java
+++ b/compute/src/test/java/org/jclouds/compute/strategy/CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest.java
@@ -23,6 +23,7 @@
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -91,8 +92,9 @@
assertEquals(goodNodes.size(), 0);
assertEquals(badNodes.keySet(), ImmutableSet.of(node));
- assertEquals(badNodes.get(node).getMessage(),
- "node(id) didn't achieve the state running within 1200 seconds, so we couldn't customize; final state: PENDING");
+ assertTrue(badNodes.get(node).getMessage() != null && badNodes.get(node).getMessage().matches(
+ "node\\(id\\) didn't achieve the state running, so we couldn't customize; aborting prematurely after .* seconds with final state: PENDING"),
+ badNodes.get(node).getMessage());
assertEquals(customizationResponses.size(), 0);
// verify mocks
diff --git a/compute/src/test/resources/initscript_with_java.sh b/compute/src/test/resources/initscript_with_java.sh
index f4220a0..093c4c2 100644
--- a/compute/src/test/resources/initscript_with_java.sh
+++ b/compute/src/test/resources/initscript_with_java.sh
@@ -182,7 +182,7 @@
%wheel ALL = (ALL) NOPASSWD:ALL
END_OF_JCLOUDS_FILE
chmod 0440 /etc/sudoers
- mkdir -p /home/users/defaultAdminUsername
+ mkdir -p /home/users
groupadd -f wheel
useradd -s /bin/bash -g wheel -m -d /home/users/defaultAdminUsername -p 'crypt(randompassword)' defaultAdminUsername
mkdir -p /home/users/defaultAdminUsername/.ssh
diff --git a/compute/src/test/resources/initscript_with_jboss.sh b/compute/src/test/resources/initscript_with_jboss.sh
index 031c842..f9bd795 100644
--- a/compute/src/test/resources/initscript_with_jboss.sh
+++ b/compute/src/test/resources/initscript_with_jboss.sh
@@ -182,7 +182,7 @@
%wheel ALL = (ALL) NOPASSWD:ALL
END_OF_JCLOUDS_FILE
chmod 0440 /etc/sudoers
- mkdir -p /home/users/web
+ mkdir -p /home/users
groupadd -f wheel
useradd -s /bin/bash -g wheel -m -d /home/users/web -p 'crypt(randompassword)' web
mkdir -p /home/users/web/.ssh
diff --git a/compute/src/test/resources/runscript_adminUpdate.sh b/compute/src/test/resources/runscript_adminUpdate.sh
index 802e808..e2f9a53 100644
--- a/compute/src/test/resources/runscript_adminUpdate.sh
+++ b/compute/src/test/resources/runscript_adminUpdate.sh
@@ -89,7 +89,7 @@
%wheel ALL = (ALL) NOPASSWD:ALL
END_OF_JCLOUDS_FILE
chmod 0440 /etc/sudoers
- mkdir -p /over/ridden/foo
+ mkdir -p /over/ridden
groupadd -f wheel
useradd -s /bin/bash -g wheel -m -d /over/ridden/foo -p 'crypt(randompassword)' foo
mkdir -p /over/ridden/foo/.ssh
diff --git a/core/src/main/java/org/jclouds/date/DateCodec.java b/core/src/main/java/org/jclouds/date/DateCodec.java
index 9e31161..8570b58 100644
--- a/core/src/main/java/org/jclouds/date/DateCodec.java
+++ b/core/src/main/java/org/jclouds/date/DateCodec.java
@@ -1,12 +1,41 @@
+/**
+ * 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.date;
-import java.text.ParseException;
import java.util.Date;
+/**
+ * converting from Date->String and vice versa.
+ *
+ * @author aled
+ */
public interface DateCodec {
- public Date toDate(String date) throws ParseException;
-
+ /**
+ * @param toParse
+ * text to parse
+ * @return parsed date
+ * @throws IllegalArgumentException
+ * if the input is invalid
+ */
+ public Date toDate(String date) throws IllegalArgumentException;
+
public String toString(Date date);
-
+
}
diff --git a/core/src/main/java/org/jclouds/date/DateCodecFactory.java b/core/src/main/java/org/jclouds/date/DateCodecFactory.java
index 4dd0b97..0087298 100644
--- a/core/src/main/java/org/jclouds/date/DateCodecFactory.java
+++ b/core/src/main/java/org/jclouds/date/DateCodecFactory.java
@@ -1,6 +1,24 @@
+/**
+ * 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.date;
-import org.jclouds.date.internal.SimpleDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory;
import com.google.inject.ImplementedBy;
@@ -10,7 +28,7 @@
*
* @author aled
*/
-@ImplementedBy(SimpleDateCodecFactory.class)
+@ImplementedBy(DateServiceDateCodecFactory.class)
public interface DateCodecFactory {
public DateCodec rfc1123();
diff --git a/core/src/main/java/org/jclouds/date/DateService.java b/core/src/main/java/org/jclouds/date/DateService.java
index a8c0e2d..75bfd55 100644
--- a/core/src/main/java/org/jclouds/date/DateService.java
+++ b/core/src/main/java/org/jclouds/date/DateService.java
@@ -40,14 +40,24 @@
String cDateFormat();
- Date cDateParse(String toParse);
+ /**
+ * @param toParse text to parse
+ * @return parsed date
+ * @throws IllegalArgumentException if the input is invalid
+ */
+ Date cDateParse(String toParse) throws IllegalArgumentException;
String rfc822DateFormat(Date date);
String rfc822DateFormat();
-
- Date rfc822DateParse(String toParse);
-
+
+ /**
+ * @param toParse text to parse
+ * @return parsed date
+ * @throws IllegalArgumentException if the input is invalid
+ */
+ Date rfc822DateParse(String toParse) throws IllegalArgumentException;
+
String iso8601SecondsDateFormat(Date dateTime);
String iso8601SecondsDateFormat();
@@ -55,15 +65,30 @@
String iso8601DateFormat(Date date);
String iso8601DateFormat();
+
+ /**
+ * @param toParse text to parse
+ * @return parsed date
+ * @throws IllegalArgumentException if the input is invalid
+ */
+ Date iso8601DateParse(String toParse) throws IllegalArgumentException;
- Date iso8601DateParse(String toParse);
-
- Date iso8601SecondsDateParse(String toParse);
+ /**
+ * @param toParse text to parse
+ * @return parsed date
+ * @throws IllegalArgumentException if the input is invalid
+ */
+ Date iso8601SecondsDateParse(String toParse) throws IllegalArgumentException;
String rfc1123DateFormat(Date date);
String rfc1123DateFormat();
- Date rfc1123DateParse(String toParse);
+ /**
+ * @param toParse text to parse
+ * @return parsed date
+ * @throws IllegalArgumentException if the input is invalid
+ */
+ Date rfc1123DateParse(String toParse) throws IllegalArgumentException;
}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/date/internal/DateServiceDateCodecFactory.java b/core/src/main/java/org/jclouds/date/internal/DateServiceDateCodecFactory.java
new file mode 100644
index 0000000..62f54f6
--- /dev/null
+++ b/core/src/main/java/org/jclouds/date/internal/DateServiceDateCodecFactory.java
@@ -0,0 +1,74 @@
+/**
+ * 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.date.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Date;
+
+import javax.inject.Singleton;
+
+import org.jclouds.date.DateCodec;
+import org.jclouds.date.DateCodecFactory;
+import org.jclouds.date.DateService;
+
+import com.google.inject.Inject;
+
+@Singleton
+public class DateServiceDateCodecFactory implements DateCodecFactory {
+
+ private final DateCodec rfc1123Codec;
+
+ @Inject
+ public DateServiceDateCodecFactory(DateServiceRfc1123Codec rfc1123Codec) {
+ this.rfc1123Codec = checkNotNull(rfc1123Codec, "rfc1123Codec");
+ }
+
+ @Singleton
+ public static class DateServiceRfc1123Codec implements DateCodec {
+
+ private final DateService dateService;
+
+ @Inject
+ public DateServiceRfc1123Codec(final DateService dateService) {
+ this.dateService = checkNotNull(dateService, "dateService");
+ }
+
+ @Override
+ public Date toDate(String date) throws IllegalArgumentException {
+ return dateService.rfc1123DateParse(date);
+ }
+
+ @Override
+ public String toString(Date date) {
+ return dateService.rfc1123DateFormat(date);
+ }
+
+ @Override
+ public String toString() {
+ return "rfc1123Codec [dateService=" + dateService + "]";
+ }
+
+ }
+
+ public DateCodec rfc1123() {
+ return rfc1123Codec;
+ }
+
+}
diff --git a/core/src/main/java/org/jclouds/date/internal/SimpleDateCodecFactory.java b/core/src/main/java/org/jclouds/date/internal/SimpleDateCodecFactory.java
deleted file mode 100644
index 20a0b78..0000000
--- a/core/src/main/java/org/jclouds/date/internal/SimpleDateCodecFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.jclouds.date.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.text.ParseException;
-import java.util.Date;
-
-import org.jclouds.date.DateCodec;
-import org.jclouds.date.DateCodecFactory;
-import org.jclouds.date.DateService;
-
-import com.google.inject.Inject;
-
-public class SimpleDateCodecFactory implements DateCodecFactory {
-
- private final DateService dateService;
-
- private volatile DateCodec rfc1123Codec;
-
- @Inject
- public SimpleDateCodecFactory(final DateService dateService) {
- this.dateService = checkNotNull(dateService, "dateService");
- }
-
- public DateCodec rfc1123() {
- if (rfc1123Codec == null) {
- rfc1123Codec = new DateCodec() {
- @Override
- public Date toDate(String date) throws ParseException {
- return dateService.rfc1123DateParse(date);
- }
-
- @Override
- public String toString(Date date) {
- return dateService.rfc1123DateFormat(date);
- }
- };
- }
- return rfc1123Codec;
- }
-}
diff --git a/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java b/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java
index bcff3f0..dd96f2a 100644
--- a/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java
+++ b/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java
@@ -89,7 +89,7 @@
try {
return cSimpleDateFormat.parse(toParse);
} catch (ParseException pe) {
- throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
+ throw new IllegalArgumentException("Error parsing data at " + pe.getErrorOffset(), pe);
}
}
}
@@ -112,7 +112,7 @@
try {
return rfc822SimpleDateFormat.parse(toParse);
} catch (ParseException pe) {
- throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
+ throw new IllegalArgumentException("Error parsing data at " + pe.getErrorOffset(), pe);
}
}
}
@@ -141,6 +141,8 @@
@Override
public final Date iso8601DateParse(String toParse) {
+ if (toParse.length() < 10)
+ throw new IllegalArgumentException("incorrect date format " + toParse);
String tz = findTZ(toParse);
toParse = trimToMillis(toParse);
toParse = trimTZ(toParse);
@@ -151,13 +153,15 @@
try {
return iso8601SimpleDateFormat.parse(toParse);
} catch (ParseException pe) {
- throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
+ throw new IllegalArgumentException("Error parsing data at " + pe.getErrorOffset(), pe);
}
}
}
@Override
public final Date iso8601SecondsDateParse(String toParse) {
+ if (toParse.length() < 10)
+ throw new IllegalArgumentException("incorrect date format " + toParse);
String tz = findTZ(toParse);
toParse = trimToMillis(toParse);
toParse = trimTZ(toParse);
@@ -168,7 +172,7 @@
try {
return iso8601SecondsSimpleDateFormat.parse(toParse);
} catch (ParseException pe) {
- throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
+ throw new IllegalArgumentException("Error parsing data at " + pe.getErrorOffset(), pe);
}
}
}
@@ -198,12 +202,12 @@
}
@Override
- public final Date rfc1123DateParse(String toParse) {
+ public final Date rfc1123DateParse(String toParse) throws IllegalArgumentException {
synchronized (rfc1123SimpleDateFormat) {
try {
return rfc1123SimpleDateFormat.parse(toParse);
} catch (ParseException pe) {
- throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
+ throw new IllegalArgumentException("Error parsing data at " + pe.getErrorOffset(), pe);
}
}
}
diff --git a/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java b/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java
index 4d2c801..64faacf 100644
--- a/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java
+++ b/core/src/main/java/org/jclouds/io/ContentMetadataCodec.java
@@ -5,7 +5,6 @@
import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.HttpHeaders.EXPIRES;
-import java.text.ParseException;
import java.util.Date;
import java.util.Map.Entry;
@@ -17,10 +16,8 @@
import org.jclouds.date.DateCodecFactory;
import org.jclouds.io.ContentMetadataCodec.DefaultContentMetadataCodec;
import org.jclouds.logging.Logger;
-import org.jclouds.util.Throwables2;
import com.google.common.base.Predicate;
-import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.Multimap;
@@ -117,13 +114,10 @@
public Date parseExpires(String expires) {
try {
return (expires != null) ? getExpiresDateCodec().toDate(expires) : null;
- } catch (Exception e) {
- if (Throwables2.getFirstThrowableOfType(e, ParseException.class) != null) {
- logger.debug("Invalid Expires header (%s); should be in RFC-1123 format; treating as already expired: %s", expires, e.getMessage());
- return new Date(0);
- } else {
- throw Throwables.propagate(e);
- }
+ } catch (IllegalArgumentException e) {
+ logger.debug("Invalid Expires header (%s); should be in RFC-1123 format; treating as already expired: %s",
+ expires, e.getMessage());
+ return new Date(0);
}
}
}
diff --git a/core/src/test/java/org/jclouds/date/DateServiceTest.java b/core/src/test/java/org/jclouds/date/DateServiceTest.java
index 2458a23..7dcf5d2 100644
--- a/core/src/test/java/org/jclouds/date/DateServiceTest.java
+++ b/core/src/test/java/org/jclouds/date/DateServiceTest.java
@@ -23,7 +23,6 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import java.util.concurrent.ExecutionException;
import org.jclouds.PerformanceTest;
import org.testng.annotations.BeforeTest;
@@ -96,90 +95,110 @@
}
@Test
- public void testIso8601DateParse() throws ExecutionException, InterruptedException {
+ public void testIso8601DateParse() {
Date dsDate = dateService.iso8601DateParse(testData[0].iso8601DateString);
assertEquals(dsDate, testData[0].date);
}
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testIso8601DateParseIllegal() {
+ dateService.iso8601DateParse("-1");
+ }
+
@Test
- public void testIso8601DateParseTz() throws ExecutionException, InterruptedException {
+ public void testIso8601DateParseTz() {
Date dsDate = dateService.iso8601SecondsDateParse(testData[0].iso8601DateStringTz);
assertEquals(dsDate, testData[0].date);
}
@Test
- public void testIso8601SecondsDateParse() throws ExecutionException, InterruptedException {
+ public void testIso8601SecondsDateParse() {
Date dsDate = dateService.iso8601SecondsDateParse(testData[0].iso8601SecondsDateString);
assertEquals(dsDate, testData[0].date);
}
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testIso8601SecondsDateParseIllegal() {
+ dateService.iso8601SecondsDateParse("-1");
+ }
@Test
- public void testCDateParse() throws ExecutionException, InterruptedException {
+ public void testCDateParse() {
Date dsDate = dateService.cDateParse(testData[0].cDateString);
assertEquals(dsDate, testData[0].date);
}
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testCDateParseIllegal() {
+ dateService.cDateParse("foo");
+ }
+
@Test
- public void testRfc822DateParse() throws ExecutionException, InterruptedException {
+ public void testRfc822DateParse() {
Date dsDate = dateService.rfc822DateParse(testData[0].rfc822DateString);
assertEquals(dsDate, testData[0].date);
}
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testRfc822DateParseIllegal() {
+ dateService.rfc822DateParse("foo");
+ }
@Test
- public void testIso8601DateFormat() throws ExecutionException, InterruptedException {
+ public void testIso8601DateFormat() {
String dsString = dateService.iso8601DateFormat(testData[0].date);
assertEquals(dsString, testData[0].iso8601DateString);
}
@Test
- public void testIso8601SecondsDateFormat() throws ExecutionException, InterruptedException {
+ public void testIso8601SecondsDateFormat() {
String dsString = dateService.iso8601SecondsDateFormat(testData[0].date);
assertEquals(dsString, testData[0].iso8601SecondsDateString);
}
@Test
- public void testCDateFormat() throws ExecutionException, InterruptedException {
+ public void testCDateFormat() {
String dsString = dateService.cDateFormat(testData[0].date);
assertEquals(dsString, testData[0].cDateString);
}
@Test
- public void testRfc822DateFormat() throws ExecutionException, InterruptedException {
+ public void testRfc822DateFormat() {
String dsString = dateService.rfc822DateFormat(testData[0].date);
assertEquals(dsString, testData[0].rfc822DateString);
}
@Test
- void testIso8601DateFormatResponseTime() throws ExecutionException, InterruptedException {
+ void testIso8601DateFormatResponseTime() {
for (int i = 0; i < LOOP_COUNT; i++)
dateService.iso8601DateFormat();
}
@Test
- void testFromSeconds() throws ExecutionException, InterruptedException {
+ void testFromSeconds() {
long seconds = 1254008225;
Date date = dateService.fromSeconds(seconds);
assertEquals(dateService.iso8601SecondsDateFormat(date), "2009-09-26T23:37:05Z");
}
@Test
- void testTz() throws ExecutionException, InterruptedException {
+ void testTz() {
assertEquals(dateService.iso8601SecondsDateParse("2011-05-26T02:14:13-04:00").getTime(), 1306390453000l);
}
@Test
- void testTzNoT() throws ExecutionException, InterruptedException {
+ void testTzNoT() {
assertEquals(dateService.iso8601DateParse("2011-05-25 16:12:21.656+0000").getTime(), 1306339941656l);
}
@Test
- void testRfc822DateFormatResponseTime() throws ExecutionException, InterruptedException {
+ void testRfc822DateFormatResponseTime() {
for (int i = 0; i < LOOP_COUNT; i++)
dateService.rfc822DateFormat();
}
@Test
- void testCDateFormatResponseTime() throws ExecutionException, InterruptedException {
+ void testCDateFormatResponseTime() {
for (int i = 0; i < LOOP_COUNT; i++)
dateService.cDateFormat();
}
@@ -212,7 +231,7 @@
}
@Test
- void testParseIso8601DateSerialResponseTime() throws ExecutionException, InterruptedException {
+ void testParseIso8601DateSerialResponseTime() {
for (int i = 0; i < LOOP_COUNT; i++)
dateService.iso8601DateParse(testData[0].iso8601DateString);
}
diff --git a/core/src/test/java/org/jclouds/date/internal/DateServiceDateCodecFactoryTest.java b/core/src/test/java/org/jclouds/date/internal/DateServiceDateCodecFactoryTest.java
new file mode 100644
index 0000000..6c6f12a
--- /dev/null
+++ b/core/src/test/java/org/jclouds/date/internal/DateServiceDateCodecFactoryTest.java
@@ -0,0 +1,65 @@
+/**
+ * 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.date.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.util.Date;
+
+import org.jclouds.date.DateCodec;
+import org.jclouds.date.internal.DateServiceDateCodecFactory.DateServiceRfc1123Codec;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author aled
+ *
+ */
+@Test(testName = "DateServiceDateCodecFactoryTest")
+public class DateServiceDateCodecFactoryTest {
+
+ private DateServiceDateCodecFactory simpleDateCodecFactory;
+ private DateCodec rfc1123Codec;
+
+ @BeforeMethod
+ public void setUp() {
+ simpleDateCodecFactory = new DateServiceDateCodecFactory(new DateServiceRfc1123Codec(
+ new SimpleDateFormatDateService()));
+ rfc1123Codec = simpleDateCodecFactory.rfc1123();
+ }
+
+ @Test
+ public void testCodecForRfc1123() {
+ Date date = new Date(1000);
+ assertEquals(rfc1123Codec.toDate(rfc1123Codec.toString(date)), date);
+
+ assertEquals(rfc1123Codec.toDate("Thu, 01 Dec 1994 16:00:00 GMT"), new Date(786297600000L));
+ }
+
+ @Test
+ public void testCodecForRfc1123ThrowsParseExceptionWhenMalformed() {
+ try {
+ rfc1123Codec.toDate("wrong");
+ fail();
+ } catch (IllegalArgumentException e) {
+ }
+ }
+}
diff --git a/core/src/test/java/org/jclouds/date/internal/SimpleDateCodecFactoryTest.java b/core/src/test/java/org/jclouds/date/internal/SimpleDateCodecFactoryTest.java
deleted file mode 100644
index 7e03049..0000000
--- a/core/src/test/java/org/jclouds/date/internal/SimpleDateCodecFactoryTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.jclouds.date.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
-
-import java.text.ParseException;
-import java.util.Date;
-
-import org.jclouds.date.DateCodec;
-import org.jclouds.util.Throwables2;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-public class SimpleDateCodecFactoryTest {
-
- private SimpleDateCodecFactory simpleDateCodecFactory;
- private DateCodec rfc1123Codec;
-
- @BeforeMethod
- public void setUp() throws Exception {
- simpleDateCodecFactory = new SimpleDateCodecFactory(new SimpleDateFormatDateService());
- rfc1123Codec = simpleDateCodecFactory.rfc1123();
- }
-
- @Test
- public void testCodecForRfc1123() throws Exception {
- Date date = new Date(1000);
- assertEquals(rfc1123Codec.toDate(rfc1123Codec.toString(date)), date);
-
- assertEquals(rfc1123Codec.toDate("Thu, 01 Dec 1994 16:00:00 GMT"), new Date(786297600000L));
- }
-
- @Test
- public void testCodecForRfc1123ThrowsParseExceptionWhenMalformed() throws Exception {
- try {
- rfc1123Codec.toDate("wrong");
- fail();
- } catch (Exception e) {
- if (Throwables2.getFirstThrowableOfType(e, ParseException.class) == null) {
- throw e;
- }
- }
- }
-}
diff --git a/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java b/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java
index 1672e5a..6861f9d 100644
--- a/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java
+++ b/core/src/test/java/org/jclouds/http/handlers/BackoffLimitedRetryHandlerTest.java
@@ -34,7 +34,8 @@
import javax.net.ssl.SSLSession;
import javax.ws.rs.core.UriBuilder;
-import org.jclouds.date.internal.SimpleDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory.DateServiceRfc1123Codec;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.BaseJettyTest;
import org.jclouds.http.HttpCommand;
@@ -47,8 +48,8 @@
import org.jclouds.http.internal.HttpWire;
import org.jclouds.http.internal.JavaUrlHttpCommandExecutorService;
import org.jclouds.io.ContentMetadataCodec;
-import org.jclouds.io.Payloads;
import org.jclouds.io.ContentMetadataCodec.DefaultContentMetadataCodec;
+import org.jclouds.io.Payloads;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@@ -116,7 +117,7 @@
BackoffLimitedRetryHandler backoff = new BackoffLimitedRetryHandler();
HttpUtils utils = new HttpUtils(0, 500, 1, 1);
ContentMetadataCodec contentMetadataCodec = new DefaultContentMetadataCodec(
- new SimpleDateCodecFactory(new SimpleDateFormatDateService()));
+ new DateServiceDateCodecFactory(new DateServiceRfc1123Codec(new SimpleDateFormatDateService())));
RedirectionRetryHandler retry = new RedirectionRetryHandler(uriBuilderProvider, backoff);
JavaUrlHttpCommandExecutorService httpService = new JavaUrlHttpCommandExecutorService(utils,
contentMetadataCodec, execService,
diff --git a/core/src/test/java/org/jclouds/rest/internal/BaseRestClientExpectTest.java b/core/src/test/java/org/jclouds/rest/internal/BaseRestClientExpectTest.java
index 7987f33..38630f5 100644
--- a/core/src/test/java/org/jclouds/rest/internal/BaseRestClientExpectTest.java
+++ b/core/src/test/java/org/jclouds/rest/internal/BaseRestClientExpectTest.java
@@ -49,7 +49,8 @@
import org.jclouds.concurrent.MoreExecutors;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
-import org.jclouds.date.internal.SimpleDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory.DateServiceRfc1123Codec;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpRequest;
@@ -123,7 +124,7 @@
protected String provider = "mock";
protected ContentMetadataCodec contentMetadataCodec = new DefaultContentMetadataCodec(
- new SimpleDateCodecFactory(new SimpleDateFormatDateService()));
+ new DateServiceDateCodecFactory(new DateServiceRfc1123Codec(new SimpleDateFormatDateService())));
/**
* Override this to supply alternative bindings for use in the test. This is commonly used to
diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java
index 768ec59..3fd8549 100644
--- a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java
+++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java
@@ -48,6 +48,7 @@
import org.jclouds.demo.paas.service.taskqueue.TaskQueue;
import org.jclouds.demo.tweetstore.config.util.CredentialsCollector;
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
+import org.jclouds.demo.tweetstore.controller.ClearTweetsController;
import org.jclouds.demo.tweetstore.controller.EnqueueStoresController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses;
@@ -173,6 +174,11 @@
return new EnqueueStoresController(providerTypeToBlobStoreMap, queue, baseUrl);
}
+ @Bean
+ public ClearTweetsController clearTweetsController() {
+ return new ClearTweetsController(providerTypeToBlobStoreMap, container);
+ }
+
private void injectServletConfig(Servlet servlet) {
LOGGER.trace("About to inject servlet config '%s'", servletConfig);
try {
@@ -195,6 +201,7 @@
urlMap.put("/store/*", storeTweetsController());
urlMap.put("/tweets/*", addTweetsController());
urlMap.put("/stores/*", enqueueStoresController());
+ urlMap.put("/clear/*", clearTweetsController());
mapping.setUrlMap(urlMap);
/*
* "/store", "/tweets" and "/stores" are part of the servlet mapping and thus
diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
new file mode 100644
index 0000000..e08cfbc
--- /dev/null
+++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
@@ -0,0 +1,96 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Strings.nullToEmpty;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Grab tweets related to me and store them into blobstores
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class ClearTweetsController extends HttpServlet {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 7215420527854203714L;
+
+ private final Map<String, BlobStoreContext> contexts;
+ private final String container;
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ @VisibleForTesting
+ public ClearTweetsController(Map<String, BlobStoreContext> contexts,
+ @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) {
+ this.container = container;
+ this.contexts = contexts;
+ }
+
+ @VisibleForTesting
+ public void clearContainer(String contextName) {
+ BlobStoreContext context = checkNotNull(contexts.get(contextName),
+ "no context for %s in %s", contextName, contexts.keySet());
+ try {
+ context.getBlobStore().clearContainer(container);
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets in %s/%s", container, context);
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ if (nullToEmpty(request.getHeader("X-Originator")).equals("admin")) {
+ try {
+ String contextName = checkNotNull(request.getHeader("context"), "missing header context");
+ logger.info("clearing tweets in %s/%s", container, contextName);
+ clearContainer(contextName);
+ logger.debug("done clearing tweets");
+ response.setContentType(MediaType.TEXT_PLAIN);
+ response.getWriter().println("Done!");
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets");
+ throw new ServletException(e);
+ }
+ } else {
+ response.sendError(401);
+ }
+ }
+}
\ No newline at end of file
diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/webapp/WEB-INF/web.xml b/demos/tweetstore/cf-tweetstore-spring/src/main/webapp/WEB-INF/web.xml
index 4b760f2..51dd074 100644
--- a/demos/tweetstore/cf-tweetstore-spring/src/main/webapp/WEB-INF/web.xml
+++ b/demos/tweetstore/cf-tweetstore-spring/src/main/webapp/WEB-INF/web.xml
@@ -67,6 +67,10 @@
<servlet-name>dispatcher</servlet-name>
<url-pattern>/stores/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>dispatcher</servlet-name>
+ <url-pattern>/clear/*</url-pattern>
+ </servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
diff --git a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
new file mode 100644
index 0000000..81f0b9f
--- /dev/null
+++ b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
@@ -0,0 +1,72 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.TransientApiMetadata;
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@code AddTweetsController}
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class ClearTweetsControllerTest {
+
+ Map<String, BlobStoreContext> createBlobStores(String container) throws InterruptedException, ExecutionException {
+ TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build();
+ Map<String, BlobStoreContext> contexts = ImmutableMap.<String, BlobStoreContext>of(
+ "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class),
+ "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class));
+ for (BlobStoreContext blobstore : contexts.values()) {
+ blobstore.getBlobStore().createContainerInLocation(null, container);
+ Blob blob = blobstore.getAsyncBlobStore().blobBuilder("1").build();
+ blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank");
+ blob.setPayload("I love beans!");
+ blobstore.getBlobStore().putBlob(container, blob);
+ }
+ return contexts;
+ }
+
+ public void testClearTweets() throws IOException, InterruptedException, ExecutionException {
+ String container = ClearTweetsControllerTest.class.getName() + "#container";
+ Map<String, BlobStoreContext> contexts = createBlobStores(container);
+
+ ClearTweetsController controller = new ClearTweetsController(contexts,
+ container);
+ controller.clearContainer("test1");
+ controller.clearContainer("test2");
+
+ for (BlobStoreContext context : contexts.values()) {
+ assertEquals(context.getBlobStore().countBlobs(container), 0, context.toString());
+ }
+ }
+}
diff --git a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java
index c925dc5..9bfba4a 100644
--- a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java
+++ b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java
@@ -46,6 +46,7 @@
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.demo.tweetstore.config.util.CredentialsCollector;
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
+import org.jclouds.demo.tweetstore.controller.ClearTweetsController;
import org.jclouds.demo.tweetstore.controller.EnqueueStoresController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
import org.jclouds.demo.tweetstore.functions.ServiceToStoredTweetStatuses;
@@ -172,6 +173,11 @@
return new EnqueueStoresController(providerTypeToBlobStoreMap, queue);
}
+ @Bean
+ public ClearTweetsController clearTweetsController() {
+ return new ClearTweetsController(providerTypeToBlobStoreMap, container);
+ }
+
private void injectServletConfig(Servlet servlet) {
LOGGER.trace("About to inject servlet config '%s'", servletConfig);
try {
@@ -194,6 +200,7 @@
urlMap.put("/store/*", storeTweetsController());
urlMap.put("/tweets/*", addTweetsController());
urlMap.put("/stores/*", enqueueStoresController());
+ urlMap.put("/clear/*", clearTweetsController());
mapping.setUrlMap(urlMap);
/*
* "/store", "/tweets" and "/stores" are part of the servlet mapping and thus
diff --git a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
new file mode 100644
index 0000000..e08cfbc
--- /dev/null
+++ b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
@@ -0,0 +1,96 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Strings.nullToEmpty;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Grab tweets related to me and store them into blobstores
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class ClearTweetsController extends HttpServlet {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 7215420527854203714L;
+
+ private final Map<String, BlobStoreContext> contexts;
+ private final String container;
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ @VisibleForTesting
+ public ClearTweetsController(Map<String, BlobStoreContext> contexts,
+ @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) {
+ this.container = container;
+ this.contexts = contexts;
+ }
+
+ @VisibleForTesting
+ public void clearContainer(String contextName) {
+ BlobStoreContext context = checkNotNull(contexts.get(contextName),
+ "no context for %s in %s", contextName, contexts.keySet());
+ try {
+ context.getBlobStore().clearContainer(container);
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets in %s/%s", container, context);
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ if (nullToEmpty(request.getHeader("X-Originator")).equals("admin")) {
+ try {
+ String contextName = checkNotNull(request.getHeader("context"), "missing header context");
+ logger.info("clearing tweets in %s/%s", container, contextName);
+ clearContainer(contextName);
+ logger.debug("done clearing tweets");
+ response.setContentType(MediaType.TEXT_PLAIN);
+ response.getWriter().println("Done!");
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets");
+ throw new ServletException(e);
+ }
+ } else {
+ response.sendError(401);
+ }
+ }
+}
\ No newline at end of file
diff --git a/demos/tweetstore/gae-tweetstore-spring/src/main/webapp/WEB-INF/web.xml b/demos/tweetstore/gae-tweetstore-spring/src/main/webapp/WEB-INF/web.xml
index 971ada2..3853142 100644
--- a/demos/tweetstore/gae-tweetstore-spring/src/main/webapp/WEB-INF/web.xml
+++ b/demos/tweetstore/gae-tweetstore-spring/src/main/webapp/WEB-INF/web.xml
@@ -45,6 +45,10 @@
<servlet-name>dispatcher</servlet-name>
<url-pattern>/stores/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>dispatcher</servlet-name>
+ <url-pattern>/clear/*</url-pattern>
+ </servlet-mapping>
<!-- limit submission of storage tasks to the cron job -->
<security-constraint>
diff --git a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
new file mode 100644
index 0000000..81f0b9f
--- /dev/null
+++ b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
@@ -0,0 +1,72 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.TransientApiMetadata;
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@code AddTweetsController}
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class ClearTweetsControllerTest {
+
+ Map<String, BlobStoreContext> createBlobStores(String container) throws InterruptedException, ExecutionException {
+ TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build();
+ Map<String, BlobStoreContext> contexts = ImmutableMap.<String, BlobStoreContext>of(
+ "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class),
+ "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class));
+ for (BlobStoreContext blobstore : contexts.values()) {
+ blobstore.getBlobStore().createContainerInLocation(null, container);
+ Blob blob = blobstore.getAsyncBlobStore().blobBuilder("1").build();
+ blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank");
+ blob.setPayload("I love beans!");
+ blobstore.getBlobStore().putBlob(container, blob);
+ }
+ return contexts;
+ }
+
+ public void testClearTweets() throws IOException, InterruptedException, ExecutionException {
+ String container = ClearTweetsControllerTest.class.getName() + "#container";
+ Map<String, BlobStoreContext> contexts = createBlobStores(container);
+
+ ClearTweetsController controller = new ClearTweetsController(contexts,
+ container);
+ controller.clearContainer("test1");
+ controller.clearContainer("test2");
+
+ for (BlobStoreContext context : contexts.values()) {
+ assertEquals(context.getBlobStore().countBlobs(container), 0, context.toString());
+ }
+ }
+}
diff --git a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
index 2db9a45..4be8fb5 100644
--- a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
+++ b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
@@ -42,6 +42,7 @@
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.demo.tweetstore.config.util.CredentialsCollector;
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
+import org.jclouds.demo.tweetstore.controller.ClearTweetsController;
import org.jclouds.demo.tweetstore.controller.EnqueueStoresController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
import org.jclouds.gae.config.GoogleAppEngineConfigurationModule;
@@ -148,6 +149,7 @@
serve("/store/*").with(StoreTweetsController.class);
serve("/tweets/*").with(AddTweetsController.class);
serve("/stores/*").with(EnqueueStoresController.class);
+ serve("/clear/*").with(ClearTweetsController.class);
}
});
}
diff --git a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
new file mode 100644
index 0000000..e08cfbc
--- /dev/null
+++ b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
@@ -0,0 +1,96 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Strings.nullToEmpty;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Grab tweets related to me and store them into blobstores
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class ClearTweetsController extends HttpServlet {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 7215420527854203714L;
+
+ private final Map<String, BlobStoreContext> contexts;
+ private final String container;
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ @VisibleForTesting
+ public ClearTweetsController(Map<String, BlobStoreContext> contexts,
+ @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) {
+ this.container = container;
+ this.contexts = contexts;
+ }
+
+ @VisibleForTesting
+ public void clearContainer(String contextName) {
+ BlobStoreContext context = checkNotNull(contexts.get(contextName),
+ "no context for %s in %s", contextName, contexts.keySet());
+ try {
+ context.getBlobStore().clearContainer(container);
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets in %s/%s", container, context);
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ if (nullToEmpty(request.getHeader("X-Originator")).equals("admin")) {
+ try {
+ String contextName = checkNotNull(request.getHeader("context"), "missing header context");
+ logger.info("clearing tweets in %s/%s", container, contextName);
+ clearContainer(contextName);
+ logger.debug("done clearing tweets");
+ response.setContentType(MediaType.TEXT_PLAIN);
+ response.getWriter().println("Done!");
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets");
+ throw new ServletException(e);
+ }
+ } else {
+ response.sendError(401);
+ }
+ }
+}
\ No newline at end of file
diff --git a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
new file mode 100644
index 0000000..81f0b9f
--- /dev/null
+++ b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
@@ -0,0 +1,72 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.TransientApiMetadata;
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@code AddTweetsController}
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class ClearTweetsControllerTest {
+
+ Map<String, BlobStoreContext> createBlobStores(String container) throws InterruptedException, ExecutionException {
+ TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build();
+ Map<String, BlobStoreContext> contexts = ImmutableMap.<String, BlobStoreContext>of(
+ "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class),
+ "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class));
+ for (BlobStoreContext blobstore : contexts.values()) {
+ blobstore.getBlobStore().createContainerInLocation(null, container);
+ Blob blob = blobstore.getAsyncBlobStore().blobBuilder("1").build();
+ blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank");
+ blob.setPayload("I love beans!");
+ blobstore.getBlobStore().putBlob(container, blob);
+ }
+ return contexts;
+ }
+
+ public void testClearTweets() throws IOException, InterruptedException, ExecutionException {
+ String container = ClearTweetsControllerTest.class.getName() + "#container";
+ Map<String, BlobStoreContext> contexts = createBlobStores(container);
+
+ ClearTweetsController controller = new ClearTweetsController(contexts,
+ container);
+ controller.clearContainer("test1");
+ controller.clearContainer("test2");
+
+ for (BlobStoreContext context : contexts.values()) {
+ assertEquals(context.getBlobStore().countBlobs(container), 0, context.toString());
+ }
+ }
+}
diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
index 24d0c94..c034343 100644
--- a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
+++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
@@ -45,6 +45,7 @@
import org.jclouds.demo.tweetstore.config.util.CredentialsCollector;
import org.jclouds.demo.tweetstore.config.util.PropertiesLoader;
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
+import org.jclouds.demo.tweetstore.controller.ClearTweetsController;
import org.jclouds.demo.tweetstore.controller.EnqueueStoresController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
@@ -138,6 +139,7 @@
serve("/store/*").with(StoreTweetsController.class);
serve("/tweets/*").with(AddTweetsController.class);
serve("/stores/*").with(EnqueueStoresController.class);
+ serve("/clear/*").with(ClearTweetsController.class);
}
});
}
diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
new file mode 100644
index 0000000..e08cfbc
--- /dev/null
+++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
@@ -0,0 +1,96 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Strings.nullToEmpty;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Grab tweets related to me and store them into blobstores
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class ClearTweetsController extends HttpServlet {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 7215420527854203714L;
+
+ private final Map<String, BlobStoreContext> contexts;
+ private final String container;
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ @VisibleForTesting
+ public ClearTweetsController(Map<String, BlobStoreContext> contexts,
+ @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) {
+ this.container = container;
+ this.contexts = contexts;
+ }
+
+ @VisibleForTesting
+ public void clearContainer(String contextName) {
+ BlobStoreContext context = checkNotNull(contexts.get(contextName),
+ "no context for %s in %s", contextName, contexts.keySet());
+ try {
+ context.getBlobStore().clearContainer(container);
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets in %s/%s", container, context);
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ if (nullToEmpty(request.getHeader("X-Originator")).equals("admin")) {
+ try {
+ String contextName = checkNotNull(request.getHeader("context"), "missing header context");
+ logger.info("clearing tweets in %s/%s", container, contextName);
+ clearContainer(contextName);
+ logger.debug("done clearing tweets");
+ response.setContentType(MediaType.TEXT_PLAIN);
+ response.getWriter().println("Done!");
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets");
+ throw new ServletException(e);
+ }
+ } else {
+ response.sendError(401);
+ }
+ }
+}
\ No newline at end of file
diff --git a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
new file mode 100644
index 0000000..81f0b9f
--- /dev/null
+++ b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
@@ -0,0 +1,72 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.TransientApiMetadata;
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@code AddTweetsController}
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class ClearTweetsControllerTest {
+
+ Map<String, BlobStoreContext> createBlobStores(String container) throws InterruptedException, ExecutionException {
+ TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build();
+ Map<String, BlobStoreContext> contexts = ImmutableMap.<String, BlobStoreContext>of(
+ "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class),
+ "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class));
+ for (BlobStoreContext blobstore : contexts.values()) {
+ blobstore.getBlobStore().createContainerInLocation(null, container);
+ Blob blob = blobstore.getAsyncBlobStore().blobBuilder("1").build();
+ blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank");
+ blob.setPayload("I love beans!");
+ blobstore.getBlobStore().putBlob(container, blob);
+ }
+ return contexts;
+ }
+
+ public void testClearTweets() throws IOException, InterruptedException, ExecutionException {
+ String container = ClearTweetsControllerTest.class.getName() + "#container";
+ Map<String, BlobStoreContext> contexts = createBlobStores(container);
+
+ ClearTweetsController controller = new ClearTweetsController(contexts,
+ container);
+ controller.clearContainer("test1");
+ controller.clearContainer("test2");
+
+ for (BlobStoreContext context : contexts.values()) {
+ assertEquals(context.getBlobStore().countBlobs(container), 0, context.toString());
+ }
+ }
+}
diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
index 24d0c94..c034343 100644
--- a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
+++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java
@@ -45,6 +45,7 @@
import org.jclouds.demo.tweetstore.config.util.CredentialsCollector;
import org.jclouds.demo.tweetstore.config.util.PropertiesLoader;
import org.jclouds.demo.tweetstore.controller.AddTweetsController;
+import org.jclouds.demo.tweetstore.controller.ClearTweetsController;
import org.jclouds.demo.tweetstore.controller.EnqueueStoresController;
import org.jclouds.demo.tweetstore.controller.StoreTweetsController;
@@ -138,6 +139,7 @@
serve("/store/*").with(StoreTweetsController.class);
serve("/tweets/*").with(AddTweetsController.class);
serve("/stores/*").with(EnqueueStoresController.class);
+ serve("/clear/*").with(ClearTweetsController.class);
}
});
}
diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
new file mode 100644
index 0000000..e08cfbc
--- /dev/null
+++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/ClearTweetsController.java
@@ -0,0 +1,96 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Strings.nullToEmpty;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.jclouds.logging.Logger;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/**
+ * Grab tweets related to me and store them into blobstores
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class ClearTweetsController extends HttpServlet {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 7215420527854203714L;
+
+ private final Map<String, BlobStoreContext> contexts;
+ private final String container;
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ @VisibleForTesting
+ public ClearTweetsController(Map<String, BlobStoreContext> contexts,
+ @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) {
+ this.container = container;
+ this.contexts = contexts;
+ }
+
+ @VisibleForTesting
+ public void clearContainer(String contextName) {
+ BlobStoreContext context = checkNotNull(contexts.get(contextName),
+ "no context for %s in %s", contextName, contexts.keySet());
+ try {
+ context.getBlobStore().clearContainer(container);
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets in %s/%s", container, context);
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ if (nullToEmpty(request.getHeader("X-Originator")).equals("admin")) {
+ try {
+ String contextName = checkNotNull(request.getHeader("context"), "missing header context");
+ logger.info("clearing tweets in %s/%s", container, contextName);
+ clearContainer(contextName);
+ logger.debug("done clearing tweets");
+ response.setContentType(MediaType.TEXT_PLAIN);
+ response.getWriter().println("Done!");
+ } catch (Exception e) {
+ logger.error(e, "Error clearing tweets");
+ throw new ServletException(e);
+ }
+ } else {
+ response.sendError(401);
+ }
+ }
+}
\ No newline at end of file
diff --git a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
new file mode 100644
index 0000000..81f0b9f
--- /dev/null
+++ b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/ClearTweetsControllerTest.java
@@ -0,0 +1,72 @@
+/**
+ * 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.demo.tweetstore.controller;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.TransientApiMetadata;
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.demo.tweetstore.reference.TweetStoreConstants;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@code AddTweetsController}
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class ClearTweetsControllerTest {
+
+ Map<String, BlobStoreContext> createBlobStores(String container) throws InterruptedException, ExecutionException {
+ TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build();
+ Map<String, BlobStoreContext> contexts = ImmutableMap.<String, BlobStoreContext>of(
+ "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class),
+ "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class));
+ for (BlobStoreContext blobstore : contexts.values()) {
+ blobstore.getBlobStore().createContainerInLocation(null, container);
+ Blob blob = blobstore.getAsyncBlobStore().blobBuilder("1").build();
+ blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank");
+ blob.setPayload("I love beans!");
+ blobstore.getBlobStore().putBlob(container, blob);
+ }
+ return contexts;
+ }
+
+ public void testClearTweets() throws IOException, InterruptedException, ExecutionException {
+ String container = ClearTweetsControllerTest.class.getName() + "#container";
+ Map<String, BlobStoreContext> contexts = createBlobStores(container);
+
+ ClearTweetsController controller = new ClearTweetsController(contexts,
+ container);
+ controller.clearContainer("test1");
+ controller.clearContainer("test2");
+
+ for (BlobStoreContext context : contexts.values()) {
+ assertEquals(context.getBlobStore().countBlobs(container), 0, context.toString());
+ }
+ }
+}
diff --git a/drivers/gae/src/test/java/org/jclouds/gae/ConvertToGaeRequestTest.java b/drivers/gae/src/test/java/org/jclouds/gae/ConvertToGaeRequestTest.java
index ea10bb2..83c6c7e 100644
--- a/drivers/gae/src/test/java/org/jclouds/gae/ConvertToGaeRequestTest.java
+++ b/drivers/gae/src/test/java/org/jclouds/gae/ConvertToGaeRequestTest.java
@@ -22,7 +22,6 @@
import java.io.File;
import java.io.IOException;
-import java.net.MalformedURLException;
import java.net.URI;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
@@ -32,7 +31,8 @@
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.crypto.Crypto;
-import org.jclouds.date.internal.SimpleDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory.DateServiceRfc1123Codec;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.encryption.internal.JCECrypto;
import org.jclouds.http.HttpRequest;
@@ -72,10 +72,10 @@
}
@BeforeTest
- void setupClient() throws MalformedURLException {
+ void setupClient() {
endPoint = URI.create("http://localhost:80/foo");
req = new ConvertToGaeRequest(new HttpUtils(0, 0, 0, 0), new DefaultContentMetadataCodec(
- new SimpleDateCodecFactory(new SimpleDateFormatDateService())));
+ new DateServiceDateCodecFactory(new DateServiceRfc1123Codec(new SimpleDateFormatDateService()))));
}
diff --git a/drivers/gae/src/test/java/org/jclouds/gae/ConvertToJcloudsResponseTest.java b/drivers/gae/src/test/java/org/jclouds/gae/ConvertToJcloudsResponseTest.java
index bce7f1d..51ec993 100644
--- a/drivers/gae/src/test/java/org/jclouds/gae/ConvertToJcloudsResponseTest.java
+++ b/drivers/gae/src/test/java/org/jclouds/gae/ConvertToJcloudsResponseTest.java
@@ -24,7 +24,6 @@
import static org.testng.Assert.assertEquals;
import java.io.IOException;
-import java.net.MalformedURLException;
import java.net.URI;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
@@ -34,7 +33,8 @@
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.crypto.Crypto;
-import org.jclouds.date.internal.SimpleDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory;
+import org.jclouds.date.internal.DateServiceDateCodecFactory.DateServiceRfc1123Codec;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.encryption.internal.JCECrypto;
import org.jclouds.http.HttpResponse;
@@ -68,10 +68,10 @@
}
@BeforeTest
- void setupClient() throws MalformedURLException {
+ void setupClient() {
endPoint = URI.create("http://localhost:80/foo");
- req = new ConvertToJcloudsResponse(new DefaultContentMetadataCodec(
- new SimpleDateCodecFactory(new SimpleDateFormatDateService())));
+ req = new ConvertToJcloudsResponse(new DefaultContentMetadataCodec(new DateServiceDateCodecFactory(
+ new DateServiceRfc1123Codec(new SimpleDateFormatDateService()))));
}
@Test
diff --git a/drivers/joda/src/main/java/org/jclouds/date/joda/JodaDateService.java b/drivers/joda/src/main/java/org/jclouds/date/joda/JodaDateService.java
index 4382b4b..e026125 100644
--- a/drivers/joda/src/main/java/org/jclouds/date/joda/JodaDateService.java
+++ b/drivers/joda/src/main/java/org/jclouds/date/joda/JodaDateService.java
@@ -111,6 +111,8 @@
}
public final Date iso8601DateParse(String toParse) {
+ if (toParse.length() < 10)
+ throw new IllegalArgumentException("incorrect date format " + toParse);
String tz = findTZ(toParse);
toParse = trimToMillis(toParse);
toParse = trimTZ(toParse);
@@ -121,6 +123,8 @@
}
public final Date iso8601SecondsDateParse(String toParse) {
+ if (toParse.length() < 10)
+ throw new IllegalArgumentException("incorrect date format " + toParse);
String tz = findTZ(toParse);
toParse = trimToMillis(toParse);
toParse = trimTZ(toParse);
diff --git a/drivers/joda/src/test/java/org/jclouds/date/joda/JodaDateServiceTest.java b/drivers/joda/src/test/java/org/jclouds/date/joda/JodaDateServiceTest.java
index 9efde59..cc3ed5e 100644
--- a/drivers/joda/src/test/java/org/jclouds/date/joda/JodaDateServiceTest.java
+++ b/drivers/joda/src/test/java/org/jclouds/date/joda/JodaDateServiceTest.java
@@ -21,7 +21,6 @@
import static org.testng.Assert.assertEquals;
import java.util.Date;
-import java.util.concurrent.ExecutionException;
import org.jclouds.date.DateService;
import org.jclouds.date.DateServiceTest;
@@ -56,14 +55,14 @@
@Override
@Test
- public void testRfc822DateFormat() throws ExecutionException, InterruptedException {
+ public void testRfc822DateFormat() {
String dsString = dateService.rfc822DateFormat(testData[0].date);
assertEquals(dsString, testData[0].rfc822DateString);
}
@Override
@Test(enabled = false)
- public void testRfc822DateParse() throws ExecutionException, InterruptedException {
+ public void testRfc822DateParse() {
Date dsDate = dateService.rfc822DateParse(testData[0].rfc822DateString);
assertEquals(dsDate, testData[0].date);
}
diff --git a/drivers/sshj/pom.xml b/drivers/sshj/pom.xml
index 2f56867..d8fbcb8 100644
--- a/drivers/sshj/pom.xml
+++ b/drivers/sshj/pom.xml
@@ -89,7 +89,7 @@
<dependency>
<groupId>net.schmizz</groupId>
<artifactId>sshj</artifactId>
- <version>0.7.0</version>
+ <version>0.8.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
diff --git a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/integration/AWSS3ContainerLiveTest.java b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/integration/AWSS3ContainerLiveTest.java
index 78788e3..f2cf6b9 100644
--- a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/integration/AWSS3ContainerLiveTest.java
+++ b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/blobstore/integration/AWSS3ContainerLiveTest.java
@@ -23,29 +23,18 @@
import java.io.IOException;
import java.net.MalformedURLException;
-import java.text.ParseException;
import java.util.Date;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jclouds.blobstore.BlobStore;
-import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.domain.BlobMetadata;
-import org.jclouds.date.DateCodec;
-import org.jclouds.date.internal.SimpleDateCodecFactory;
-import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.domain.Location;
-import org.jclouds.io.ContentMetadataCodec;
-import org.jclouds.io.ContentMetadataCodec.DefaultContentMetadataCodec;
import org.jclouds.s3.blobstore.integration.S3ContainerLiveTest;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.inject.AbstractModule;
-import com.google.inject.Module;
/**
* @author Adrian Cole
@@ -75,50 +64,6 @@
}
@Test(groups = { "live" })
- public void testCreateBlobWithMalformedExpiry() throws InterruptedException, MalformedURLException, IOException {
- // Create a blob that has a malformed Expires value; requires overriding the ContentMetadataCodec in Guice...
- final ContentMetadataCodec contentMetadataCodec = new DefaultContentMetadataCodec(new SimpleDateCodecFactory(new SimpleDateFormatDateService())) {
- @Override
- protected DateCodec getExpiresDateCodec() {
- return new DateCodec() {
- @Override public Date toDate(String date) throws ParseException {
- return new Date();
- }
- @Override public String toString(Date date) {
- return "wrong";
- }
- };
- }
- };
-
- Module customModule = new AbstractModule() {
- @Override
- protected void configure() {
- bind(ContentMetadataCodec.class).toInstance(contentMetadataCodec);
- }
- };
-
- Iterable<Module> modules = Iterables.concat(setupModules(), ImmutableList.of(customModule));
- BlobStoreContext naughtyBlobStoreContext = createView(setupProperties(), modules);
- BlobStore naughtyBlobStore = naughtyBlobStoreContext.getBlobStore();
-
- final String containerName = getScratchContainerName();
-
- try {
- final String blobName = "hello";
-
- naughtyBlobStore.createContainerInLocation(null, containerName, publicRead());
- naughtyBlobStore.putBlob(containerName, naughtyBlobStore.blobBuilder(blobName)
- .payload(TEST_STRING).expires(new Date(System.currentTimeMillis() + 60*1000)).build());
-
- assertConsistencyAwareBlobExpiryMetadata(containerName, blobName, new Date(0));
-
- } finally {
- recycleContainer(containerName);
- }
- }
-
- @Test(groups = { "live" })
public void testCreateBlobInLocation() throws InterruptedException, MalformedURLException, IOException {
String payload = "my data";
runCreateContainerInLocation(payload);
diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/UserAdd.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/UserAdd.java
index 14751d1..aa76afb 100644
--- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/UserAdd.java
+++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/statements/login/UserAdd.java
@@ -18,6 +18,7 @@
*/
package org.jclouds.scriptbuilder.statements.login;
+import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
@@ -36,6 +37,7 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -178,10 +180,10 @@
checkNotNull(family, "family");
if (family == OsFamily.WINDOWS)
throw new UnsupportedOperationException("windows not yet implemented");
- String homeDir = (home != null) ? home : (defaultHome + "{fs}" + login);
+ String homeDir = (home != null) ? home : (defaultHome + '/' + login);
ImmutableList.Builder<Statement> statements = ImmutableList.builder();
// useradd cannot create the default homedir
- statements.add(Statements.exec("{md} " + homeDir));
+ statements.add(Statements.exec("{md} " + homeDir.substring(0, homeDir.lastIndexOf('/'))));
ImmutableMap.Builder<String, String> userAddOptions = ImmutableMap.builder();
userAddOptions.put("-s", shell);
@@ -222,27 +224,22 @@
}
@Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((login == null) ? 0 : login.hashCode());
- return result;
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ UserAdd that = UserAdd.class.cast(o);
+ return equal(this.login, that.login);
}
@Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- UserAdd other = (UserAdd) obj;
- if (login == null) {
- if (other.login != null)
- return false;
- } else if (!login.equals(other.login))
- return false;
- return true;
+ public int hashCode() {
+ return Objects.hashCode(login);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper("").add("login", login).toString();
}
}
\ No newline at end of file
diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/login/UserAddTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/login/UserAddTest.java
index a41a60f..fd11d75 100644
--- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/login/UserAddTest.java
+++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/statements/login/UserAddTest.java
@@ -33,51 +33,51 @@
public void testUNIX() {
assertEquals(UserAdd.builder().login("me").build().render(OsFamily.UNIX),
- "mkdir -p /home/users/me\nuseradd -s /bin/bash -m -d /home/users/me me\nchown -R me /home/users/me\n");
+ "mkdir -p /home/users\nuseradd -s /bin/bash -m -d /home/users/me me\nchown -R me /home/users/me\n");
}
public void testWithBaseUNIX() {
assertEquals(UserAdd.builder().login("me").defaultHome("/export/home").build().render(OsFamily.UNIX),
- "mkdir -p /export/home/me\nuseradd -s /bin/bash -m -d /export/home/me me\nchown -R me /export/home/me\n");
+ "mkdir -p /export/home\nuseradd -s /bin/bash -m -d /export/home/me me\nchown -R me /export/home/me\n");
}
public void testWithGroupUNIX() {
assertEquals(UserAdd.builder().login("me").group("wheel").build().render(OsFamily.UNIX),
- "mkdir -p /home/users/me\ngroupadd -f wheel\nuseradd -s /bin/bash -g wheel -m -d /home/users/me me\nchown -R me /home/users/me\n");
+ "mkdir -p /home/users\ngroupadd -f wheel\nuseradd -s /bin/bash -g wheel -m -d /home/users/me me\nchown -R me /home/users/me\n");
}
public void testWithGroupsUNIX() {
assertEquals(UserAdd.builder().login("me").groups(ImmutableList.of("wheel", "candy")).build().render(
OsFamily.UNIX),
- "mkdir -p /home/users/me\ngroupadd -f wheel\ngroupadd -f candy\nuseradd -s /bin/bash -g wheel -G candy -m -d /home/users/me me\nchown -R me /home/users/me\n");
+ "mkdir -p /home/users\ngroupadd -f wheel\ngroupadd -f candy\nuseradd -s /bin/bash -g wheel -G candy -m -d /home/users/me me\nchown -R me /home/users/me\n");
}
public void testWithPasswordUNIX() {
String userAdd = UserAdd.builder().login("me").password("foo").group("wheel").build().render(OsFamily.UNIX);
- assert userAdd.startsWith("mkdir -p /home/users/me\ngroupadd -f wheel\nuseradd -s /bin/bash -g wheel -m -d /home/users/me -p '$6$") : userAdd;
+ assert userAdd.startsWith("mkdir -p /home/users\ngroupadd -f wheel\nuseradd -s /bin/bash -g wheel -m -d /home/users/me -p '$6$") : userAdd;
assert userAdd.endsWith("' me\nchown -R me /home/users/me\n") : userAdd;
}
public void testWithSshAuthorizedKeyUNIX() {
assertEquals(
UserAdd.builder().login("me").authorizeRSAPublicKey("rsapublickey").build().render(OsFamily.UNIX),
- "mkdir -p /home/users/me\nuseradd -s /bin/bash -m -d /home/users/me me\nmkdir -p /home/users/me/.ssh\ncat >> /home/users/me/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'\n\trsapublickey\nEND_OF_JCLOUDS_FILE\nchmod 600 /home/users/me/.ssh/authorized_keys\nchown -R me /home/users/me\n");
+ "mkdir -p /home/users\nuseradd -s /bin/bash -m -d /home/users/me me\nmkdir -p /home/users/me/.ssh\ncat >> /home/users/me/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'\n\trsapublickey\nEND_OF_JCLOUDS_FILE\nchmod 600 /home/users/me/.ssh/authorized_keys\nchown -R me /home/users/me\n");
}
public void testWithSshInstalledKeyUNIX() {
assertEquals(
UserAdd.builder().login("me").installRSAPrivateKey("rsaprivate").build().render(OsFamily.UNIX),
- "mkdir -p /home/users/me\nuseradd -s /bin/bash -m -d /home/users/me me\nmkdir -p /home/users/me/.ssh\nrm /home/users/me/.ssh/id_rsa\ncat >> /home/users/me/.ssh/id_rsa <<-'END_OF_JCLOUDS_FILE'\n\trsaprivate\nEND_OF_JCLOUDS_FILE\nchmod 600 /home/users/me/.ssh/id_rsa\nchown -R me /home/users/me\n");
+ "mkdir -p /home/users\nuseradd -s /bin/bash -m -d /home/users/me me\nmkdir -p /home/users/me/.ssh\nrm /home/users/me/.ssh/id_rsa\ncat >> /home/users/me/.ssh/id_rsa <<-'END_OF_JCLOUDS_FILE'\n\trsaprivate\nEND_OF_JCLOUDS_FILE\nchmod 600 /home/users/me/.ssh/id_rsa\nchown -R me /home/users/me\n");
}
public void testWithHomeUNIX() {
assertEquals(UserAdd.builder().login("me").home("/myhome/myme").build().render(
OsFamily.UNIX),
- "mkdir -p /myhome/myme\nuseradd -s /bin/bash -m -d /myhome/myme me\nchown -R me /myhome/myme\n");
+ "mkdir -p /myhome\nuseradd -s /bin/bash -m -d /myhome/myme me\nchown -R me /myhome/myme\n");
assertEquals(UserAdd.builder().login("me").home("/myhome/myme").defaultHome("/ignoreddefault").build().render(
OsFamily.UNIX),
- "mkdir -p /myhome/myme\nuseradd -s /bin/bash -m -d /myhome/myme me\nchown -R me /myhome/myme\n");
+ "mkdir -p /myhome\nuseradd -s /bin/bash -m -d /myhome/myme me\nchown -R me /myhome/myme\n");
}
@Test(expectedExceptions = UnsupportedOperationException.class)
diff --git a/scriptbuilder/src/test/resources/test_adminaccess_flipped.sh b/scriptbuilder/src/test/resources/test_adminaccess_flipped.sh
index d065eff..bfe8478 100644
--- a/scriptbuilder/src/test/resources/test_adminaccess_flipped.sh
+++ b/scriptbuilder/src/test/resources/test_adminaccess_flipped.sh
@@ -4,7 +4,7 @@
%wheel ALL = (ALL) NOPASSWD:ALL
END_OF_FILE
chmod 0440 /etc/sudoers
-mkdir -p /home/users/defaultAdminUsername
+mkdir -p /home/users
groupadd -f wheel
useradd -s /bin/bash -g wheel -d /home/users/defaultAdminUsername -p 'crypt(0)' defaultAdminUsername
mkdir -p /home/users/defaultAdminUsername/.ssh
diff --git a/scriptbuilder/src/test/resources/test_adminaccess_params.sh b/scriptbuilder/src/test/resources/test_adminaccess_params.sh
index 30fd511..3c33878 100644
--- a/scriptbuilder/src/test/resources/test_adminaccess_params.sh
+++ b/scriptbuilder/src/test/resources/test_adminaccess_params.sh
@@ -3,7 +3,7 @@
%wheel ALL = (ALL) NOPASSWD:ALL
END_OF_JCLOUDS_FILE
chmod 0440 /etc/sudoers
-mkdir -p /over/ridden/foo
+mkdir -p /over/ridden
groupadd -f wheel
useradd -s /bin/bash -g wheel -m -d /over/ridden/foo -p 'crypt(bar)' foo
mkdir -p /over/ridden/foo/.ssh
diff --git a/scriptbuilder/src/test/resources/test_adminaccess_plainuser.sh b/scriptbuilder/src/test/resources/test_adminaccess_plainuser.sh
index e63f6f2..68325f9 100644
--- a/scriptbuilder/src/test/resources/test_adminaccess_plainuser.sh
+++ b/scriptbuilder/src/test/resources/test_adminaccess_plainuser.sh
@@ -1,4 +1,4 @@
-mkdir -p /home/users/defaultAdminUsername
+mkdir -p /home/users
useradd -s /bin/bash -m -d /home/users/defaultAdminUsername -p 'crypt(0)' defaultAdminUsername
mkdir -p /home/users/defaultAdminUsername/.ssh
cat >> /home/users/defaultAdminUsername/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'
diff --git a/scriptbuilder/src/test/resources/test_adminaccess_standard.sh b/scriptbuilder/src/test/resources/test_adminaccess_standard.sh
index 6c48413..28d1849 100644
--- a/scriptbuilder/src/test/resources/test_adminaccess_standard.sh
+++ b/scriptbuilder/src/test/resources/test_adminaccess_standard.sh
@@ -3,7 +3,7 @@
%wheel ALL = (ALL) NOPASSWD:ALL
END_OF_JCLOUDS_FILE
chmod 0440 /etc/sudoers
-mkdir -p /home/users/defaultAdminUsername
+mkdir -p /home/users
groupadd -f wheel
useradd -s /bin/bash -g wheel -m -d /home/users/defaultAdminUsername -p 'crypt(0)' defaultAdminUsername
mkdir -p /home/users/defaultAdminUsername/.ssh