diff --git a/archetypes/.svnignore b/archetypes/.svnignore
new file mode 100644
index 0000000000..2ed45a5c3d
--- /dev/null
+++ b/archetypes/.svnignore
@@ -0,0 +1,7 @@
+target
+.settings
+.classpath
+.project
+jclouds-archetypes.iml
+jclouds-archetypes.ipr
+jclouds-archetypes.iws
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/pom.xml b/archetypes/jclouds-json-client-archetype/pom.xml
new file mode 100644
index 0000000000..339ccc48ba
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/pom.xml
@@ -0,0 +1,80 @@
+
+
+
+
+ jclouds-archetypes
+ org.jclouds
+ 1.0-SNAPSHOT
+
+ 4.0.0
+ jclouds-json-client-archetype
+ jclouds JSON client archetype
+ Maven archetype for a client of a JSON-speaking service
+ maven-archetype
+
+
+
+
+ maven-archetype-plugin
+ 2.0-alpha-4
+ true
+
+
+ maven-resources-plugin
+
+ UTF-8
+
+
+
+
+
+ org.apache.maven.archetype
+ archetype-packaging
+ 2.0-alpha-4
+
+
+ org.apache.maven.wagon
+ wagon-webdav
+ 1.0-beta-2
+
+
+
+
+
+ false
+ jclouds-googlecode-deploy
+ svn:https://jclouds.googlecode.com/svn/repo
+
+
+ website
+ website
+ file://${basedir}/target/dist/site/jclouds-testing/
+
+
+
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/archetypes/jclouds-json-client-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000000..076c0258fd
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,37 @@
+
+
+
+
+ org.jclouds
+
+
+ Adrian Cole
+
+
+
+
+
+
+
+
+
+ src/main/java
+
+ **/*.java
+
+
+
+ src/test/java
+
+ **/*.java
+
+
+
+ src/test/resources
+
+ **/*.xml
+ **/*.json
+
+
+
+
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/pom.xml b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/pom.xml
new file mode 100644
index 0000000000..d50176be32
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/pom.xml
@@ -0,0 +1,79 @@
+#set( $lcaseClientName = ${clientName.toLowerCase()} )
+#set( $symbol_dollar = '$' )
+
+
+
+
+ org.jclouds
+ jclouds-project
+ 1.0-SNAPSHOT
+ ../project/pom.xml
+
+ 4.0.0
+ ${groupId}
+ ${artifactId}
+ jclouds ${clientName} core
+ jar
+ jclouds components to access ${clientName}
+
+
+ scm:svn:http://jclouds.googlecode.com/svn/trunk/${lcaseClientName}
+ scm:svn:https://jclouds.googlecode.com/svn/trunk/${lcaseClientName}
+ http://jclouds.googlecode.com/svn/trunk/${lcaseClientName}
+
+
+ ${clientUser}
+ ${clientPassword}
+
+
+
+ ${symbol_dollar}{project.groupId}
+ jclouds-core
+ ${symbol_dollar}{project.version}
+
+
+ ${symbol_dollar}{project.groupId}
+ jclouds-core
+ ${symbol_dollar}{project.version}
+ test-jar
+ test
+
+
+ log4j
+ log4j
+ 1.2.14
+ test
+
+
+ ${symbol_dollar}{project.groupId}
+ jclouds-log4j
+ ${symbol_dollar}{project.version}
+ test
+
+
+
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__.java
new file mode 100644
index 0000000000..0b7ca36b15
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__.java
@@ -0,0 +1,47 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package};
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Related to a ${clientName} resource.
+ *
+ * @author ${author}
+ *
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+@Qualifier
+public @interface ${clientName} {
+
+}
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__Client.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__Client.java
new file mode 100644
index 0000000000..fe4224fbfb
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__Client.java
@@ -0,0 +1,58 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package};
+
+import java.util.SortedSet;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import ${package}.domain.Status;
+import ${package}.functions.ParseStatusesFromJsonResponse;
+
+/**
+ * Provides access to ${clientName} via their REST API.
+ *
+ *
+ * @see
+ * @author ${author}
+ */
+@Endpoint(${clientName}.class)
+@RequestFilters(BasicAuthentication.class)
+public interface ${clientName}Client {
+
+ @GET
+ @ResponseParser(ParseStatusesFromJsonResponse.class)
+ @Path("/statuses/mentions.json")
+ Future> getMyMentions();
+
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__ContextBuilder.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__ContextBuilder.java
new file mode 100644
index 0000000000..fdd4b9815b
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__ContextBuilder.java
@@ -0,0 +1,65 @@
+#set( $ucaseClientName = ${clientName.toUpperCase()} )
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package};
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Properties;
+
+import org.jclouds.rest.RestContextBuilder;
+import ${package}.config.${clientName}ContextModule;
+import ${package}.config.${clientName}RestClientModule;
+import ${package}.reference.${clientName}Constants;
+
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+
+/**
+ *
+ * @author ${author}
+ */
+public class ${clientName}ContextBuilder extends RestContextBuilder<${clientName}Client> {
+
+ public ${clientName}ContextBuilder(Properties props) {
+ super(new TypeLiteral<${clientName}Client>() {
+ }, props);
+ checkNotNull(properties.getProperty(${clientName}Constants.PROPERTY_${ucaseClientName}_USER));
+ checkNotNull(properties.getProperty(${clientName}Constants.PROPERTY_${ucaseClientName}_PASSWORD));
+ }
+
+ protected void addClientModule(List modules) {
+ modules.add(new ${clientName}RestClientModule());
+ }
+
+ @Override
+ protected void addContextModule(List modules) {
+ modules.add(new ${clientName}ContextModule());
+ }
+
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__ContextFactory.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__ContextFactory.java
new file mode 100644
index 0000000000..332b0937b8
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__ContextFactory.java
@@ -0,0 +1,64 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package};
+
+import java.util.Properties;
+
+import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
+import org.jclouds.logging.jdk.config.JDKLoggingModule;
+import org.jclouds.rest.RestContext;
+
+import com.google.inject.Module;
+
+/**
+ * Creates {@link RestContext} for {@link ${clientName}Client} instances based on the most commonly
+ * requested arguments.
+ *
+ * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
+ *
+ *
+ * If no Module
s are specified, the default {@link JDKLoggingModule logging} and
+ * {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
+ *
+ * @author ${author}
+ * @see RestContext
+ * @see ${clientName}Client
+ */
+public class ${clientName}ContextFactory {
+
+ public static RestContext<${clientName}Client> createContext(String user, String password,
+ Module... modules) {
+ return new ${clientName}ContextBuilder(new ${clientName}PropertiesBuilder(user, password).build())
+ .withModules(modules).buildContext();
+ }
+
+ public static RestContext<${clientName}Client> createContext(Properties properties, Module... modules) {
+ return new ${clientName}ContextBuilder(new ${clientName}PropertiesBuilder(properties).build())
+ .withModules(modules).buildContext();
+ }
+
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__PropertiesBuilder.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__PropertiesBuilder.java
new file mode 100644
index 0000000000..299973769d
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/__clientName__PropertiesBuilder.java
@@ -0,0 +1,73 @@
+#set( $ucaseClientName = ${clientName.toUpperCase()} )
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package};
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static ${package}.reference.${clientName}Constants.PROPERTY_${ucaseClientName}_ENDPOINT;
+import static ${package}.reference.${clientName}Constants.PROPERTY_${ucaseClientName}_PASSWORD;
+import static ${package}.reference.${clientName}Constants.PROPERTY_${ucaseClientName}_USER;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.http.HttpPropertiesBuilder;
+
+/**
+ * Builds properties used in ${clientName} Clients
+ *
+ * @author ${author}
+ */
+public class ${clientName}PropertiesBuilder extends HttpPropertiesBuilder {
+ @Override
+ protected Properties defaultProperties() {
+ Properties properties = super.defaultProperties();
+ properties.setProperty(PROPERTY_${ucaseClientName}_ENDPOINT, "${endpoint}");
+ return properties;
+ }
+
+ public ${clientName}PropertiesBuilder(Properties properties) {
+ super(properties);
+ }
+
+ public ${clientName}PropertiesBuilder(String id, String secret) {
+ super();
+ withCredentials(id, secret);
+ }
+
+ public ${clientName}PropertiesBuilder withCredentials(String id, String secret) {
+ properties.setProperty(PROPERTY_${ucaseClientName}_USER, checkNotNull(id, "user"));
+ properties.setProperty(PROPERTY_${ucaseClientName}_PASSWORD, checkNotNull(secret, "password"));
+ return this;
+ }
+
+ public ${clientName}PropertiesBuilder withEndpoint(URI endpoint) {
+ properties.setProperty(PROPERTY_${ucaseClientName}_ENDPOINT, checkNotNull(endpoint, "endpoint")
+ .toString());
+ return this;
+ }
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/config/__clientName__ContextModule.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/config/__clientName__ContextModule.java
new file mode 100644
index 0000000000..8e4df2440d
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/config/__clientName__ContextModule.java
@@ -0,0 +1,62 @@
+#set( $ucaseClientName = ${clientName.toUpperCase()} )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package}.config;
+
+import java.net.URI;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.http.functions.config.ParserModule.CDateTimeAdapter;
+import org.jclouds.http.functions.config.ParserModule.DateTimeAdapter;
+import org.jclouds.lifecycle.Closer;
+import org.jclouds.rest.RestContext;
+import org.jclouds.rest.internal.RestContextImpl;
+import ${package}.${clientName};
+import ${package}.${clientName}Client;
+import ${package}.reference.${clientName}Constants;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+
+/**
+ * Configures the ${clientName} connection, including logging and http transport.
+ *
+ * @author ${author}
+ */
+public class ${clientName}ContextModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(DateTimeAdapter.class).to(CDateTimeAdapter.class);
+ }
+
+ @Provides
+ @Singleton
+ RestContext<${clientName}Client> provideContext(Closer closer, ${clientName}Client defaultApi,
+ @${clientName} URI endPoint, @Named(${clientName}Constants.PROPERTY_${ucaseClientName}_USER) String account) {
+ return new RestContextImpl<${clientName}Client>(closer, defaultApi, endPoint, account);
+ }
+
+}
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/config/__clientName__RestClientModule.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/config/__clientName__RestClientModule.java
new file mode 100644
index 0000000000..d8025d78cb
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/config/__clientName__RestClientModule.java
@@ -0,0 +1,89 @@
+#set( $ucaseClientName = ${clientName.toUpperCase()} )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package}.config;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.http.RequiresHttp;
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.RestClientFactory;
+import ${package}.${clientName};
+import ${package}.${clientName}Client;
+import ${package}.reference.${clientName}Constants;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+
+/**
+ * Configures the ${clientName} connection.
+ *
+ * @author ${author}
+ */
+@RequiresHttp
+@ConfiguresRestClient
+public class ${clientName}RestClientModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ bindErrorHandlers();
+ bindRetryHandlers();
+ }
+
+ @Provides
+ @Singleton
+ public BasicAuthentication provideBasicAuthentication(
+ @Named(${clientName}Constants.PROPERTY_${ucaseClientName}_USER) String user,
+ @Named(${clientName}Constants.PROPERTY_${ucaseClientName}_PASSWORD) String password)
+ throws UnsupportedEncodingException {
+ return new BasicAuthentication(user, password);
+ }
+
+ @Provides
+ @Singleton
+ protected ${clientName}Client provideClient(RestClientFactory factory) {
+ return factory.create(${clientName}Client.class);
+ }
+
+ @Provides
+ @Singleton
+ @${clientName}
+ protected URI provideURI(@Named(${clientName}Constants.PROPERTY_${ucaseClientName}_ENDPOINT) String endpoint) {
+ return URI.create(endpoint);
+ }
+
+ protected void bindErrorHandlers() {
+ // TODO
+ }
+
+ protected void bindRetryHandlers() {
+ // TODO
+ }
+
+}
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/domain/Status.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/domain/Status.java
new file mode 100644
index 0000000000..e4a7cf8c7f
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/domain/Status.java
@@ -0,0 +1,205 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package}.domain;
+
+import org.joda.time.DateTime;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ *
+ * @author ${author}
+ *
+ */
+public class Status implements Comparable {
+ @SerializedName("created_at")
+ private DateTime createdAt;
+ private boolean favorited;
+ private String geo;
+ private long id;
+ @SerializedName("in_reply_to_screen_name")
+ private String inReplyToScreenName;
+ @SerializedName("in_reply_to_status_id")
+ private Integer inReplyToStatusId;
+ @SerializedName("in_reply_to_user_id")
+ private Integer inReplyToUserId;
+ private String source;
+ private String text;
+ private boolean truncated;
+ private User user;
+
+ public Status() {
+ }
+
+ public Status(DateTime createdAt, boolean favorited, String geo, long id,
+ String inReplyToScreenName, Integer inReplyToStatusId, Integer inReplyToUserId,
+ String source, String text, boolean truncated, User user) {
+ this.createdAt = createdAt;
+ this.favorited = favorited;
+ this.geo = geo;
+ this.id = id;
+ this.inReplyToScreenName = inReplyToScreenName;
+ this.inReplyToStatusId = inReplyToStatusId;
+ this.inReplyToUserId = inReplyToUserId;
+ this.source = source;
+ this.text = text;
+ this.truncated = truncated;
+ this.user = user;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((createdAt == null) ? 0 : createdAt.hashCode());
+ result = prime * result + (int) (id ^ (id >>> 32));
+ result = prime * result + ((text == null) ? 0 : text.hashCode());
+ result = prime * result + ((user == null) ? 0 : user.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;
+ Status other = (Status) obj;
+ if (createdAt == null) {
+ if (other.createdAt != null)
+ return false;
+ } else if (!createdAt.equals(other.createdAt))
+ return false;
+ if (id != other.id)
+ return false;
+ if (text == null) {
+ if (other.text != null)
+ return false;
+ } else if (!text.equals(other.text))
+ return false;
+ if (user == null) {
+ if (other.user != null)
+ return false;
+ } else if (!user.equals(other.user))
+ return false;
+ return true;
+ }
+
+ public DateTime getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(DateTime createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public String getSource() {
+ return source;
+ }
+
+ public void setSource(String source) {
+ this.source = source;
+ }
+
+ public boolean isTruncated() {
+ return truncated;
+ }
+
+ public void setTruncated(boolean truncated) {
+ this.truncated = truncated;
+ }
+
+ public Integer getInReplyToStatusId() {
+ return inReplyToStatusId;
+ }
+
+ public void setInReplyToStatusId(Integer inReplyToStatusId) {
+ this.inReplyToStatusId = inReplyToStatusId;
+ }
+
+ public Integer getInReplyToUserId() {
+ return inReplyToUserId;
+ }
+
+ public void setInReplyToUserId(Integer inReplyToUserId) {
+ this.inReplyToUserId = inReplyToUserId;
+ }
+
+ public boolean isFavorited() {
+ return favorited;
+ }
+
+ public void setFavorited(boolean favorited) {
+ this.favorited = favorited;
+ }
+
+ public String getInReplyToScreenName() {
+ return inReplyToScreenName;
+ }
+
+ public void setInReplyToScreenName(String inReplyToScreenName) {
+ this.inReplyToScreenName = inReplyToScreenName;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ public int compareTo(Status o) {
+ return (int) ((this == o) ? 0 : id + "".compareTo(o.id + ""));
+ }
+
+ public void setGeo(String geo) {
+ this.geo = geo;
+ }
+
+ public String getGeo() {
+ return geo;
+ }
+}
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/domain/User.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/domain/User.java
new file mode 100644
index 0000000000..965e3209b5
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/domain/User.java
@@ -0,0 +1,372 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package}.domain;
+
+import java.net.URI;
+
+import org.joda.time.DateTime;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ *
+ * @author ${author}
+ */
+public class User implements Comparable {
+ @SerializedName("created_at")
+ private DateTime createdAt;
+ private String description;
+ @SerializedName("favourites_count")
+ private int favouritesCount;
+ @SerializedName("followers_count")
+ private int followersCount;
+ private boolean following;
+ @SerializedName("friends_count")
+ private int friendsCount;
+ @SerializedName("geo_enabled")
+ private boolean geoEnabled;
+ private long id;
+ private String location;
+ private String name;
+ private boolean notifications;
+ @SerializedName("profile_background_color")
+ private String profileBackgroundColor;
+ @SerializedName("profile_background_image_url")
+ private URI profileBackgroundImageUrl;
+ @SerializedName("profile_background_tile")
+ private boolean profileBackgroundTile;
+ @SerializedName("profile_image_url")
+ private URI profileImageUrl;
+ @SerializedName("profile_link_color")
+ private String profileLinkColor;
+ @SerializedName("profile_sidebar_border_color")
+ private String profileSidebarBorderColor;
+ @SerializedName("profile_sidebar_fill_color")
+ private String profileSidebarFillColor;
+ @SerializedName("profile_text_color")
+ private String profileTextColor;
+ @SerializedName("protected")
+ private boolean isProtected;
+ @SerializedName("screen_name")
+ private String screenName;
+ @SerializedName("statuses_count")
+ private int statusesCount;
+ @SerializedName("time_zone")
+ private String timeZone;
+ private URI url;
+ @SerializedName("utc_offset")
+ private int utcOffset;
+ private boolean verified;
+
+ public User() {
+
+ }
+
+ public User(DateTime createdAt, String description, int favouritesCount, int followersCount,
+ boolean following, int friendsCount, boolean geoEnabled, long id, String location,
+ String name, boolean notifications, String profileBackgroundColor,
+ URI profileBackgroundImageUrl, boolean profileBackgroundTile, URI profileImageUrl,
+ String profileLinkColor, String profileSidebarBorderColor,
+ String profileSidebarFillColor, String profileTextColor, boolean isProtected,
+ String screenName, int statusesCount, String timeZone, URI url, int utcOffset,
+ boolean verified) {
+ this.createdAt = createdAt;
+ this.description = description;
+ this.favouritesCount = favouritesCount;
+ this.followersCount = followersCount;
+ this.following = following;
+ this.friendsCount = friendsCount;
+ this.setGeoEnabled(geoEnabled);
+ this.id = id;
+ this.location = location;
+ this.name = name;
+ this.notifications = notifications;
+ this.profileBackgroundColor = profileBackgroundColor;
+ this.profileBackgroundImageUrl = profileBackgroundImageUrl;
+ this.profileBackgroundTile = profileBackgroundTile;
+ this.profileImageUrl = profileImageUrl;
+ this.profileLinkColor = profileLinkColor;
+ this.profileSidebarBorderColor = profileSidebarBorderColor;
+ this.profileSidebarFillColor = profileSidebarFillColor;
+ this.profileTextColor = profileTextColor;
+ this.isProtected = isProtected;
+ this.screenName = screenName;
+ this.statusesCount = statusesCount;
+ this.timeZone = timeZone;
+ this.url = url;
+ this.utcOffset = utcOffset;
+ this.verified = verified;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (id ^ (id >>> 32));
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((screenName == null) ? 0 : screenName.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;
+ User other = (User) obj;
+ if (id != other.id)
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (screenName == null) {
+ if (other.screenName != null)
+ return false;
+ } else if (!screenName.equals(other.screenName))
+ return false;
+ return true;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getScreenName() {
+ return screenName;
+ }
+
+ public void setScreenName(String screenName) {
+ this.screenName = screenName;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public URI getProfileImageUrl() {
+ return profileImageUrl;
+ }
+
+ public void setProfileImageUrl(URI profileImageUrl) {
+ this.profileImageUrl = profileImageUrl;
+ }
+
+ public URI getUrl() {
+ return url;
+ }
+
+ public void setUrl(URI url) {
+ this.url = url;
+ }
+
+ public boolean isProtected() {
+ return isProtected;
+ }
+
+ public void setProtected(boolean isProtected) {
+ this.isProtected = isProtected;
+ }
+
+ public int getFollowersCount() {
+ return followersCount;
+ }
+
+ public void setFollowersCount(int followersCount) {
+ this.followersCount = followersCount;
+ }
+
+ public String getProfileBackgroundColor() {
+ return profileBackgroundColor;
+ }
+
+ public void setProfileBackgroundColor(String profileBackgroundColor) {
+ this.profileBackgroundColor = profileBackgroundColor;
+ }
+
+ public String getProfileTextColor() {
+ return profileTextColor;
+ }
+
+ public void setProfileTextColor(String profileTextColor) {
+ this.profileTextColor = profileTextColor;
+ }
+
+ public String getProfileLinkColor() {
+ return profileLinkColor;
+ }
+
+ public void setProfileLinkColor(String profileLinkColor) {
+ this.profileLinkColor = profileLinkColor;
+ }
+
+ public String getProfileSidebarFillColor() {
+ return profileSidebarFillColor;
+ }
+
+ public void setProfileSidebarFillColor(String profileSidebarFillColor) {
+ this.profileSidebarFillColor = profileSidebarFillColor;
+ }
+
+ public String getProfileSidebarBorderColor() {
+ return profileSidebarBorderColor;
+ }
+
+ public void setProfileSidebarBorderColor(String profileSidebarBorderColor) {
+ this.profileSidebarBorderColor = profileSidebarBorderColor;
+ }
+
+ public int getFriendsCount() {
+ return friendsCount;
+ }
+
+ public void setFriendsCount(int friendsCount) {
+ this.friendsCount = friendsCount;
+ }
+
+ public DateTime getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(DateTime createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public int getFavouritesCount() {
+ return favouritesCount;
+ }
+
+ public void setFavouritesCount(int favouritesCount) {
+ this.favouritesCount = favouritesCount;
+ }
+
+ public int getUtcOffset() {
+ return utcOffset;
+ }
+
+ public void setUtcOffset(int utcOffset) {
+ this.utcOffset = utcOffset;
+ }
+
+ public String getTimeZone() {
+ return timeZone;
+ }
+
+ public void setTimeZone(String timeZone) {
+ this.timeZone = timeZone;
+ }
+
+ public URI getProfileBackgroundImageUrl() {
+ return profileBackgroundImageUrl;
+ }
+
+ public void setProfileBackgroundImageUrl(URI profileBackgroundImageUrl) {
+ this.profileBackgroundImageUrl = profileBackgroundImageUrl;
+ }
+
+ public boolean isProfileBackgroundTile() {
+ return profileBackgroundTile;
+ }
+
+ public void setProfileBackgroundTile(boolean profileBackgroundTile) {
+ this.profileBackgroundTile = profileBackgroundTile;
+ }
+
+ public int getStatusesCount() {
+ return statusesCount;
+ }
+
+ public void setStatusesCount(int statusesCount) {
+ this.statusesCount = statusesCount;
+ }
+
+ public boolean isNotifications() {
+ return notifications;
+ }
+
+ public void setNotifications(boolean notifications) {
+ this.notifications = notifications;
+ }
+
+ public boolean isFollowing() {
+ return following;
+ }
+
+ public void setFollowing(boolean following) {
+ this.following = following;
+ }
+
+ public boolean isVerified() {
+ return verified;
+ }
+
+ public void setVerified(boolean verified) {
+ this.verified = verified;
+ }
+
+ public int compareTo(User o) {
+ if (screenName == null)
+ return -1;
+ return (this == o) ? 0 : screenName.compareTo(o.screenName);
+ }
+
+ public void setGeoEnabled(boolean geoEnabled) {
+ this.geoEnabled = geoEnabled;
+ }
+
+ public boolean isGeoEnabled() {
+ return geoEnabled;
+ }
+}
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/functions/ParseStatusesFromJsonResponse.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/functions/ParseStatusesFromJsonResponse.java
new file mode 100644
index 0000000000..fe6b218cbd
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/functions/ParseStatusesFromJsonResponse.java
@@ -0,0 +1,66 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package}.functions;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Type;
+import java.util.SortedSet;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.http.functions.ParseJson;
+import ${package}.domain.Status;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * This parses {@link Status} from a json string.
+ *
+ * @author ${author}
+ */
+@Singleton
+public class ParseStatusesFromJsonResponse extends ParseJson> {
+
+ @Inject
+ public ParseStatusesFromJsonResponse(Gson gson) {
+ super(gson);
+ }
+
+ public SortedSet apply(InputStream stream) {
+ Type setType = new TypeToken>() {
+ }.getType();
+ try {
+ return gson.fromJson(new InputStreamReader(stream, "UTF-8"), setType);
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("jclouds requires UTF-8 encoding", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/reference/__clientName__Constants.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/reference/__clientName__Constants.java
new file mode 100644
index 0000000000..67eadeec07
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/main/java/reference/__clientName__Constants.java
@@ -0,0 +1,37 @@
+#set( $lcaseClientName = ${clientName.toLowerCase()} )
+#set( $ucaseClientName = ${clientName.toUpperCase()} )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package}.reference;
+
+/**
+ * Configuration properties and constants used in ${clientName} connections.
+ *
+ * @author ${author}
+ */
+public interface ${clientName}Constants {
+ public static final String PROPERTY_${ucaseClientName}_ENDPOINT = "jclouds.${lcaseClientName}.endpoint";
+ public static final String PROPERTY_${ucaseClientName}_USER = "jclouds.${lcaseClientName}.user";
+ public static final String PROPERTY_${ucaseClientName}_PASSWORD = "jclouds.${lcaseClientName}.password";
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ClientLiveTest.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ClientLiveTest.java
new file mode 100644
index 0000000000..8f7b238b1e
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ClientLiveTest.java
@@ -0,0 +1,67 @@
+#set( $lcaseClientName = ${clientName.toLowerCase()} )
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package};
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.SortedSet;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.jclouds.logging.log4j.config.Log4JLoggingModule;
+import ${package}.domain.Status;
+import org.testng.annotations.BeforeGroups;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code ${clientName}Client}
+ *
+ * @author ${author}
+ */
+@Test(groups = "live", testName = "${lcaseClientName}.${clientName}ClientLiveTest")
+public class ${clientName}ClientLiveTest {
+
+ private ${clientName}Client connection;
+
+ @BeforeGroups(groups = { "live" })
+ public void setupClient() throws InterruptedException, ExecutionException, TimeoutException {
+ String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
+ String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
+
+ connection = ${clientName}ContextFactory.createContext(user, password, new Log4JLoggingModule())
+ .getApi();
+ }
+
+ @Test
+ public void testGetMyMentions() throws Exception {
+ SortedSet response = connection.getMyMentions().get(1, TimeUnit.SECONDS);
+ assert (response.size() > 0);
+ }
+
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ClientTest.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ClientTest.java
new file mode 100644
index 0000000000..e3a24535d3
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ClientTest.java
@@ -0,0 +1,112 @@
+#set( $lcaseClientName = ${clientName.toLowerCase()} )
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package};
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Method;
+import java.net.URI;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.logging.Logger;
+import org.jclouds.logging.Logger.LoggerFactory;
+import org.jclouds.rest.RestClientTest;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.jclouds.rest.internal.RestAnnotationProcessor;
+import ${package}.functions.ParseStatusesFromJsonResponse;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Tests behavior of {@code ${clientName}Client}
+ *
+ * @author ${author}
+ */
+@Test(groups = "unit", testName = "${lcaseClientName}.${clientName}ClientTest")
+public class ${clientName}ClientTest extends RestClientTest<${clientName}Client> {
+
+ public void testGetMyMentions() throws SecurityException, NoSuchMethodException, IOException {
+ Method method = ${clientName}Client.class.getMethod(""<-- (remove '"') TODO: insert test method name");
+ GeneratedHttpRequest<${clientName}Client> httpMethod = processor.createRequest(method);
+
+ assertRequestLineEquals(httpMethod, ""<-- (remove '"') TODO: insert expected request");
+ assertHeadersEqual(httpMethod, "");
+ assertEntityEquals(httpMethod, null);
+
+ assertResponseParserClassEquals(method, httpMethod, ParseStatusesFromJsonResponse.class);
+ assertSaxResponseParserClassEquals(method, null);
+ assertExceptionParserClassEquals(method, null);
+
+ checkFilters(httpMethod);
+ }
+
+ @Override
+ protected void checkFilters(GeneratedHttpRequest<${clientName}Client> httpMethod) {
+ assertEquals(httpMethod.getFilters().size(), 1);
+ assertEquals(httpMethod.getFilters().get(0).getClass(), BasicAuthentication.class);
+ }
+
+ @Override
+ protected TypeLiteral> createTypeLiteral() {
+ return new TypeLiteral>() {
+ };
+ }
+
+ @Override
+ protected Module createModule() {
+ return new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(URI.class).annotatedWith(${clientName}.class).toInstance(
+ URI.create("${endpoint}"));
+ bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() {
+ public Logger getLogger(String category) {
+ return Logger.NULL;
+ }
+ });
+ }
+
+ @SuppressWarnings("unused")
+ @Provides
+ @Singleton
+ public BasicAuthentication provideBasicAuthentication()
+ throws UnsupportedEncodingException {
+ return new BasicAuthentication("foo", "bar");
+ }
+
+ };
+ }
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ContextBuilderTest.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ContextBuilderTest.java
new file mode 100644
index 0000000000..3f93eb1f17
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/__clientName__ContextBuilderTest.java
@@ -0,0 +1,103 @@
+#set( $lcaseClientName = ${clientName.toLowerCase()} )
+#set( $ucaseClientName = ${clientName.toUpperCase()} )
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package};
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.rest.RestContext;
+import org.jclouds.rest.internal.RestContextImpl;
+import ${package}.config.${clientName}RestClientModule;
+import ${package}.reference.${clientName}Constants;
+import org.testng.annotations.Test;
+
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Tests behavior of modules configured in ${clientName}ContextBuilder
+ *
+ * @author ${author}
+ */
+@Test(groups = "unit", testName = "${lcaseClientName}.${clientName}ContextBuilderTest")
+public class ${clientName}ContextBuilderTest {
+
+ public void testNewBuilder() {
+ ${clientName}ContextBuilder builder = newBuilder();
+ assertEquals(builder.getProperties().getProperty(${clientName}Constants.PROPERTY_${ucaseClientName}_ENDPOINT),
+ "${endpoint}");
+ assertEquals(builder.getProperties().getProperty(${clientName}Constants.PROPERTY_${ucaseClientName}_USER),
+ "user");
+ assertEquals(builder.getProperties().getProperty(${clientName}Constants.PROPERTY_${ucaseClientName}_PASSWORD),
+ "password");
+ }
+
+ public void testBuildContext() {
+ RestContext<${clientName}Client> context = newBuilder().buildContext();
+ assertEquals(context.getClass(), RestContextImpl.class);
+ assertEquals(context.getAccount(), "user");
+ assertEquals(context.getEndPoint(), URI.create("${endpoint}"));
+ }
+
+ public void testBuildInjector() {
+ Injector i = newBuilder().buildInjector();
+ assert i.getInstance(Key.get(new TypeLiteral>() {
+ })) != null; // TODO: test all things taken from context
+ assert i.getInstance(BasicAuthentication.class) != null;
+ }
+
+ protected void testAddContextModule() {
+ List modules = new ArrayList();
+ ${clientName}ContextBuilder builder = newBuilder();
+ builder.addContextModule(modules);
+ assertEquals(modules.size(), 1);
+ assertEquals(modules.get(0).getClass(), ${clientName}RestClientModule.class);
+ }
+
+ private ${clientName}ContextBuilder newBuilder() {
+ ${clientName}ContextBuilder builder = new ${clientName}ContextBuilder(new ${clientName}PropertiesBuilder(
+ "user", "password").build());
+ return builder;
+ }
+
+ protected void addClientModule() {
+ List modules = new ArrayList();
+ ${clientName}ContextBuilder builder = newBuilder();
+ builder.addClientModule(modules);
+ assertEquals(modules.size(), 1);
+ assertEquals(modules.get(0).getClass(), ${clientName}RestClientModule.class);
+ }
+
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/config/__clientName__ContextModuleTest.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/config/__clientName__ContextModuleTest.java
new file mode 100644
index 0000000000..fa0a35794a
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/config/__clientName__ContextModuleTest.java
@@ -0,0 +1,112 @@
+#set( $lcaseClientName = ${clientName.toLowerCase()} )
+#set( $ucaseClientName = ${clientName.toUpperCase()} )
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package}.config;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.concurrent.WithinThreadExecutorService;
+import org.jclouds.concurrent.config.ExecutorServiceModule;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
+import org.jclouds.http.functions.config.ParserModule;
+import org.jclouds.http.functions.config.ParserModule.CDateTimeAdapter;
+import org.jclouds.http.functions.config.ParserModule.DateTimeAdapter;
+import org.jclouds.http.handlers.CloseContentAndSetExceptionErrorHandler;
+import org.jclouds.http.handlers.DelegatingErrorHandler;
+import org.jclouds.http.handlers.DelegatingRetryHandler;
+import org.jclouds.http.handlers.RedirectionRetryHandler;
+import org.jclouds.logging.Logger;
+import org.jclouds.logging.Logger.LoggerFactory;
+import ${package}.reference.${clientName}Constants;
+import org.jclouds.util.Jsr330;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * @author ${author}
+ */
+@Test(groups = "unit", testName = "${lcaseClientName}.${clientName}ContextModule")
+public class ${clientName}ContextModuleTest {
+
+ Injector createInjector() {
+ return Guice.createInjector(new ${clientName}RestClientModule(), new ${clientName}ContextModule() {
+ @Override
+ protected void configure() {
+ bindConstant().annotatedWith(Jsr330.named(${clientName}Constants.PROPERTY_${ucaseClientName}_USER)).to(
+ "user");
+ bindConstant().annotatedWith(Jsr330.named(${clientName}Constants.PROPERTY_${ucaseClientName}_PASSWORD))
+ .to("password");
+ bindConstant().annotatedWith(Jsr330.named(${clientName}Constants.PROPERTY_${ucaseClientName}_ENDPOINT))
+ .to("http://localhost");
+ bind(Logger.LoggerFactory.class).toInstance(new LoggerFactory() {
+ public Logger getLogger(String category) {
+ return Logger.NULL;
+ }
+ });
+ super.configure();
+ }
+ }, new ParserModule(), new JavaUrlHttpCommandExecutorServiceModule(),
+ new ExecutorServiceModule(new WithinThreadExecutorService()));
+ }
+
+ @Test
+ void testServerErrorHandler() {
+ DelegatingErrorHandler handler = createInjector().getInstance(DelegatingErrorHandler.class);
+ assertEquals(handler.getServerErrorHandler().getClass(),
+ CloseContentAndSetExceptionErrorHandler.class);
+ }
+
+ @Test
+ void testDateTimeAdapter() {
+ assertEquals(this.createInjector().getInstance(DateTimeAdapter.class).getClass(),
+ CDateTimeAdapter.class);
+ }
+
+ @Test
+ void testClientErrorHandler() {
+ DelegatingErrorHandler handler = createInjector().getInstance(DelegatingErrorHandler.class);
+ assertEquals(handler.getClientErrorHandler().getClass(),
+ CloseContentAndSetExceptionErrorHandler.class);
+ }
+
+ @Test
+ void testClientRetryHandler() {
+ DelegatingRetryHandler handler = createInjector().getInstance(DelegatingRetryHandler.class);
+ assertEquals(handler.getClientErrorRetryHandler(), HttpRetryHandler.NEVER_RETRY);
+ }
+
+ @Test
+ void testRedirectionRetryHandler() {
+ DelegatingRetryHandler handler = createInjector().getInstance(DelegatingRetryHandler.class);
+ assertEquals(handler.getRedirectionRetryHandler().getClass(), RedirectionRetryHandler.class);
+ }
+
+}
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/functions/ParseStatusesFromJsonResponseTest.java b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/functions/ParseStatusesFromJsonResponseTest.java
new file mode 100644
index 0000000000..15f1c2516b
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/java/functions/ParseStatusesFromJsonResponseTest.java
@@ -0,0 +1,151 @@
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC.
+ *
+ * ====================================================================
+ * 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 ${package}.functions;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.SortedSet;
+
+import org.jclouds.http.functions.config.ParserModule;
+import ${package}.domain.Status;
+import ${package}.domain.User;
+import org.jclouds.util.DateService;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.gson.Gson;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code ParseStatusesFromJsonResponse}
+ *
+ * @author ${author}
+ */
+@Test(groups = "unit", testName = "twitter.ParseStatusesFromJsonResponseTest")
+public class ParseStatusesFromJsonResponseTest {
+
+ Injector i = Guice.createInjector(new ParserModule() {
+ @Override
+ protected void configure() {
+ bind(DateTimeAdapter.class).to(CDateTimeAdapter.class);
+ super.configure();
+ }
+ });
+ DateService dateService = new DateService();
+
+ public void testApplyInputStreamDetails() throws UnknownHostException {
+ InputStream is = getClass().getResourceAsStream("/test_mentions.json");
+
+ SortedSet expects = ImmutableSortedSet
+ .of(
+
+ new Status(
+ dateService.cDateParse("Sat Oct 31 01:45:14 +0000 2009"),
+ false,
+ null,
+ 5303839785l,
+ null,
+ null,
+ null,
+ "TweetDeck",
+ "RT @jclouds: come find out about ${symbol_pound}cloud storage and how to access it from ${symbol_pound}java in palo alto this Tuesday: http://is.gd/4IFA9",
+ false,
+ new User(
+ dateService.cDateParse("Sat Apr 26 06:13:08 +0000 2008"),
+ "Jack of All Trades: Dad to anZel and Arden, VMware, vCloud, Security, Compliance, Former Developer",
+ 0,
+ 474,
+ false,
+ 199,
+ false,
+ 14540593,
+ "Bay Area, CA",
+ "Jian Zhen",
+ false,
+ "C6E2EE",
+ URI
+ .create("http://s.twimg.com/a/1256778767/images/themes/theme2/bg.gif"),
+ false,
+ URI
+ .create("http://a3.twimg.com/profile_images/64445411/30b8b19_bigger_normal.jpg"),
+ "1F98C7", "C6E2EE", "DAECF4", "663B12", false, "zhenjl",
+ 1981, "Pacific Time (US & Canada)", URI
+ .create("http://zhen.org"), -28800, false)),
+
+ new Status(
+ dateService.cDateParse("Sat Oct 31 09:35:27 +0000 2009"),
+ false,
+ null,
+ 5310690603l,
+ null,
+ null,
+ null,
+ "TweetDeck",
+ "RT @jclouds: live multi ${symbol_pound}cloud demo of jclouds connecting to 3 storage clouds from google appengine http://is.gd/4IXMh",
+ false,
+ new User(
+ dateService.cDateParse("Tue Apr 28 15:29:42 +0000 2009"),
+ "Some random guy who seems to care about cloud collisions at siliconANGLE.com",
+ 245,
+ 572,
+ false,
+ 325,
+ false,
+ 36093693,
+ "San Francisco ",
+ "James Watters",
+ false,
+ "C6E2EE",
+ URI
+ .create("http://a1.twimg.com/profile_background_images/24067016/17361976.jpg"),
+ true,
+ URI
+ .create("http://a3.twimg.com/profile_images/445071063/tiktaalik-transitional-fossil_normal.png"),
+ "1F98C7",
+ "C6E2EE",
+ "DAECF4",
+ "663B12",
+ false,
+ "wattersjames",
+ 1964,
+ "Pacific Time (US & Canada)",
+ URI
+ .create("http://siliconangle.net/ver2/author/jwatters/"),
+ -28800, false))
+
+ );
+
+ ParseStatusesFromJsonResponse parser = new ParseStatusesFromJsonResponse(i
+ .getInstance(Gson.class));
+ SortedSet response = parser.apply(is);
+ assertEquals(response, expects);
+ }
+}
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/resources/log4j.xml b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/resources/log4j.xml
new file mode 100644
index 0000000000..d69a42f26f
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/resources/log4j.xml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/resources/test_mentions.json b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/resources/test_mentions.json
new file mode 100644
index 0000000000..19e6deb04a
--- /dev/null
+++ b/archetypes/jclouds-json-client-archetype/src/main/resources/archetype-resources/src/test/resources/test_mentions.json
@@ -0,0 +1,77 @@
+[ { "created_at" : "Sat Oct 31 09:35:27 +0000 2009",
+ "favorited" : false,
+ "geo" : null,
+ "id" : 5310690603,
+ "in_reply_to_screen_name" : null,
+ "in_reply_to_status_id" : null,
+ "in_reply_to_user_id" : null,
+ "source" : "TweetDeck",
+ "text" : "RT @jclouds: live multi #cloud demo of jclouds connecting to 3 storage clouds from google appengine http://is.gd/4IXMh",
+ "truncated" : false,
+ "user" : { "created_at" : "Tue Apr 28 15:29:42 +0000 2009",
+ "description" : "Some random guy who seems to care about cloud collisions at siliconANGLE.com",
+ "favourites_count" : 245,
+ "followers_count" : 572,
+ "following" : false,
+ "friends_count" : 325,
+ "geo_enabled" : false,
+ "id" : 36093693,
+ "location" : "San Francisco ",
+ "name" : "James Watters",
+ "notifications" : false,
+ "profile_background_color" : "C6E2EE",
+ "profile_background_image_url" : "http://a1.twimg.com/profile_background_images/24067016/17361976.jpg",
+ "profile_background_tile" : true,
+ "profile_image_url" : "http://a3.twimg.com/profile_images/445071063/tiktaalik-transitional-fossil_normal.png",
+ "profile_link_color" : "1F98C7",
+ "profile_sidebar_border_color" : "C6E2EE",
+ "profile_sidebar_fill_color" : "DAECF4",
+ "profile_text_color" : "663B12",
+ "protected" : false,
+ "screen_name" : "wattersjames",
+ "statuses_count" : 1964,
+ "time_zone" : "Pacific Time (US & Canada)",
+ "url" : "http://siliconangle.net/ver2/author/jwatters/",
+ "utc_offset" : -28800,
+ "verified" : false
+ }
+ },
+ { "created_at" : "Sat Oct 31 01:45:14 +0000 2009",
+ "favorited" : false,
+ "geo" : null,
+ "id" : 5303839785,
+ "in_reply_to_screen_name" : null,
+ "in_reply_to_status_id" : null,
+ "in_reply_to_user_id" : null,
+ "source" : "TweetDeck",
+ "text" : "RT @jclouds: come find out about #cloud storage and how to access it from #java in palo alto this Tuesday: http://is.gd/4IFA9",
+ "truncated" : false,
+ "user" : { "created_at" : "Sat Apr 26 06:13:08 +0000 2008",
+ "description" : "Jack of All Trades: Dad to anZel and Arden, VMware, vCloud, Security, Compliance, Former Developer",
+ "favourites_count" : 0,
+ "followers_count" : 474,
+ "following" : false,
+ "friends_count" : 199,
+ "geo_enabled" : false,
+ "id" : 14540593,
+ "location" : "Bay Area, CA",
+ "name" : "Jian Zhen",
+ "notifications" : false,
+ "profile_background_color" : "C6E2EE",
+ "profile_background_image_url" : "http://s.twimg.com/a/1256778767/images/themes/theme2/bg.gif",
+ "profile_background_tile" : false,
+ "profile_image_url" : "http://a3.twimg.com/profile_images/64445411/30b8b19_bigger_normal.jpg",
+ "profile_link_color" : "1F98C7",
+ "profile_sidebar_border_color" : "C6E2EE",
+ "profile_sidebar_fill_color" : "DAECF4",
+ "profile_text_color" : "663B12",
+ "protected" : false,
+ "screen_name" : "zhenjl",
+ "statuses_count" : 1981,
+ "time_zone" : "Pacific Time (US & Canada)",
+ "url" : "http://zhen.org",
+ "utc_offset" : -28800,
+ "verified" : false
+ }
+ }
+]
\ No newline at end of file
diff --git a/archetypes/pom.xml b/archetypes/pom.xml
new file mode 100644
index 0000000000..e4760ae496
--- /dev/null
+++ b/archetypes/pom.xml
@@ -0,0 +1,42 @@
+
+
+
+
+ jclouds-project
+ org.jclouds
+ 1.0-SNAPSHOT
+ ../project/pom.xml
+
+ 4.0.0
+ jclouds-archetypes
+ pom
+ jclouds Maven archetypes
+
+ jclouds-json-client-archetype
+
+