diff --git a/concurrent/pom.xml b/concurrent/pom.xml
new file mode 100755
index 0000000000..b2b6bb75e8
--- /dev/null
+++ b/concurrent/pom.xml
@@ -0,0 +1,112 @@
+
+
+
+
+ jclouds-project
+ org.jclouds
+ 1.0-SNAPSHOT
+ ../project/pom.xml
+
+ 4.0.0
+ jclouds-concurrent
+ jclouds concurrent
+ jar
+ Core components to access jclouds services
+
+
+ scm:svn:http://jclouds.googlecode.com/svn/trunk/concurrent
+ scm:svn:https://jclouds.googlecode.com/svn/trunk/concurrent
+ http://jclouds.googlecode.com/svn/trunk/concurrent
+
+
+
+
+
+
+
+
+ com.google.collections
+ google-collections
+ 1.0-rc2
+
+
+
+
+
+
+ compilejdk6executors
+
+ 1.5
+
+
+
+
+ maven-dependency-plugin
+
+
+ process-resources
+
+ copy
+
+
+
+
+ java.concurrent
+ jdk6-exec
+ 6.18
+ ${project.build.directory}/endorsed
+
+
+
+
+
+
+
+ maven-compiler-plugin
+
+ -Djava.endorsed.dirs=${project.build.directory}/endorsed
+ true
+
+
+
+ maven-surefire-plugin
+
+ -Djava.endorsed.dirs=${project.build.directory}/endorsed
+
+
+ listener
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/main/java/org/jclouds/concurrent/FutureExceptionParser.java b/concurrent/src/main/java/org/jclouds/concurrent/FutureExceptionParser.java
old mode 100644
new mode 100755
similarity index 100%
rename from core/src/main/java/org/jclouds/concurrent/FutureExceptionParser.java
rename to concurrent/src/main/java/org/jclouds/concurrent/FutureExceptionParser.java
diff --git a/core/src/main/java/org/jclouds/concurrent/FutureFunctionCallable.java b/concurrent/src/main/java/org/jclouds/concurrent/FutureFunctionCallable.java
old mode 100644
new mode 100755
similarity index 100%
rename from core/src/main/java/org/jclouds/concurrent/FutureFunctionCallable.java
rename to concurrent/src/main/java/org/jclouds/concurrent/FutureFunctionCallable.java
diff --git a/core/src/main/java/org/jclouds/concurrent/RunnableFutureTask.java b/concurrent/src/main/java/org/jclouds/concurrent/RunnableFutureTask.java
old mode 100644
new mode 100755
similarity index 100%
rename from core/src/main/java/org/jclouds/concurrent/RunnableFutureTask.java
rename to concurrent/src/main/java/org/jclouds/concurrent/RunnableFutureTask.java
diff --git a/core/src/main/java/org/jclouds/concurrent/SingleThreadCompatible.java b/concurrent/src/main/java/org/jclouds/concurrent/SingleThreadCompatible.java
old mode 100644
new mode 100755
similarity index 100%
rename from core/src/main/java/org/jclouds/concurrent/SingleThreadCompatible.java
rename to concurrent/src/main/java/org/jclouds/concurrent/SingleThreadCompatible.java
diff --git a/core/src/main/java/org/jclouds/concurrent/SingleThreaded.java b/concurrent/src/main/java/org/jclouds/concurrent/SingleThreaded.java
old mode 100644
new mode 100755
similarity index 100%
rename from core/src/main/java/org/jclouds/concurrent/SingleThreaded.java
rename to concurrent/src/main/java/org/jclouds/concurrent/SingleThreaded.java
diff --git a/core/src/main/java/org/jclouds/concurrent/WithinThreadExecutor.java b/concurrent/src/main/java/org/jclouds/concurrent/WithinThreadExecutor.java
old mode 100644
new mode 100755
similarity index 100%
rename from core/src/main/java/org/jclouds/concurrent/WithinThreadExecutor.java
rename to concurrent/src/main/java/org/jclouds/concurrent/WithinThreadExecutor.java
diff --git a/core/src/main/java/org/jclouds/concurrent/WithinThreadExecutorService.java b/concurrent/src/main/java/org/jclouds/concurrent/WithinThreadExecutorService.java
old mode 100644
new mode 100755
similarity index 93%
rename from core/src/main/java/org/jclouds/concurrent/WithinThreadExecutorService.java
rename to concurrent/src/main/java/org/jclouds/concurrent/WithinThreadExecutorService.java
index e4ffa77c9a..e151e0c2b3
--- a/core/src/main/java/org/jclouds/concurrent/WithinThreadExecutorService.java
+++ b/concurrent/src/main/java/org/jclouds/concurrent/WithinThreadExecutorService.java
@@ -59,7 +59,8 @@ public class WithinThreadExecutorService extends WithinThreadExecutor implements
/**
* {@inheritDoc}
*/
- public List> invokeAll(Collection> tasks) throws InterruptedException {
+ public List> invokeAll(Collection extends Callable> tasks)
+ throws InterruptedException {
checkState(!shutdown, "shutdown!");
List> results = new ArrayList>(tasks.size());
for (Callable task : tasks) {
@@ -74,8 +75,8 @@ public class WithinThreadExecutorService extends WithinThreadExecutor implements
/**
* {@inheritDoc}
*/
- public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit)
- throws InterruptedException {
+ public List> invokeAll(Collection extends Callable> tasks, long timeout,
+ TimeUnit unit) throws InterruptedException {
checkState(!shutdown, "shutdown!");
List> results = new ArrayList>(tasks.size());
long timeUp = System.nanoTime() + unit.toNanos(timeout);
@@ -94,7 +95,7 @@ public class WithinThreadExecutorService extends WithinThreadExecutor implements
/**
* {@inheritDoc}
*/
- public T invokeAny(Collection> tasks) throws InterruptedException,
+ public T invokeAny(Collection extends Callable> tasks) throws InterruptedException,
ExecutionException {
checkState(!shutdown, "shutdown!");
checkArgument(tasks.size() > 0, "no tasks");
@@ -115,7 +116,7 @@ public class WithinThreadExecutorService extends WithinThreadExecutor implements
/**
* {@inheritDoc}
*/
- public T invokeAny(Collection> tasks, long timeout, TimeUnit unit)
+ public T invokeAny(Collection extends Callable> tasks, long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
checkState(!shutdown, "shutdown!");
checkArgument(tasks.size() > 0, "no tasks");
diff --git a/concurrent/src/test/java/org/jclouds/concurrent/FutureExceptionParserTest.java b/concurrent/src/test/java/org/jclouds/concurrent/FutureExceptionParserTest.java
new file mode 100755
index 0000000000..7586059ab5
--- /dev/null
+++ b/concurrent/src/test/java/org/jclouds/concurrent/FutureExceptionParserTest.java
@@ -0,0 +1,94 @@
+/**
+ *
+ * Copyright (C) 2009 Global Cloud Specialists, Inc.
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+package org.jclouds.concurrent;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+
+/**
+ * Tests behavior of FutureExceptionParser
+ *
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "concurrent.FutureExceptionParserTest")
+public class FutureExceptionParserTest {
+ ExecutorService executorService = new WithinThreadExecutorService();
+
+ @Test
+ public void testGet() throws InterruptedException, ExecutionException {
+ Future> future = createFuture(new RuntimeException("foo"));
+ assertEquals(future.get(), "foo");
+ }
+
+ @Test(expectedExceptions = ExecutionException.class)
+ public void testGetUnmatched() throws InterruptedException, ExecutionException {
+ Future> future = createFuture(new Exception("foo"));
+ assertEquals(future.get(), "foo");
+ }
+
+ @Test
+ public void testGetLongTimeUnit() throws InterruptedException, ExecutionException,
+ TimeoutException {
+ Future> future = createFuture(new RuntimeException("foo"));
+ assertEquals(future.get(1, TimeUnit.SECONDS), "foo");
+ }
+
+ @Test(expectedExceptions = ExecutionException.class)
+ public void testGetLongTimeUnitUnmatched() throws InterruptedException, ExecutionException,
+ TimeoutException {
+ Future> future = createFuture(new Exception("foo"));
+ assertEquals(future.get(1, TimeUnit.SECONDS), "foo");
+ }
+
+ @SuppressWarnings("unchecked")
+ private Future> createFuture(final Exception exception) {
+ Future> future = executorService.submit(new Callable() {
+
+ public String call() throws Exception {
+ throw exception;
+ }
+
+ });
+
+ future = new FutureExceptionParser(future, new Function() {
+
+ public String apply(Exception from) {
+ return (from instanceof RuntimeException) ? from.getMessage() : null;
+ }
+
+ });
+ return future;
+ }
+
+}
diff --git a/project/pom.xml b/project/pom.xml
index f10376b3f4..5ef8fa2a69 100644
--- a/project/pom.xml
+++ b/project/pom.xml
@@ -144,6 +144,7 @@
1.5
true
true
+ org.jclouds.test.testng.UnitTestStatusListener
@@ -205,7 +206,7 @@
listener
- org.jclouds.test.testng.UnitTestStatusListener
+ ${jclouds.test.listener}