diff --git a/demos/googleappengine/pom.xml b/demos/googleappengine/pom.xml
index b78ce3452b..ce378227d5 100644
--- a/demos/googleappengine/pom.xml
+++ b/demos/googleappengine/pom.xml
@@ -40,8 +40,6 @@
1.6.5
localhost
8088
- FIXME_IDENTITY
- FIXME_CREDENTIAL
@@ -57,13 +55,13 @@
org.jclouds.provider
- hpcloud-objectstorage
+ aws-s3
${project.version}
runtime
org.jclouds.provider
- hpcloud-compute
+ hpcloud-objectstorage
${project.version}
runtime
@@ -369,8 +367,12 @@
- ${test.hpcloud.identity}
- ${test.hpcloud.credential}
+
+ ${test.aws-s3.identity}
+ ${test.aws-s3.credential}
+ ${test.hpcloud-objectstorage.identity}
+ ${test.hpcloud-objectstorage.credential}
${appengine.sdk.root}
${devappserver.address}
${devappserver.port}
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/GetAllResourcesController.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/GetAllResourcesController.java
new file mode 100644
index 0000000000..1be0d9ca74
--- /dev/null
+++ b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/GetAllResourcesController.java
@@ -0,0 +1,175 @@
+/**
+ * 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.samples.googleappengine;
+
+import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Iterables.size;
+import static com.google.common.collect.Iterables.transform;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jclouds.View;
+import org.jclouds.domain.ResourceMetadata;
+import org.jclouds.logging.Logger;
+import org.jclouds.samples.googleappengine.domain.ResourceResult;
+import org.jclouds.samples.googleappengine.functions.ResourceMetadataToResourceResult;
+import org.jclouds.samples.googleappengine.functions.ViewToAsyncResources;
+import org.jclouds.samples.googleappengine.functions.ViewToId;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+/**
+ * Shows an example of how to list all resources from all views!
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class GetAllResourcesController extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ private final ListeningExecutorService currentRequestExecutorService;
+ private final Iterable views;
+ private final ViewToAsyncResources viewToAsyncResources;
+ private final ResourceMetadataToResourceResult resourceMetadataToStatusResult;
+ private final Provider remainingMillis;
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ GetAllResourcesController(ListeningExecutorService currentRequestExecutorService, Iterable views,
+ ViewToAsyncResources viewToAsyncResources, ResourceMetadataToResourceResult resourceMetadataToStatusResult,
+ Provider remainingMillis) {
+ this.currentRequestExecutorService = currentRequestExecutorService;
+ this.views = views;
+ this.viewToAsyncResources = viewToAsyncResources;
+ this.resourceMetadataToStatusResult = resourceMetadataToStatusResult;
+ this.remainingMillis = remainingMillis;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ try {
+ addResourcesToRequest(request);
+ RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/jsp/resources.jsp");
+ dispatcher.forward(request, response);
+ } catch (Exception e) {
+ logger.error(e, "Error listing resources");
+ throw new ServletException(e);
+ }
+ }
+
+ private void addResourcesToRequest(HttpServletRequest request) {
+ Stopwatch watch = new Stopwatch().start();
+ logger.info("ready to list views: %s", transform(views, ViewToId.INSTANCE));
+ Iterable>>> asyncResources = transform(views,
+ viewToAsyncResources);
+ logger.info("launched %s tasks with %sms remaining", size(asyncResources), remainingMillis.get());
+
+ Set>> done = allResourcesWithinDeadline(asyncResources);
+ logger.info("%s tasks completed in %sms with %sms remaining", size(done), watch.stop().elapsedMillis(),
+ remainingMillis.get());
+
+ Iterable> flattened = concat(done);
+
+ Set results = FluentIterable.from(flattened).transform(resourceMetadataToStatusResult)
+ .toImmutableSet();
+
+ request.setAttribute("resources", results);
+ }
+
+ private Set>> allResourcesWithinDeadline(
+ Iterable>>> asyncResources) {
+ Builder>> resourcesWeCanList = addToBuilderOnComplete(asyncResources);
+
+ // only serve resources that made it by the timeout
+ blockUntilAllDoneOrCancelOnTimeout(asyncResources);
+
+ return resourcesWeCanList.build();
+ }
+
+ private Builder>> addToBuilderOnComplete(
+ Iterable>>> asyncResources) {
+
+ final Builder>> resourcesWeCanList = ImmutableSet
+ .>> builder();
+
+ for (final ListenableFuture extends Iterable extends ResourceMetadata>>> asyncResource : asyncResources) {
+ Futures.addCallback(asyncResource, new FutureCallback>>() {
+ public void onSuccess(Iterable extends ResourceMetadata>> result) {
+ if (result != null)
+ resourcesWeCanList.add(result);
+ }
+
+ public void onFailure(Throwable t) {
+ if (!(t instanceof CancellationException))
+ logger.info("exception getting resource %s: %s", asyncResource, t.getMessage());
+ }
+ }, currentRequestExecutorService);
+
+ }
+ return resourcesWeCanList;
+ }
+
+ private void blockUntilAllDoneOrCancelOnTimeout(
+ Iterable>>> asyncResources) {
+ List>>> remaining = Lists
+ .newArrayList(asyncResources);
+
+ while (remaining.size() > 0) {
+ ListenableFuture> resource = remaining.remove(0);
+ if (remainingMillis.get() <= 0) {
+ if (!resource.isDone())
+ resource.cancel(true);
+ continue;
+ }
+
+ try {
+ resource.get(remainingMillis.get(), TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ logger.info("exception getting resource %s: %s", resource, e.getMessage());
+ if (!resource.isDone())
+ resource.cancel(true);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/GetAllStatusController.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/GetAllStatusController.java
deleted file mode 100644
index 2f6e76089b..0000000000
--- a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/GetAllStatusController.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.samples.googleappengine;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-import javax.annotation.Resource;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.jclouds.blobstore.BlobStoreContext;
-import org.jclouds.compute.ComputeServiceContext;
-import org.jclouds.logging.Logger;
-import org.jclouds.samples.googleappengine.functions.BlobStoreContextToStatusResult;
-import org.jclouds.samples.googleappengine.functions.ComputeServiceContextToStatusResult;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-/**
- * Shows an example of how to use {@link BlobStoreContext} and {@link ComputeServiceContext}
- * injected with Guice.
- *
- * @author Adrian Cole
- */
-@Singleton
-public class GetAllStatusController extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- private final Iterable blobsStoreContexts;
- private final Iterable computeServiceContexts;
- private final BlobStoreContextToStatusResult blobStoreContextToContainerResult;
- private final ComputeServiceContextToStatusResult computeServiceContextToContainerResult;
-
- @Resource
- protected Logger logger = Logger.NULL;
-
- @Inject
- GetAllStatusController(Iterable blobsStoreContexts,
- Iterable computeServiceContexts,
- BlobStoreContextToStatusResult blobStoreContextToContainerResult,
- ComputeServiceContextToStatusResult computeServiceContextToContainerResult) {
- this.blobsStoreContexts = blobsStoreContexts;
- this.computeServiceContexts = computeServiceContexts;
- this.blobStoreContextToContainerResult = blobStoreContextToContainerResult;
- this.computeServiceContextToContainerResult = computeServiceContextToContainerResult;
- }
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- try {
- addStatusResultsToRequest(request);
- RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/jsp/status.jsp");
- dispatcher.forward(request, response);
- } catch (Exception e) {
- logger.error(e, "Error listing status");
- throw new ServletException(e);
- }
- }
-
- private void addStatusResultsToRequest(HttpServletRequest request) throws InterruptedException, ExecutionException,
- TimeoutException {
- request.setAttribute(
- "status",
- ImmutableSet.copyOf(Iterables.concat(
- Iterables.transform(blobsStoreContexts, blobStoreContextToContainerResult),
- Iterables.transform(computeServiceContexts, computeServiceContextToContainerResult))));
- }
-
-}
\ No newline at end of file
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java
index 5b195a08a1..cdc671b8ac 100644
--- a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java
+++ b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/config/GuiceServletConfig.java
@@ -18,6 +18,11 @@
*/
package org.jclouds.samples.googleappengine.config;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.get;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.io.Closeables.closeQuietly;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
@@ -26,59 +31,90 @@ import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import javax.inject.Singleton;
import javax.servlet.ServletContextEvent;
import org.jclouds.ContextBuilder;
-import org.jclouds.blobstore.BlobStoreContext;
-import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.View;
import org.jclouds.gae.config.AsyncGoogleAppEngineConfigurationModule;
-import org.jclouds.samples.googleappengine.GetAllStatusController;
+import org.jclouds.logging.jdk.config.JDKLoggingModule;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.Providers;
+import org.jclouds.samples.googleappengine.GetAllResourcesController;
+import com.google.appengine.api.ThreadManager;
+import com.google.apphosting.api.ApiProxy;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
-import com.google.common.io.Closeables;
+import com.google.common.reflect.TypeToken;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
+import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.servlet.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;
/**
- * Setup Logging and create {@link Injector} for use in testing Amazon EC2 and S3.
+ * Setup Logging and create {@link Injector} for use in testing Views
*
* @author Adrian Cole
*/
public class GuiceServletConfig extends GuiceServletContextListener {
- private Iterable blobsStoreContexts;
- private Iterable computeServiceContexts;
+ private Iterable views;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
- Properties overrides = loadJCloudsProperties(servletContextEvent);
+ final Properties overrides = loadJCloudsProperties(servletContextEvent);
+ // until there's a global skip image parse option
+ overrides.setProperty("jclouds.ec2.ami-query", "");
+ overrides.setProperty("jclouds.ec2.cc-ami-query", "");
+
+ // ensure requests don't take longer than GAE timeout
overrides.setProperty(TIMEOUT_NODE_TERMINATED, "25000");
overrides.setProperty(TIMEOUT_NODE_RUNNING, "25000");
overrides.setProperty(TIMEOUT_SCRIPT_COMPLETE, "25000");
overrides.setProperty(TIMEOUT_PORT_OPEN, "25000");
- // note that this module hooks into the async urlfetchservice
- ImmutableSet modules = ImmutableSet. of(new AsyncGoogleAppEngineConfigurationModule());
+ // correct the classloader so that extensions can be found
+ Thread.currentThread().setContextClassLoader(Providers.class.getClassLoader());
- blobsStoreContexts = ImmutableSet.of(
- ContextBuilder.newBuilder("hpcloud-objectstorage")
- .modules(modules)
- .overrides(overrides)
- .buildView(BlobStoreContext.class));
- computeServiceContexts = ImmutableSet.of(
- ContextBuilder.newBuilder("hpcloud-compute")
- .modules(modules)
- .overrides(overrides)
- .buildView(ComputeServiceContext.class));
+ Iterable identityInProperties = providersWeHaveIdentitiesFor(overrides);
+
+ final ImmutableSet modules = ImmutableSet. of(new AsyncGoogleAppEngineConfigurationModule());
+ views = transform(identityInProperties, new Function() {
+
+ @Override
+ public View apply(ProviderMetadata input) {
+ TypeToken extends View> defaultView = get(input.getApiMetadata().getViews(), 0);
+ return ContextBuilder.newBuilder(input).modules(modules).overrides(overrides).buildView(defaultView);
+ }
+
+ });
super.contextInitialized(servletContextEvent);
}
+ protected Iterable providersWeHaveIdentitiesFor(final Properties overrides) {
+ // there's a chance serviceloader is being lazy, and we don't want
+ // ConcurrentModificationException, so copy into a set.
+ return ImmutableSet.copyOf(filter(Providers.all(), new Predicate() {
+
+ @Override
+ public boolean apply(ProviderMetadata input) {
+ return overrides.containsKey(input.getId() + ".identity");
+ }
+
+ }));
+ }
+
private Properties loadJCloudsProperties(ServletContextEvent servletContextEvent) {
InputStream input = servletContextEvent.getServletContext().getResourceAsStream("/WEB-INF/jclouds.properties");
Properties props = new Properties();
@@ -87,35 +123,44 @@ public class GuiceServletConfig extends GuiceServletContextListener {
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
- Closeables.closeQuietly(input);
+ closeQuietly(input);
}
return props;
}
@Override
protected Injector getInjector() {
- return Guice.createInjector(new ServletModule() {
+ return Guice.createInjector(new JDKLoggingModule(), new ServletModule() {
@Override
protected void configureServlets() {
- bind(new TypeLiteral>() {
- }).toInstance(GuiceServletConfig.this.blobsStoreContexts);
- bind(new TypeLiteral>() {
- }).toInstance(GuiceServletConfig.this.computeServiceContexts);
- serve("*.check").with(GetAllStatusController.class);
+ bind(new TypeLiteral>() {
+ }).toInstance(GuiceServletConfig.this.views);
+ serve("*.check").with(GetAllResourcesController.class);
requestInjection(this);
}
- }
- );
+ @SuppressWarnings("unused")
+ @Provides
+ long remainingMillis() {
+ // leave 100ms for any post processing
+ return ApiProxy.getCurrentEnvironment().getRemainingMillis() - 100;
+ }
+
+ @SuppressWarnings("unused")
+ @Provides
+ @Singleton
+ ListeningExecutorService currentRequestExecutorService() {
+ ThreadFactory factory = checkNotNull(ThreadManager.currentRequestThreadFactory(),
+ "ThreadManager.currentRequestThreadFactory()");
+ return MoreExecutors.listeningDecorator(Executors.newCachedThreadPool(factory));
+ }
+ });
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
- for (BlobStoreContext context : blobsStoreContexts) {
- context.close();
- }
- for (ComputeServiceContext context : computeServiceContexts) {
- context.close();
+ for (View view : views) {
+ view.unwrap().close();
}
super.contextDestroyed(servletContextEvent);
}
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/domain/ResourceResult.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/domain/ResourceResult.java
new file mode 100644
index 0000000000..fe09faa27d
--- /dev/null
+++ b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/domain/ResourceResult.java
@@ -0,0 +1,128 @@
+/**
+ * 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.samples.googleappengine.domain;
+
+import static com.google.common.base.Objects.equal;
+
+import com.google.common.base.Objects;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+public class ResourceResult {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ protected String provider;
+ protected String location;
+ protected String type;
+ protected String id;
+ protected String name;
+
+ public Builder provider(String provider) {
+ this.provider = provider;
+ return this;
+ }
+
+ public Builder location(String location) {
+ this.location = location;
+ return this;
+ }
+
+ public Builder type(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public Builder id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public ResourceResult build() {
+ return new ResourceResult(provider, location, type, id, name);
+ }
+
+ }
+
+ private final String provider;
+ private final String location;
+ private final String type;
+ private final String id;
+ private final String name;
+
+ protected ResourceResult(String provider, String location, String type, String id, String name) {
+ this.provider = provider;
+ this.type = type;
+ this.location = location;
+ this.id = id;
+ this.name = name;
+ }
+
+ public String getProvider() {
+ return provider;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ ResourceResult that = ResourceResult.class.cast(o);
+ return equal(this.provider, that.provider) && equal(this.location, that.location) && equal(this.type, that.type)
+ && equal(this.id, that.id) && equal(this.name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(provider, location, type, id, name);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper("").add("provider", provider).add("location", location).add("type", type)
+ .add("id", id).add("name", name).toString();
+ }
+}
\ No newline at end of file
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/domain/StatusResult.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/domain/StatusResult.java
deleted file mode 100644
index 26138971ce..0000000000
--- a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/domain/StatusResult.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.samples.googleappengine.domain;
-
-import java.io.Serializable;
-
-/**
- *
- * @author Adrian Cole
- */
-public class StatusResult implements Comparable, Serializable {
- /** The serialVersionUID */
- private static final long serialVersionUID = -3257496189689220018L;
- private final String service;
- private final String host;
- private final String name;
- private final String status;
-
- public StatusResult(String service, String host, String name, String status) {
- this.service = service;
- this.host = host;
- this.name = name;
- this.status = status;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((host == null) ? 0 : host.hashCode());
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((service == null) ? 0 : service.hashCode());
- result = prime * result + ((status == null) ? 0 : status.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- StatusResult other = (StatusResult) obj;
- if (host == null) {
- if (other.host != null)
- return false;
- } else if (!host.equals(other.host))
- return false;
- if (name == null) {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- if (service == null) {
- if (other.service != null)
- return false;
- } else if (!service.equals(other.service))
- return false;
- if (status == null) {
- if (other.status != null)
- return false;
- } else if (!status.equals(other.status))
- return false;
- return true;
- }
-
- public int compareTo(StatusResult o) {
- return (this == o) ? 0 : getService().compareTo(o.getService());
- }
-
- public String getHost() {
- return host;
- }
-
- public String getName() {
- return name;
- }
-
- public String getStatus() {
- return status;
- }
-
- public String getService() {
- return service;
- }
-
-}
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/BlobStoreContextToStatusResult.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/BlobStoreContextToAsyncResources.java
similarity index 59%
rename from demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/BlobStoreContextToStatusResult.java
rename to demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/BlobStoreContextToAsyncResources.java
index a98f28ff91..518ea8b1ec 100644
--- a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/BlobStoreContextToStatusResult.java
+++ b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/BlobStoreContextToAsyncResources.java
@@ -18,41 +18,28 @@
*/
package org.jclouds.samples.googleappengine.functions;
-import java.net.URI;
-
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.domain.ResourceMetadata;
import org.jclouds.logging.Logger;
-import org.jclouds.samples.googleappengine.domain.StatusResult;
import com.google.common.base.Function;
+import com.google.common.util.concurrent.ListenableFuture;
/**
*
* @author Adrian Cole
*/
@Singleton
-public class BlobStoreContextToStatusResult implements Function {
-
+public class BlobStoreContextToAsyncResources implements
+ Function>>> {
@Resource
protected Logger logger = Logger.NULL;
- public StatusResult apply(BlobStoreContext in) {
- String host = URI.create(in.unwrap().getProviderMetadata().getEndpoint()).getHost();
- String status;
- String name = "not found";
- try {
- long start = System.currentTimeMillis();
-
- name = String.format("%d containers", in.getBlobStore().list().size());
-
- status = ((System.currentTimeMillis() - start) + "ms");
- } catch (Exception e) {
- logger.error(e, "Error listing context %s", in);
- status = (e.getMessage());
- }
- return new StatusResult(in.unwrap().getId(), host, name, status);
+ public ListenableFuture extends Iterable extends ResourceMetadata>>> apply(BlobStoreContext in) {
+ logger.info("listing containers on %s: ", in.unwrap().getId());
+ return in.getAsyncBlobStore().list();
}
}
\ No newline at end of file
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ComputeServiceContextToAsyncResources.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ComputeServiceContextToAsyncResources.java
new file mode 100644
index 0000000000..fed3897fb1
--- /dev/null
+++ b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ComputeServiceContextToAsyncResources.java
@@ -0,0 +1,69 @@
+/**
+ * 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.samples.googleappengine.functions;
+
+import java.util.concurrent.Callable;
+
+import javax.annotation.Resource;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.domain.ResourceMetadata;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.inject.Inject;
+
+/**
+ * ComputeService doesn't currently have an Async counterpart
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class ComputeServiceContextToAsyncResources implements
+ Function>>> {
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ private final ListeningExecutorService currentRequestExecutorService;
+
+ @Inject
+ public ComputeServiceContextToAsyncResources(ListeningExecutorService currentRequestExecutorService) {
+ this.currentRequestExecutorService = currentRequestExecutorService;
+ }
+
+ public ListenableFuture extends Iterable extends ResourceMetadata>>> apply(final ComputeServiceContext in) {
+ return currentRequestExecutorService.submit(new Callable>>() {
+
+ @Override
+ public Iterable extends ResourceMetadata>> call() throws Exception {
+ logger.info("listing nodes on %s: ", in.unwrap().getId());
+ return in.getComputeService().listNodes();
+ }
+
+ @Override
+ public String toString() {
+ return in.toString();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ComputeServiceContextToStatusResult.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ResourceMetadataToResourceResult.java
similarity index 56%
rename from demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ComputeServiceContextToStatusResult.java
rename to demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ResourceMetadataToResourceResult.java
index 08aaeb2b55..1ef82b85dc 100644
--- a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ComputeServiceContextToStatusResult.java
+++ b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ResourceMetadataToResourceResult.java
@@ -18,14 +18,14 @@
*/
package org.jclouds.samples.googleappengine.functions;
-import java.net.URI;
-
import javax.annotation.Resource;
import javax.inject.Singleton;
-import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.ResourceMetadata;
import org.jclouds.logging.Logger;
-import org.jclouds.samples.googleappengine.domain.StatusResult;
+import org.jclouds.samples.googleappengine.domain.ResourceResult;
+import org.jclouds.samples.googleappengine.domain.ResourceResult.Builder;
import com.google.common.base.Function;
@@ -34,25 +34,21 @@ import com.google.common.base.Function;
* @author Adrian Cole
*/
@Singleton
-public class ComputeServiceContextToStatusResult implements Function {
+public class ResourceMetadataToResourceResult implements Function, ResourceResult> {
@Resource
protected Logger logger = Logger.NULL;
- public StatusResult apply(ComputeServiceContext in) {
- String host = URI.create(in.unwrap().getProviderMetadata().getEndpoint()).getHost();
- String status;
- String name = "not found";
- try {
- long start = System.currentTimeMillis();
-
- name = String.format("%d nodes", in.getComputeService().listNodes().size());
-
- status = ((System.currentTimeMillis() - start) + "ms");
- } catch (Exception e) {
- logger.error(e, "Error listing context %s", in);
- status = (e.getMessage());
- }
- return new StatusResult(in.unwrap().getId(), host, name, status);
+ public ResourceResult apply(ResourceMetadata> in) {
+ Builder builder = ResourceResult.builder();
+ Location provider = in.getLocation();
+ while (provider.getParent() != null)
+ provider = provider.getParent();
+ builder.provider(provider.getId());
+ builder.location(in.getLocation().getId());
+ builder.type(in.getType().toString().toLowerCase());
+ builder.id(in.getProviderId());
+ builder.name(in.getName());
+ return builder.build();
}
}
\ No newline at end of file
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ViewToAsyncResources.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ViewToAsyncResources.java
new file mode 100644
index 0000000000..bd1030c213
--- /dev/null
+++ b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ViewToAsyncResources.java
@@ -0,0 +1,59 @@
+/**
+ * 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.samples.googleappengine.functions;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.View;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.domain.ResourceMetadata;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ *
+ * @author Adrian Cole
+ */
+@Singleton
+public class ViewToAsyncResources implements Function>>> {
+ private final BlobStoreContextToAsyncResources blobStoreContextToAsyncResources;
+ private final ComputeServiceContextToAsyncResources computeServiceContextToAsyncResources;
+
+ @Inject
+ public ViewToAsyncResources(BlobStoreContextToAsyncResources blobStoreContextToAsyncResources,
+ ComputeServiceContextToAsyncResources computeServiceContextToAsyncResources) {
+ this.blobStoreContextToAsyncResources = blobStoreContextToAsyncResources;
+ this.computeServiceContextToAsyncResources = computeServiceContextToAsyncResources;
+ }
+
+
+ @Override
+ public ListenableFuture extends Iterable extends ResourceMetadata>>> apply(View input) {
+ if (input instanceof BlobStoreContext) {
+ return blobStoreContextToAsyncResources.apply(BlobStoreContext.class.cast(input));
+ } else if (input instanceof ComputeServiceContext) {
+ return computeServiceContextToAsyncResources.apply(ComputeServiceContext.class.cast(input));
+ }
+ throw new UnsupportedOperationException("unknown view type: " + input);
+ }
+
+}
\ No newline at end of file
diff --git a/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ViewToId.java b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ViewToId.java
new file mode 100644
index 0000000000..ea9f2da92d
--- /dev/null
+++ b/demos/googleappengine/src/main/java/org/jclouds/samples/googleappengine/functions/ViewToId.java
@@ -0,0 +1,31 @@
+/**
+ * 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.samples.googleappengine.functions;
+
+import org.jclouds.View;
+
+import com.google.common.base.Function;
+
+public enum ViewToId implements Function {
+ INSTANCE;
+ @Override
+ public String apply(View input) {
+ return input.unwrap().getId();
+ }
+}
\ No newline at end of file
diff --git a/demos/googleappengine/src/main/webapp/WEB-INF/jsp/resources.jsp b/demos/googleappengine/src/main/webapp/WEB-INF/jsp/resources.jsp
new file mode 100644
index 0000000000..1a8a21bfd2
--- /dev/null
+++ b/demos/googleappengine/src/main/webapp/WEB-INF/jsp/resources.jsp
@@ -0,0 +1,104 @@
+<%--
+
+ 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.
+
+--%>
+<%@ page buffer="100kb"%>
+<%@ taglib uri="http://displaytag.sf.net" prefix="display"%>
+
+
+jclouds: multi-cloud library
+
+
+
+Resource List
+
+
+
diff --git a/demos/googleappengine/src/main/webapp/WEB-INF/jsp/status.jsp b/demos/googleappengine/src/main/webapp/WEB-INF/jsp/status.jsp
deleted file mode 100644
index 8cb3960523..0000000000
--- a/demos/googleappengine/src/main/webapp/WEB-INF/jsp/status.jsp
+++ /dev/null
@@ -1,36 +0,0 @@
-<%--
-
- Licensed to jclouds, Inc. (jclouds) under one or more
- contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. jclouds licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-
---%>
-<%@ page buffer="20kb"%>
-<%@ taglib uri="http://displaytag.sf.net" prefix="display"%>
-
-
-jclouds: multi-cloud library
-
-
-Status List
-
-
-
-
-
-
-
-
diff --git a/demos/googleappengine/src/main/webapp/index.jsp b/demos/googleappengine/src/main/webapp/index.jsp
index b3db1e7d8f..38308a0f33 100644
--- a/demos/googleappengine/src/main/webapp/index.jsp
+++ b/demos/googleappengine/src/main/webapp/index.jsp
@@ -25,6 +25,6 @@
Welcome!
Click
-here to get status of cloud services.
+here to list all your cloud resources!