Issue 190: created skeleton for box.net

This commit is contained in:
Adrian Cole 2010-06-07 08:43:08 -07:00
parent bdf03e65d8
commit 7b204d2f94
17 changed files with 1141 additions and 6 deletions

View File

@ -62,7 +62,7 @@ public class ${providerName}AsyncClientTest extends RestClientTest<${providerNam
Method method = ${providerName}AsyncClient.class.getMethod("list"); Method method = ${providerName}AsyncClient.class.getMethod("list");
GeneratedHttpRequest<${providerName}AsyncClient> httpRequest = processor.createRequest(method); GeneratedHttpRequest<${providerName}AsyncClient> httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/item HTTP/1.1"); assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/items HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n"); assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null); assertPayloadEquals(httpRequest, null);
@ -70,9 +70,9 @@ public class ${providerName}AsyncClientTest extends RestClientTest<${providerNam
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/item HTTP/1.1"); assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/items HTTP/1.1");
// for example, using basic authentication, we should get "only one" header // for example, using basic authentication, we should get "only one" header
assertHeadersEqual(httpRequest, "Accept: application/json\nAuthorization: Basic Zm9vOmJhcg==\n"); assertHeadersEqual(httpRequest, "Accept: application/json\nAuthorization: Basic dXNlcjprZXk=\n");
assertPayloadEquals(httpRequest, null); assertPayloadEquals(httpRequest, null);
// TODO: insert expected response class, which probably extends ParseJson // TODO: insert expected response class, which probably extends ParseJson
@ -88,7 +88,7 @@ public class ${providerName}AsyncClientTest extends RestClientTest<${providerNam
Method method = ${providerName}AsyncClient.class.getMethod("get", long.class); Method method = ${providerName}AsyncClient.class.getMethod("get", long.class);
GeneratedHttpRequest<${providerName}AsyncClient> httpRequest = processor.createRequest(method, 1); GeneratedHttpRequest<${providerName}AsyncClient> httpRequest = processor.createRequest(method, 1);
assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/item/1 HTTP/1.1"); assertRequestLineEquals(httpRequest, "GET ${providerEndpoint}/items/1 HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n"); assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null); assertPayloadEquals(httpRequest, null);
@ -108,7 +108,7 @@ public class ${providerName}AsyncClientTest extends RestClientTest<${providerNam
method, 1); method, 1);
assertRequestLineEquals(httpRequest, assertRequestLineEquals(httpRequest,
"DELETE ${providerEndpoint}/item/1 HTTP/1.1"); "DELETE ${providerEndpoint}/items/1 HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n"); assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null); assertPayloadEquals(httpRequest, null);

9
boxdotnet/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
# use glob syntax.
syntax: glob
target
.settings
.classpath
.project
jclouds-boxdotnet.iml
jclouds-boxdotnet.ipr
jclouds-boxdotnet.iws

92
boxdotnet/pom.xml Normal file
View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$HeadURL$
$Revision$
$Date$
Copyright (C) 2009 Cloud Conscious, LLC <info@cloudconscious.com>
====================================================================
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.html
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.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-boxdotnet</artifactId>
<name>jclouds BoxDotNet core</name>
<description>jclouds components to access BoxDotNet</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/boxdotnet</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/boxdotnet</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/boxdotnet</url>
</scm>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
<repository>
<id>jclouds-googlecode-deploy</id>
<url>http://jclouds.googlecode.com/svn/repo</url>
</repository>
<repository>
<id>jclouds-rimu-snapshots-nexus</id>
<url>http://jclouds.rimuhosting.com:8081/nexus/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<jclouds.test.user>apiKey</jclouds.test.user>
<jclouds.test.key>authToken</jclouds.test.key>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,39 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet;
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 BoxDotNet resource.
*
* @author Adrian Cole
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface BoxDotNet {
}

View File

@ -0,0 +1,81 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.boxdotnet.BoxDotNetClient;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to BoxDotNet via their REST API.
* <p/>
*
* @see BoxDotNetClient
* @see <a href="TODO: insert URL of provider documentation" />
* @author Adrian Cole
*/
@Endpoint(BoxDotNet.class)
@RequestFilters(BasicAuthentication.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface BoxDotNetAsyncClient {
/*
* TODO: define interface methods for BoxDotNet
*/
/**
* @see BoxDotNetClient#list()
*/
@GET
@Path("/items")
ListenableFuture<String> list();
/**
* @see BoxDotNetClient#get(long)
*/
@GET
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/items/{itemId}")
ListenableFuture<String> get(@PathParam("itemId") long id);
/**
* @see BoxDotNetClient#delete
*/
@DELETE
@Path("/items/{itemId}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> delete(@PathParam("itemId") long id);
}

View File

@ -0,0 +1,55 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to BoxDotNet.
* <p/>
*
* @see BoxDotNetAsyncClient
* @see <a href="TODO: insert URL of BoxDotNet documentation" />
* @author Adrian Cole
*/
@Timeout(duration = 4, timeUnit = TimeUnit.SECONDS)
public interface BoxDotNetClient {
/*
* Note all these delegate to methods in BoxDotNetAsyncClient with a specified or inherited timeout.
* The singatures should match those of BoxDotNetAsyncClient, except the returnvals should not be
* wrapped in a ListenableFuture
*/
String list();
/**
* @return null, if not found
*/
String get(long id);
void delete(long id);
}

View File

@ -0,0 +1,62 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import java.util.Properties;
import org.jclouds.rest.RestContextBuilder;
import org.jclouds.boxdotnet.BoxDotNetAsyncClient;
import org.jclouds.boxdotnet.BoxDotNetClient;
import org.jclouds.boxdotnet.config.BoxDotNetContextModule;
import org.jclouds.boxdotnet.config.BoxDotNetRestClientModule;
import org.jclouds.boxdotnet.reference.BoxDotNetConstants;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class BoxDotNetContextBuilder extends RestContextBuilder<BoxDotNetClient, BoxDotNetAsyncClient> {
public BoxDotNetContextBuilder(String providerName, Properties props) {
super(providerName, BoxDotNetClient.class, BoxDotNetAsyncClient.class, props);
checkNotNull(properties.getProperty(BoxDotNetConstants.PROPERTY_BOXDOTNET_USER));
checkNotNull(properties.getProperty(BoxDotNetConstants.PROPERTY_BOXDOTNET_PASSWORD));
}
protected void addClientModule(List<Module> modules) {
modules.add(new BoxDotNetRestClientModule());
}
@Override
protected void addContextModule(String providerName, List<Module> modules) {
modules.add(new BoxDotNetContextModule(providerName));
}
}

View File

@ -0,0 +1,69 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet;
import java.net.URI;
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 BoxDotNetClient} instances based on the most commonly
* requested arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see RestContext
* @see BoxDotNetClient
* @see BoxDotNetAsyncClient
*/
public class BoxDotNetContextFactory {
public static RestContext<BoxDotNetClient, BoxDotNetAsyncClient> createContext(String user, String password,
Module... modules) {
return new BoxDotNetContextBuilder("boxdotnet", new BoxDotNetPropertiesBuilder(user, password).build())
.withModules(modules).buildContext();
}
public static RestContext<BoxDotNetClient, BoxDotNetAsyncClient> createContext(URI endpoint, String user, String password,
Module... modules) {
return new BoxDotNetContextBuilder("boxdotnet", new BoxDotNetPropertiesBuilder(user, password).withEndpoint(endpoint).build())
.withModules(modules).buildContext();
}
public static RestContext<BoxDotNetClient, BoxDotNetAsyncClient> createContext(Properties properties, Module... modules) {
return new BoxDotNetContextBuilder("boxdotnet", new BoxDotNetPropertiesBuilder(properties).build())
.withModules(modules).buildContext();
}
}

View File

@ -0,0 +1,69 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.boxdotnet.reference.BoxDotNetConstants.PROPERTY_BOXDOTNET_ENDPOINT;
import static org.jclouds.boxdotnet.reference.BoxDotNetConstants.PROPERTY_BOXDOTNET_PASSWORD;
import static org.jclouds.boxdotnet.reference.BoxDotNetConstants.PROPERTY_BOXDOTNET_USER;
import java.net.URI;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
/**
* Builds properties used in BoxDotNet Clients
*
* @author Adrian Cole
*/
public class BoxDotNetPropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_BOXDOTNET_ENDPOINT, "https://www.box.net/api/1.0/rest");
return properties;
}
public BoxDotNetPropertiesBuilder(Properties properties) {
super(properties);
}
public BoxDotNetPropertiesBuilder(String id, String secret) {
super();
withCredentials(id, secret);
}
public BoxDotNetPropertiesBuilder withCredentials(String id, String secret) {
properties.setProperty(PROPERTY_BOXDOTNET_USER, checkNotNull(id, "user"));
properties.setProperty(PROPERTY_BOXDOTNET_PASSWORD, checkNotNull(secret, "password"));
return this;
}
public BoxDotNetPropertiesBuilder withEndpoint(URI endpoint) {
properties.setProperty(PROPERTY_BOXDOTNET_ENDPOINT, checkNotNull(endpoint, "endpoint")
.toString());
return this;
}
}

View File

@ -0,0 +1,84 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet.config;
import java.net.URI;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.lifecycle.Closer;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.RestContextImpl;
import org.jclouds.boxdotnet.BoxDotNet;
import org.jclouds.boxdotnet.BoxDotNetAsyncClient;
import org.jclouds.boxdotnet.BoxDotNetClient;
import org.jclouds.boxdotnet.reference.BoxDotNetConstants;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
* Configures the BoxDotNet connection, including logging and http transport.
*
* @author Adrian Cole
*/
public class BoxDotNetContextModule extends AbstractModule {
public BoxDotNetContextModule(String providerName) {
// providerName ignored right now
}
@Override
protected void configure() {
// example of how to customize bindings
// bind(DateAdapter.class).to(CDateAdapter.class);
}
@Provides
@Singleton
RestContext<BoxDotNetClient, BoxDotNetAsyncClient> provideContext(Closer closer, BoxDotNetAsyncClient asyncApi,
BoxDotNetClient syncApi, @BoxDotNet URI endPoint, @Named(BoxDotNetConstants.PROPERTY_BOXDOTNET_USER) String account) {
return new RestContextImpl<BoxDotNetClient, BoxDotNetAsyncClient>(closer, asyncApi, syncApi, endPoint, account);
}
}

View File

@ -0,0 +1,114 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet.config;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.RequiresHttp;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.boxdotnet.BoxDotNet;
import org.jclouds.boxdotnet.BoxDotNetClient;
import org.jclouds.boxdotnet.BoxDotNetAsyncClient;
import org.jclouds.boxdotnet.reference.BoxDotNetConstants;
import org.jclouds.boxdotnet.handlers.BoxDotNetErrorHandler;
import com.google.inject.Provides;
/**
* Configures the BoxDotNet connection.
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public class BoxDotNetRestClientModule extends
RestClientModule<BoxDotNetClient, BoxDotNetAsyncClient> {
public BoxDotNetRestClientModule() {
super(BoxDotNetClient.class, BoxDotNetAsyncClient.class);
}
@Provides
@Singleton
public BasicAuthentication provideBasicAuthentication(
@Named(BoxDotNetConstants.PROPERTY_BOXDOTNET_USER) String user,
@Named(BoxDotNetConstants.PROPERTY_BOXDOTNET_PASSWORD) String password,
EncryptionService encryptionService)
throws UnsupportedEncodingException {
return new BasicAuthentication(user, password, encryptionService);
}
@Provides
@Singleton
@BoxDotNet
protected URI provideURI(@Named(BoxDotNetConstants.PROPERTY_BOXDOTNET_ENDPOINT) String endpoint) {
return URI.create(endpoint);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
BoxDotNetErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
BoxDotNetErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
BoxDotNetErrorHandler.class);
}
@Override
protected void bindRetryHandlers() {
// TODO
}
}

View File

@ -0,0 +1,89 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet.handlers;
import java.io.IOException;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.util.Utils;
import com.google.common.base.Throwables;
import com.google.common.io.Closeables;
/**
* This will parse and set an appropriate exception on the command object.
*
* @author Adrian Cole
*
*/
@Singleton
public class BoxDotNetErrorHandler implements HttpErrorHandler {
@Resource
protected Logger logger = Logger.NULL;
public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams
String message = parseMessage(response);
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
try {
message = message != null ? message : String.format("%s -> %s", command.getRequest()
.getRequestLine(), response.getStatusLine());
switch (response.getStatusCode()) {
case 401:
case 403:
exception = new AuthorizationException(message, exception);
break;
case 404:
if (!command.getRequest().getMethod().equals("DELETE")) {
exception = new ResourceNotFoundException(message, exception);
}
break;
}
} finally {
Closeables.closeQuietly(response.getContent());
command.setException(exception);
}
}
public String parseMessage(HttpResponse response) {
if (response.getContent() == null)
return null;
try {
return Utils.toStringAndClose(response.getContent());
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
response.getContent().close();
} catch (IOException e) {
Throwables.propagate(e);
}
}
}
}

View File

@ -0,0 +1,53 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet.reference;
/**
* Configuration properties and constants used in BoxDotNet connections.
*
* @author Adrian Cole
*/
public interface BoxDotNetConstants {
public static final String PROPERTY_BOXDOTNET_ENDPOINT = "jclouds.boxdotnet.endpoint";
public static final String PROPERTY_BOXDOTNET_USER = "jclouds.boxdotnet.user";
public static final String PROPERTY_BOXDOTNET_PASSWORD = "jclouds.boxdotnet.password";
}

View File

@ -0,0 +1,141 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.boxdotnet.config.BoxDotNetRestClientModule;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.functions.CloseContentAndReturn;
import org.jclouds.http.functions.ReturnStringIf200;
import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
/**
* Tests annotation parsing of {@code BoxDotNetAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "boxdotnet.BoxDotNetAsyncClientTest")
public class BoxDotNetAsyncClientTest extends RestClientTest<BoxDotNetAsyncClient> {
public void testList() throws SecurityException, NoSuchMethodException, IOException {
Method method = BoxDotNetAsyncClient.class.getMethod("list");
GeneratedHttpRequest<BoxDotNetAsyncClient> httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest, "GET https://www.box.net/api/1.0/rest/items HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null);
// now make sure request filters apply by replaying
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
assertRequestLineEquals(httpRequest, "GET https://www.box.net/api/1.0/rest/items HTTP/1.1");
// for example, using basic authentication, we should get "only one" header
assertHeadersEqual(httpRequest, "Accept: application/json\nAuthorization: Basic dXNlcjprZXk=\n");
assertPayloadEquals(httpRequest, null);
// TODO: insert expected response class, which probably extends ParseJson
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf200.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testGet() throws SecurityException, NoSuchMethodException, IOException {
Method method = BoxDotNetAsyncClient.class.getMethod("get", long.class);
GeneratedHttpRequest<BoxDotNetAsyncClient> httpRequest = processor.createRequest(method, 1);
assertRequestLineEquals(httpRequest, "GET https://www.box.net/api/1.0/rest/items/1 HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null);
// TODO: insert expected response class, which probably extends ParseJson
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf200.class);
assertSaxResponseParserClassEquals(method, null);
// note that get methods should convert 404's to null
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testDelete() throws SecurityException, NoSuchMethodException, IOException {
Method method = BoxDotNetAsyncClient.class.getMethod("delete", long.class);
GeneratedHttpRequest<BoxDotNetAsyncClient> httpRequest = processor.createRequest(
method, 1);
assertRequestLineEquals(httpRequest,
"DELETE https://www.box.net/api/1.0/rest/items/1 HTTP/1.1");
assertHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null);
assertResponseParserClassEquals(method, httpRequest, CloseContentAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected void checkFilters(GeneratedHttpRequest<BoxDotNetAsyncClient> httpRequest) {
assertEquals(httpRequest.getFilters().size(), 1);
assertEquals(httpRequest.getFilters().get(0).getClass(), BasicAuthentication.class);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<BoxDotNetAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<BoxDotNetAsyncClient>>() {
};
}
@Override
protected Module createModule() {
return new BoxDotNetRestClientModule() {
@Override
protected void configure() {
Names.bindProperties(binder(), new BoxDotNetPropertiesBuilder("user", "key").build());
install(new NullLoggingModule());
super.configure();
}
};
}
}

View File

@ -0,0 +1,67 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.boxdotnet;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertNotNull;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code BoxDotNetClient}
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "boxdotnet.BoxDotNetClientLiveTest")
public class BoxDotNetClientLiveTest {
private BoxDotNetClient connection;
@BeforeGroups(groups = { "live" })
public void setupClient() {
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
connection = BoxDotNetContextFactory.createContext(user, password, new Log4JLoggingModule())
.getApi();
}
@Test
public void testList() throws Exception {
String response = connection.list();
assertNotNull(response);
}
@Test
public void testGet() throws Exception {
String response = connection.get(1l);
assertNotNull(response);
}
/*
* TODO: add tests for BoxDotNet interface methods
*/
}

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
====================================================================
-->
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
For more configuration infromation and examples see the Apache Log4j
website: http://logging.apache.org/log4j/
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message${symbol_escape}n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message${symbol_escape}n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category><!--
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
--><!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>

View File

@ -53,6 +53,7 @@
<module>chef</module> <module>chef</module>
<module>opscodeplatform</module> <module>opscodeplatform</module>
<module>ibmdev</module> <module>ibmdev</module>
<module>boxdotnet</module>
</modules> </modules>
<build> <build>
<plugins> <plugins>