mirror of https://github.com/apache/jclouds.git
Issue 830: initial vCloud 1.5 with session functionality complete
This commit is contained in:
parent
edbd09b984
commit
1905615c49
|
@ -61,6 +61,9 @@ opscodeplatform.propertiesbuilder=org.jclouds.opscodeplatform.OpscodePlatformPro
|
||||||
vcloud.contextbuilder=org.jclouds.vcloud.VCloudContextBuilder
|
vcloud.contextbuilder=org.jclouds.vcloud.VCloudContextBuilder
|
||||||
vcloud.propertiesbuilder=org.jclouds.vcloud.VCloudPropertiesBuilder
|
vcloud.propertiesbuilder=org.jclouds.vcloud.VCloudPropertiesBuilder
|
||||||
|
|
||||||
|
vcloud-director.contextbuilder=org.jclouds.vcloud.director.v1_5.VCloudDirectorContextBuilder
|
||||||
|
vcloud-director.propertiesbuilder=org.jclouds.vcloud.director.v1_5.VCloudDirectorPropertiesBuilder
|
||||||
|
|
||||||
eucalyptus.contextbuilder=org.jclouds.ec2.EC2ContextBuilder
|
eucalyptus.contextbuilder=org.jclouds.ec2.EC2ContextBuilder
|
||||||
eucalyptus.propertiesbuilder=org.jclouds.eucalyptus.EucalyptusPropertiesBuilder
|
eucalyptus.propertiesbuilder=org.jclouds.eucalyptus.EucalyptusPropertiesBuilder
|
||||||
|
|
||||||
|
|
|
@ -34,5 +34,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>openstack-nova</module>
|
<module>openstack-nova</module>
|
||||||
<module>virtualbox</module>
|
<module>virtualbox</module>
|
||||||
|
<module>vcloud-director</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. jclouds licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<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.5.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../../project/pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<groupId>org.jclouds.labs</groupId>
|
||||||
|
<artifactId>vcloud-director</artifactId>
|
||||||
|
<name>jcloud vcloud-director api</name>
|
||||||
|
<description>jclouds components to access an implementation of VMware vCloud Director 1.5+</description>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<test.vcloud-director.endpoint>https://vcloudbeta.bluelock.com/api</test.vcloud-director.endpoint>
|
||||||
|
<test.vcloud-director.api-version>1.5</test.vcloud-director.api-version>
|
||||||
|
<test.vcloud-director.build-version>1.5.0.464915</test.vcloud-director.build-version>
|
||||||
|
<test.vcloud-director.identity>FIXME_USERNAME_WHICH_MIGHT_BE_EMAIL@JClouds</test.vcloud-director.identity>
|
||||||
|
<test.vcloud-director.credential>FIXME_PASSWORD</test.vcloud-director.credential>
|
||||||
|
<test.vcloud-director.image-id></test.vcloud-director.image-id>
|
||||||
|
<test.vcloud-director.image.login-user></test.vcloud-director.image.login-user>
|
||||||
|
<test.vcloud-director.image.authenticate-sudo></test.vcloud-director.image.authenticate-sudo>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-compute</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-compute</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds.driver</groupId>
|
||||||
|
<artifactId>jclouds-sshj</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds.driver</groupId>
|
||||||
|
<artifactId>jclouds-slf4j</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>0.9.29</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>live</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>integration</id>
|
||||||
|
<phase>integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<test.vcloud-director.endpoint>${test.vcloud-director.endpoint}</test.vcloud-director.endpoint>
|
||||||
|
<test.vcloud-director.api-version>${test.vcloud-director.api-version}</test.vcloud-director.api-version>
|
||||||
|
<test.vcloud-director.build-version>${test.vcloud-director.build-version}</test.vcloud-director.build-version>
|
||||||
|
<test.vcloud-director.identity>${test.vcloud-director.identity}</test.vcloud-director.identity>
|
||||||
|
<test.vcloud-director.credential>${test.vcloud-director.credential}</test.vcloud-director.credential>
|
||||||
|
<test.vcloud-director.image-id>${test.vcloud-director.image-id}</test.vcloud-director.image-id>
|
||||||
|
<test.vcloud-director.image.login-user>${test.vcloud-director.image.login-user}</test.vcloud-director.image.login-user>
|
||||||
|
<test.vcloud-director.image.authenticate-sudo>${test.vcloud-director.image.authenticate-sudo}</test.vcloud-director.image.authenticate-sudo>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Export-Package>org.jclouds.vcloud.director.v1_5.*;version="${project.version}"</Export-Package>
|
||||||
|
<Import-Package>
|
||||||
|
org.jclouds.compute.internal;version="${project.version}",
|
||||||
|
org.jclouds.rest.internal;version="${project.version}",
|
||||||
|
org.jclouds.*;version="${project.version}",
|
||||||
|
*
|
||||||
|
</Import-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5;
|
||||||
|
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.Session;
|
||||||
|
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to VCloudDirector via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @see VCloudDirectorClient
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public interface VCloudDirectorAsyncClient {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the current login session
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
Session getCurrentSession();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.Session;
|
||||||
|
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to VCloudDirector.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @see VCloudDirectorAsyncClient
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
||||||
|
public interface VCloudDirectorClient {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the current login session
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
Session getCurrentSession();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.vcloud.director.v1_5.config.VCloudDirectorRestClientModule;
|
||||||
|
import org.jclouds.rest.RestContextBuilder;
|
||||||
|
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class VCloudDirectorContextBuilder extends RestContextBuilder<VCloudDirectorClient, VCloudDirectorAsyncClient> {
|
||||||
|
|
||||||
|
public VCloudDirectorContextBuilder(Properties props) {
|
||||||
|
super(VCloudDirectorClient.class, VCloudDirectorAsyncClient.class, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addClientModule(List<Module> modules) {
|
||||||
|
modules.add(new VCloudDirectorRestClientModule());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource Types used in VCloud
|
||||||
|
*
|
||||||
|
* <br/>
|
||||||
|
* The object type, specified as a MIME content type, of the object that the link references. This
|
||||||
|
* attribute is present only for links to objects. It is not present for links to actions.
|
||||||
|
*
|
||||||
|
* @see MediaType
|
||||||
|
*/
|
||||||
|
public interface VCloudDirectorMediaType {
|
||||||
|
public final static String NS = "http://www.vmware.com/vcloud/v1.5";
|
||||||
|
|
||||||
|
public final static String SESSION_XML = "application/vnd.vmware.vcloud.session+xml";
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5;
|
||||||
|
|
||||||
|
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||||
|
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||||
|
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.PropertiesBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds properties used in VCloudDirector Clients
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class VCloudDirectorPropertiesBuilder extends PropertiesBuilder {
|
||||||
|
@Override
|
||||||
|
protected Properties defaultProperties() {
|
||||||
|
Properties properties = super.defaultProperties();
|
||||||
|
properties.setProperty(PROPERTY_ENDPOINT, "http://localhost/api");
|
||||||
|
properties.setProperty(PROPERTY_SESSION_INTERVAL, 30*60 + "");
|
||||||
|
properties.setProperty(PROPERTY_API_VERSION, "1.5");
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VCloudDirectorPropertiesBuilder(Properties properties) {
|
||||||
|
super(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.jclouds.vcloud.director.v1_5.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.inject.Qualifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The login url for the vCloud, typically {@code https://vdc_host/api/sessions}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Retention(value = RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = { ElementType.METHOD, ElementType.PARAMETER })
|
||||||
|
@Qualifier
|
||||||
|
public @interface Login {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.jclouds.vcloud.director.v1_5.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.inject.Qualifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* relating to the current session on the vCloud
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Retention(value = RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value = { ElementType.METHOD, ElementType.PARAMETER })
|
||||||
|
@Qualifier
|
||||||
|
public @interface Session {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.binders;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
|
||||||
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
|
import org.jclouds.rest.MapBinder;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses Basic Authentication to sign the request.
|
||||||
|
*
|
||||||
|
* @see <a href= "http://en.wikipedia.org/wiki/Basic_access_authentication" />
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class BindUserOrgAndPasswordAsBasicAuthorizationHeader implements MapBinder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
|
||||||
|
try {
|
||||||
|
String header = "Basic "
|
||||||
|
+ CryptoStreams.base64(String.format("%s@%s:%s", checkNotNull(postParams.get("user"), "user"),
|
||||||
|
checkNotNull(postParams.get("org"), "org"),
|
||||||
|
checkNotNull(postParams.get("password"), "password")).getBytes("UTF-8"));
|
||||||
|
return ModifyRequest.replaceHeader(request, HttpHeaders.AUTHORIZATION, header);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw Throwables.propagate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
/**
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.config;
|
||||||
|
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.concurrent.RetryOnTimeOutExceptionFunction;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.http.HttpErrorHandler;
|
||||||
|
import org.jclouds.http.HttpRetryHandler;
|
||||||
|
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.location.Provider;
|
||||||
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
|
import org.jclouds.rest.config.RestClientModule;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.VCloudDirectorAsyncClient;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.annotations.Login;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.Session;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.functions.LoginUserInOrgWithPassword;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.handlers.InvalidateSessionAndRetryOn401AndLogoutOnClose;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.handlers.VCloudDirectorErrorHandler;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.login.SessionAsyncClient;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.login.SessionClient;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
import com.google.inject.name.Named;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the VCloudDirector connection.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@RequiresHttp
|
||||||
|
@ConfiguresRestClient
|
||||||
|
public class VCloudDirectorRestClientModule extends RestClientModule<VCloudDirectorClient, VCloudDirectorAsyncClient> {
|
||||||
|
|
||||||
|
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
|
||||||
|
// TODO
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public VCloudDirectorRestClientModule() {
|
||||||
|
super(VCloudDirectorClient.class, VCloudDirectorAsyncClient.class, DELEGATE_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
// session client is used directly for filters and retry handlers, so let's bind it explicitly
|
||||||
|
bindClientAndAsyncClient(binder(), SessionClient.class, SessionAsyncClient.class);
|
||||||
|
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(
|
||||||
|
InvalidateSessionAndRetryOn401AndLogoutOnClose.class);
|
||||||
|
super.configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void bindErrorHandlers() {
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(VCloudDirectorErrorHandler.class);
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(VCloudDirectorErrorHandler.class);
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(VCloudDirectorErrorHandler.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Login
|
||||||
|
protected Supplier<URI> loginUrl(@Provider Supplier<URI> provider) {
|
||||||
|
// TODO: technically, we should implement version client, but this will work
|
||||||
|
return Suppliers.compose(new Function<URI, URI>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI apply(URI arg0) {
|
||||||
|
return URI.create(arg0.toASCIIString() + "/sessions");
|
||||||
|
}
|
||||||
|
|
||||||
|
}, provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
protected Supplier<Session> currentSession(Supplier<SessionWithToken> in) {
|
||||||
|
return Suppliers.compose(new Function<SessionWithToken, Session>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Session apply(SessionWithToken arg0) {
|
||||||
|
return arg0.getSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, in);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@org.jclouds.vcloud.director.v1_5.annotations.Session
|
||||||
|
protected Supplier<String> sessionToken(Supplier<SessionWithToken> in) {
|
||||||
|
return Suppliers.compose(new Function<SessionWithToken, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(SessionWithToken arg0) {
|
||||||
|
return arg0.getToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, in);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Function<Credentials, SessionWithToken> makeSureFilterRetriesOnTimeout(
|
||||||
|
LoginUserInOrgWithPassword loginWithPasswordCredentials) {
|
||||||
|
// we should retry on timeout exception logging in.
|
||||||
|
return new RetryOnTimeOutExceptionFunction<Credentials, SessionWithToken>(loginWithPasswordCredentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public LoadingCache<Credentials, SessionWithToken> provideSessionWithTokenCache(
|
||||||
|
Function<Credentials, SessionWithToken> getSessionWithToken,
|
||||||
|
@Named(Constants.PROPERTY_SESSION_INTERVAL) int seconds) {
|
||||||
|
return CacheBuilder.newBuilder().expireAfterWrite(seconds, TimeUnit.SECONDS).build(
|
||||||
|
CacheLoader.from(getSessionWithToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporary conversion of a cache to a supplier until there is a single-element cache
|
||||||
|
// http://code.google.com/p/guava-libraries/issues/detail?id=872
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Supplier<SessionWithToken> provideSessionWithTokenSupplier(
|
||||||
|
final LoadingCache<Credentials, SessionWithToken> cache, @Provider final Credentials creds) {
|
||||||
|
return new Supplier<SessionWithToken>() {
|
||||||
|
@Override
|
||||||
|
public SessionWithToken get() {
|
||||||
|
try {
|
||||||
|
return cache.get(creds);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
throw propagate(e.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Location of a Rest resource <xs:complexType name="ReferenceType">
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BaseNamedResource<T extends BaseNamedResource<T>> extends BaseResource<T> {
|
||||||
|
|
||||||
|
public static <T extends BaseNamedResource<T>> Builder<T> builder() {
|
||||||
|
return new Builder<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> toBuilder() {
|
||||||
|
return new Builder<T>().fromNamedResource(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder<T extends BaseNamedResource<T>> extends BaseResource.Builder<T> {
|
||||||
|
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see BaseNamedResource#getName
|
||||||
|
*/
|
||||||
|
public Builder<T> name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseNamedResource<T> build() {
|
||||||
|
return new BaseNamedResource<T>(href, type, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Builder<T> fromBaseResource(BaseResource<T> in) {
|
||||||
|
return Builder.class.cast(super.fromBaseResource(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> fromNamedResource(BaseNamedResource<T> in) {
|
||||||
|
return fromBaseResource(in).name(in.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Builder<T> fromAttributes(Map<String, String> attributes) {
|
||||||
|
return Builder.class.cast(super.fromAttributes(attributes)).name(attributes.get("name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlAttribute
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
protected BaseNamedResource(URI href, String type, String name) {
|
||||||
|
super(href, type);
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BaseNamedResource() {
|
||||||
|
// For JAXB
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the referenced object, taken from the value of that object's name attribute.
|
||||||
|
* Action links do not include a name attribute.
|
||||||
|
*
|
||||||
|
* @return name;
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!super.equals(o))
|
||||||
|
return false;
|
||||||
|
BaseNamedResource<?> that = BaseNamedResource.class.cast(o);
|
||||||
|
return equal(name, that.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return super.hashCode() + Objects.hashCode(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ToStringHelper string() {
|
||||||
|
return super.string().add("name", name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Location of a Rest resource
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BaseResource<T extends BaseResource<T>> {
|
||||||
|
|
||||||
|
public static <T extends BaseResource<T>> Builder<T> builder() {
|
||||||
|
return new Builder<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<T> toBuilder() {
|
||||||
|
return new Builder<T>().fromBaseResource(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder<T extends BaseResource<T>> {
|
||||||
|
|
||||||
|
protected String type;
|
||||||
|
protected URI href;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see BaseResource#getType
|
||||||
|
*/
|
||||||
|
public Builder<T> type(String type) {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see BaseResource#getHref
|
||||||
|
*/
|
||||||
|
public Builder<T> href(URI href) {
|
||||||
|
this.href = href;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseResource<T> build() {
|
||||||
|
return new BaseResource<T>(href, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Builder<T> fromBaseResource(BaseResource<T> in) {
|
||||||
|
return type(in.getType()).href(in.getHref());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Builder<T> fromAttributes(Map<String, String> attributes) {
|
||||||
|
return href(URI.create(attributes.get("href"))).type(attributes.get("type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlAttribute
|
||||||
|
protected String type;
|
||||||
|
|
||||||
|
@XmlAttribute
|
||||||
|
protected URI href;
|
||||||
|
|
||||||
|
protected BaseResource(URI href, String type) {
|
||||||
|
this.type = type;
|
||||||
|
this.href = href;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BaseResource() {
|
||||||
|
// For JAXB
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object type, specified as a MIME content type, of the object that the link references.
|
||||||
|
* This attribute is present only for links to objects. It is not present for links to actions.
|
||||||
|
*
|
||||||
|
* @return type definition, type, expressed as an HTTP Content-Type
|
||||||
|
*/
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object reference, expressed in URL format. Because this URL includes the object identifier
|
||||||
|
* portion of the id attribute value, it uniquely identifies the object, persists for the life of
|
||||||
|
* the object, and is never reused. The value of the href attribute is a reference to a view of
|
||||||
|
* the object, and can be used to access a representation of the object that is valid in a
|
||||||
|
* particular context. Although URLs have a well-known syntax and a well-understood
|
||||||
|
* interpretation, a client should treat each href as an opaque string. The rules that govern how
|
||||||
|
* the server constructs href strings might change in future releases.
|
||||||
|
*
|
||||||
|
* @return an opaque reference and should never be parsed
|
||||||
|
*/
|
||||||
|
public URI getHref() {
|
||||||
|
return href;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #getHref
|
||||||
|
*/
|
||||||
|
public URI getURI() {
|
||||||
|
return getHref();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
BaseResource<?> that = BaseResource.class.cast(o);
|
||||||
|
return equal(href, that.href) && equal(type, that.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(type, href);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return Objects.toStringHelper("").add("href", href).add("type", type);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
package org.jclouds.vcloud.director.v1_5.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <xs:complexType name="LinkType">
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Link extends BaseNamedResource<Link> {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return new Builder().fromLink(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder extends BaseNamedResource.Builder<Link> {
|
||||||
|
|
||||||
|
protected String rel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Link#getString
|
||||||
|
*/
|
||||||
|
public Builder rel(String rel) {
|
||||||
|
this.rel = rel;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Link build() {
|
||||||
|
return new Link(href, type, name, rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder fromLink(Link in) {
|
||||||
|
return fromNamedResource(in).rel(in.getRel());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Builder fromBaseResource(BaseResource<Link> in) {
|
||||||
|
return Builder.class.cast(super.fromBaseResource(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Builder fromNamedResource(BaseNamedResource<Link> in) {
|
||||||
|
return Builder.class.cast(super.fromNamedResource(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Builder name(String name) {
|
||||||
|
return Builder.class.cast(super.name(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Builder href(URI href) {
|
||||||
|
return Builder.class.cast(super.href(href));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Builder type(String type) {
|
||||||
|
return Builder.class.cast(super.type(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Builder fromAttributes(Map<String, String> attributes) {
|
||||||
|
super.fromAttributes(attributes);
|
||||||
|
rel(attributes.get("rel"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlAttribute
|
||||||
|
protected String rel;
|
||||||
|
|
||||||
|
private Link(URI href, String type, String name, String rel) {
|
||||||
|
super(href, type, name);
|
||||||
|
this.rel = checkNotNull(rel, "rel");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Link() {
|
||||||
|
// For JAXB
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the relationship of the link to the object that contains it. A relationship can be the
|
||||||
|
* name of an operation on the object, a reference to a contained or containing object, or a
|
||||||
|
* reference to an alternate representation of the object. The relationship value implies the
|
||||||
|
* HTTP verb to use when you use the link's href value as a request URL.
|
||||||
|
*
|
||||||
|
* @return relationship of the link to the object that contains it.
|
||||||
|
*/
|
||||||
|
public String getRel() {
|
||||||
|
return rel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!super.equals(o))
|
||||||
|
return false;
|
||||||
|
Link that = (Link) o;
|
||||||
|
return equal(this.rel, that.rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return super.hashCode() + Objects.hashCode(rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ToStringHelper string() {
|
||||||
|
return super.string().add("rel", rel);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.NS;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login Session
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@XmlRootElement(namespace = NS, name = "Session")
|
||||||
|
public class Session {
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return new Builder().fromSession(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private String user;
|
||||||
|
private String org;
|
||||||
|
private URI href;
|
||||||
|
private Set<Link> links = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Session#getUser
|
||||||
|
*/
|
||||||
|
public Builder user(String user) {
|
||||||
|
this.user = user;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Session#getOrg
|
||||||
|
*/
|
||||||
|
public Builder org(String org) {
|
||||||
|
this.org = org;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Session#getHref
|
||||||
|
*/
|
||||||
|
public Builder href(URI href) {
|
||||||
|
this.href = href;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Session#getLinks
|
||||||
|
*/
|
||||||
|
public Builder links(Set<Link> links) {
|
||||||
|
this.links = Sets.newLinkedHashSet(checkNotNull(links, "links"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Session#getLinks
|
||||||
|
*/
|
||||||
|
public Builder addLink(Link link) {
|
||||||
|
links.add(checkNotNull(link, "link"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session build() {
|
||||||
|
return new Session(user, org, href, links);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder fromSession(Session in) {
|
||||||
|
return user(in.getUser()).org(in.getOrg()).href(in.getHref()).links(in.getLinks());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Session() {
|
||||||
|
// For JAXB and builder use
|
||||||
|
}
|
||||||
|
|
||||||
|
private Session(String user, String org, URI href, Set<Link> links) {
|
||||||
|
this.user = user;
|
||||||
|
this.org = org;
|
||||||
|
this.href = href;
|
||||||
|
this.links = ImmutableSet.copyOf(links);
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(namespace = NS, name = "Link")
|
||||||
|
private Set<Link> links = Sets.newLinkedHashSet();
|
||||||
|
@XmlAttribute
|
||||||
|
private String user;
|
||||||
|
@XmlAttribute
|
||||||
|
private String org;
|
||||||
|
@XmlAttribute
|
||||||
|
private URI href;
|
||||||
|
|
||||||
|
public Set<Link> getLinks() {
|
||||||
|
return ImmutableSet.copyOf(links);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the user's login name.
|
||||||
|
*/
|
||||||
|
public String getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return is the name of an organization of which the user is a member
|
||||||
|
*/
|
||||||
|
public String getOrg() {
|
||||||
|
return org;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return a reference to the current session
|
||||||
|
*/
|
||||||
|
public URI getHref() {
|
||||||
|
return href;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
Session that = Session.class.cast(o);
|
||||||
|
return equal(user, that.user) && equal(org, that.org) && equal(href, that.href) && equal(links, that.links);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(org, user, href, links);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Objects.toStringHelper("").add("user", user).add("org", org).add("href", href).add("links", links)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session and its corresponding token
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SessionWithToken {
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return new Builder().fromSessionWithToken(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
protected Session session;
|
||||||
|
protected String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SessionWithToken#getType
|
||||||
|
*/
|
||||||
|
public Builder session(Session session) {
|
||||||
|
this.session = session;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SessionWithToken#getHref
|
||||||
|
*/
|
||||||
|
public Builder token(String token) {
|
||||||
|
this.token = token;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionWithToken build() {
|
||||||
|
return new SessionWithToken(token, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Builder fromSessionWithToken(SessionWithToken in) {
|
||||||
|
return session(in.getSession()).token(in.getToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Session session;
|
||||||
|
protected String token;
|
||||||
|
|
||||||
|
protected SessionWithToken(String token, Session session) {
|
||||||
|
this.session = session;
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SessionWithToken() {
|
||||||
|
// For JAXB
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
public Session getSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object reference, expressed in URL format. Because this URL includes the object identifier
|
||||||
|
* portion of the id attribute value, it uniquely identifies the object, persists for the life of
|
||||||
|
* the object, and is never reused. The value of the token attribute is a reference to a view of
|
||||||
|
* the object, and can be used to access a representation of the object that is valid in a
|
||||||
|
* particular context. Although URLs have a well-known syntax and a well-understood
|
||||||
|
* interpretation, a client should treat each token as an opaque string. The rules that govern
|
||||||
|
* how the server constructs token strings might change in future releases.
|
||||||
|
*
|
||||||
|
* @return an opaque reference and should never be parsed
|
||||||
|
*/
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
SessionWithToken that = SessionWithToken.class.cast(o);
|
||||||
|
return equal(token, that.token) && equal(session, that.session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(session, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Objects.toStringHelper("").add("session", session).add("token", token).toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package org.jclouds.vcloud.director.v1_5.filters;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpException;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpRequestFilter;
|
||||||
|
import org.jclouds.http.utils.ModifyRequest;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.annotations.Session;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AddVCloudAuthorizationToRequest implements HttpRequestFilter {
|
||||||
|
|
||||||
|
private final Supplier<String> sessionSupplier;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AddVCloudAuthorizationToRequest(@Session Supplier<String> sessionSupplier) {
|
||||||
|
this.sessionSupplier = sessionSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpRequest filter(HttpRequest request) throws HttpException {
|
||||||
|
return ModifyRequest.replaceHeader(request, "x-vcloud-authorization", sessionSupplier.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.functions;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.annotations.Login;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.login.SessionClient;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class LoginUserInOrgWithPassword implements Function<Credentials, SessionWithToken> {
|
||||||
|
private final SessionClient client;
|
||||||
|
private final Supplier<URI> loginUrl;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public LoginUserInOrgWithPassword(SessionClient client, @Login Supplier<URI> loginUrl) {
|
||||||
|
this.client = client;
|
||||||
|
this.loginUrl = loginUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionWithToken apply(Credentials input) {
|
||||||
|
String user = input.identity.substring(0, input.identity.lastIndexOf('@'));
|
||||||
|
String org = input.identity.substring(input.identity.lastIndexOf('@') + 1);
|
||||||
|
String password = input.credential;
|
||||||
|
|
||||||
|
return client.loginUserInOrgWithPassword(loginUrl.get(), user, org, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "loginUserInOrgWithPassword()";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.handlers;
|
||||||
|
|
||||||
|
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
|
||||||
|
import static org.jclouds.http.HttpUtils.releasePayload;
|
||||||
|
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.http.HttpCommand;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.login.SessionClient;
|
||||||
|
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the credentials supplied in the authentication header are invalid, or if the token has
|
||||||
|
* expired, the server returns HTTP response code 401. The token expires after a configurable
|
||||||
|
* interval of client inactivity. The default is 30 minutes after the token is created. After the
|
||||||
|
* token expires, you must log in again to obtain a new token.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class InvalidateSessionAndRetryOn401AndLogoutOnClose extends BackoffLimitedRetryHandler {
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final LoadingCache<Credentials, SessionWithToken> authenticationResponseCache;
|
||||||
|
private final SessionClient sessionClient;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected InvalidateSessionAndRetryOn401AndLogoutOnClose(
|
||||||
|
LoadingCache<Credentials, SessionWithToken> authenticationResponseCache, SessionClient sessionClient) {
|
||||||
|
this.authenticationResponseCache = authenticationResponseCache;
|
||||||
|
this.sessionClient = sessionClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
|
||||||
|
boolean retry = false; // default
|
||||||
|
try {
|
||||||
|
if (response.getStatusCode() == 401) {
|
||||||
|
closeClientButKeepContentStream(response);
|
||||||
|
logger.debug("invalidating session");
|
||||||
|
authenticationResponseCache.invalidateAll();
|
||||||
|
retry = super.shouldRetryRequest(command, response);
|
||||||
|
}
|
||||||
|
return retry;
|
||||||
|
} finally {
|
||||||
|
releasePayload(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* it is important that we close any sessions on close to help the server not become overloaded.
|
||||||
|
*/
|
||||||
|
@PreDestroy
|
||||||
|
public void logoutOnClose() {
|
||||||
|
for (SessionWithToken s : authenticationResponseCache.asMap().values()) {
|
||||||
|
try {
|
||||||
|
sessionClient.logoutSessionWithToken(s.getSession().getHref(), s.getToken());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e, "error logging out session %s", s.getSession());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.handlers;
|
||||||
|
|
||||||
|
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
|
||||||
|
|
||||||
|
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.rest.AuthorizationException;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will parse and set an appropriate exception on the command object.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//TODO: is there error spec someplace? let's type errors, etc.
|
||||||
|
@Singleton
|
||||||
|
public class VCloudDirectorErrorHandler implements HttpErrorHandler {
|
||||||
|
|
||||||
|
public void handleError(HttpCommand command, HttpResponse response) {
|
||||||
|
// it is important to always read fully and close streams
|
||||||
|
byte[] data = closeClientButKeepContentStream(response);
|
||||||
|
String message = data != null ? new String(data) : null;
|
||||||
|
|
||||||
|
Exception exception = message != null ? new HttpResponseException(command, response, message)
|
||||||
|
: new HttpResponseException(command, response);
|
||||||
|
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
|
||||||
|
response.getStatusLine());
|
||||||
|
switch (response.getStatusCode()) {
|
||||||
|
case 401:
|
||||||
|
case 403:
|
||||||
|
exception = new AuthorizationException(message, exception);
|
||||||
|
break;
|
||||||
|
case 404:
|
||||||
|
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
|
||||||
|
exception = new ResourceNotFoundException(message, exception);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exception = new HttpResponseException(command, response, message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
command.setException(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.login;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.HeaderParam;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
|
||||||
|
import org.jclouds.rest.annotations.EndpointParam;
|
||||||
|
import org.jclouds.rest.annotations.JAXBResponseParser;
|
||||||
|
import org.jclouds.rest.annotations.MapBinder;
|
||||||
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
|
import org.jclouds.rest.annotations.ResponseParser;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.binders.BindUserOrgAndPasswordAsBasicAuthorizationHeader;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.Session;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.parsers.SessionWithTokenFromXMLAndHeader;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Session via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @see SessionClient
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public interface SessionAsyncClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SessionClient#loginUserInOrgWithPassword
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Consumes
|
||||||
|
@ResponseParser(SessionWithTokenFromXMLAndHeader.class)
|
||||||
|
@MapBinder(BindUserOrgAndPasswordAsBasicAuthorizationHeader.class)
|
||||||
|
ListenableFuture<SessionWithToken> loginUserInOrgWithPassword(@EndpointParam URI loginUrl,
|
||||||
|
@PayloadParam("user") String user, @PayloadParam("org") String org,
|
||||||
|
@PayloadParam("password") String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SessionClient#getSessionWithToken
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Consumes
|
||||||
|
@JAXBResponseParser
|
||||||
|
ListenableFuture<Session> getSessionWithToken(@EndpointParam URI session,
|
||||||
|
@HeaderParam("x-vcloud-authorization") String authenticationToken);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see SessionClient#logoutSessionWithToken
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Consumes
|
||||||
|
@JAXBResponseParser
|
||||||
|
ListenableFuture<Void> logoutSessionWithToken(@EndpointParam URI session,
|
||||||
|
@HeaderParam("x-vcloud-authorization") String authenticationToken);
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.login;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.Session;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Session.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @see SessionAsyncClient
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
||||||
|
public interface SessionClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
SessionWithToken loginUserInOrgWithPassword(URI loginUrl, String user, String org, String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
Session getSessionWithToken(URI session, String authenticationToken);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
void logoutSessionWithToken(URI session, String authenticationToken);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.parsers;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.functions.ParseXMLWithJAXB;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.Session;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class SessionWithTokenFromXMLAndHeader implements Function<HttpResponse, SessionWithToken> {
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
private ParseXMLWithJAXB<Session> sessionParser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public SessionWithTokenFromXMLAndHeader(ParseXMLWithJAXB<Session> sessionParser) {
|
||||||
|
this.sessionParser = sessionParser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionWithToken apply(final HttpResponse from) {
|
||||||
|
Session session = sessionParser.apply(from);
|
||||||
|
return SessionWithToken.builder().session(session).token(from.getFirstHeaderOrNull("x-vcloud-authorization"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorRestClientExpectTest;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.login.SessionClientExpectTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "VCloudDirectorClient")
|
||||||
|
public class VCloudDirectorClientExpectTest extends BaseVCloudDirectorRestClientExpectTest {
|
||||||
|
|
||||||
|
public void testRestClientModuleWorksProperly() throws Exception {
|
||||||
|
|
||||||
|
VCloudDirectorClient clientWhenSessionsExist = requestSendsResponse(loginRequest, sessionResponse);
|
||||||
|
|
||||||
|
assertEquals(clientWhenSessionsExist.getCurrentSession(), SessionClientExpectTest.SESSION);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.handlers;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.createMock;
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.EasyMock.expectLastCall;
|
||||||
|
import static org.easymock.EasyMock.replay;
|
||||||
|
import static org.easymock.EasyMock.verify;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.http.HttpCommand;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.login.SessionClient;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code InvalidateSessionAndRetryOn401AndLogoutOnClose} handler
|
||||||
|
*
|
||||||
|
* @author grkvlt@apache.org
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "InvalidateSessionAndRetryOn401AndLogoutOnCloseTest")
|
||||||
|
public class InvalidateSessionAndRetryOn401AndLogoutOnCloseTest {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void test401ShouldInvalidateSessionAndRetry() {
|
||||||
|
HttpCommand command = createMock(HttpCommand.class);
|
||||||
|
SessionClient sessionClient = createMock(SessionClient.class);
|
||||||
|
LoadingCache<Credentials, SessionWithToken> cache = createMock(LoadingCache.class);
|
||||||
|
|
||||||
|
cache.invalidateAll();
|
||||||
|
expectLastCall();
|
||||||
|
expect(command.incrementFailureCount()).andReturn(1);
|
||||||
|
expect(command.isReplayable()).andReturn(true);
|
||||||
|
expect(command.getFailureCount()).andReturn(1).atLeastOnce();
|
||||||
|
|
||||||
|
replay(cache, command);
|
||||||
|
|
||||||
|
HttpResponse response = HttpResponse.builder().statusCode(401).build();
|
||||||
|
|
||||||
|
InvalidateSessionAndRetryOn401AndLogoutOnClose retry = new InvalidateSessionAndRetryOn401AndLogoutOnClose(cache,
|
||||||
|
sessionClient);
|
||||||
|
|
||||||
|
assertTrue(retry.shouldRetryRequest(command, response));
|
||||||
|
|
||||||
|
verify(cache, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void test403ShouldNotInvalidateSessionOrRetry() {
|
||||||
|
HttpCommand command = createMock(HttpCommand.class);
|
||||||
|
SessionClient sessionClient = createMock(SessionClient.class);
|
||||||
|
LoadingCache<Credentials, SessionWithToken> cache = createMock(LoadingCache.class);
|
||||||
|
|
||||||
|
replay(cache, command);
|
||||||
|
|
||||||
|
HttpResponse response = HttpResponse.builder().statusCode(403).build();
|
||||||
|
|
||||||
|
InvalidateSessionAndRetryOn401AndLogoutOnClose retry = new InvalidateSessionAndRetryOn401AndLogoutOnClose(cache,
|
||||||
|
sessionClient);
|
||||||
|
|
||||||
|
assertFalse(retry.shouldRetryRequest(command, response));
|
||||||
|
|
||||||
|
verify(cache, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.handlers;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.createMock;
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.EasyMock.replay;
|
||||||
|
import static org.easymock.EasyMock.reportMatcher;
|
||||||
|
import static org.easymock.EasyMock.verify;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.easymock.IArgumentMatcher;
|
||||||
|
import org.jclouds.http.HttpCommand;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.io.Payloads;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.handlers.VCloudDirectorErrorHandler;
|
||||||
|
import org.jclouds.rest.AuthorizationException;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = { "unit" })
|
||||||
|
public class VCloudDirectorErrorHandlerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test401MakesAuthorizationException() {
|
||||||
|
assertCodeMakes("GET", URI.create("https://api.vcloud.director.com/foo"), 401, "", "Unauthorized",
|
||||||
|
AuthorizationException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test404MakesResourceNotFoundException() {
|
||||||
|
assertCodeMakes("GET", URI.create("https://api.vcloud.director.com/foo"), 404, "", "Not Found",
|
||||||
|
ResourceNotFoundException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
|
||||||
|
Class<? extends Exception> expected) {
|
||||||
|
assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
|
||||||
|
String content, Class<? extends Exception> expected) {
|
||||||
|
|
||||||
|
VCloudDirectorErrorHandler function = Guice.createInjector().getInstance(VCloudDirectorErrorHandler.class);
|
||||||
|
|
||||||
|
HttpCommand command = createMock(HttpCommand.class);
|
||||||
|
HttpRequest request = new HttpRequest(method, uri);
|
||||||
|
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Strings2
|
||||||
|
.toInputStream(content)));
|
||||||
|
response.getPayload().getContentMetadata().setContentType(contentType);
|
||||||
|
|
||||||
|
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
|
||||||
|
command.setException(classEq(expected));
|
||||||
|
|
||||||
|
replay(command);
|
||||||
|
|
||||||
|
function.handleError(command, response);
|
||||||
|
|
||||||
|
verify(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Exception classEq(final Class<? extends Exception> in) {
|
||||||
|
reportMatcher(new IArgumentMatcher() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendTo(StringBuffer buffer) {
|
||||||
|
buffer.append("classEq(");
|
||||||
|
buffer.append(in);
|
||||||
|
buffer.append(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Object arg) {
|
||||||
|
return arg.getClass() == in;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.internal;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.compute.BaseVersionedServiceLiveTest;
|
||||||
|
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.VCloudDirectorAsyncClient;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
|
||||||
|
import org.jclouds.rest.RestContext;
|
||||||
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
import org.jclouds.sshj.config.SshjSshClientModule;
|
||||||
|
import org.testng.annotations.AfterGroups;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code VCloudDirectorClient}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "live")
|
||||||
|
public class BaseVCloudDirectorClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
|
public BaseVCloudDirectorClientLiveTest() {
|
||||||
|
provider = "vcloud-director";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RestContext<VCloudDirectorClient, VCloudDirectorAsyncClient> context;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = { "live" })
|
||||||
|
public void setupClient() {
|
||||||
|
setupCredentials();
|
||||||
|
Properties overrides = setupProperties();
|
||||||
|
context = new RestContextFactory().createContext(provider, identity, credential,
|
||||||
|
ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule()), overrides);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterGroups(groups = "live")
|
||||||
|
protected void tearDown() {
|
||||||
|
if (context != null)
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.vcloud.director.v1_5.internal;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.rest.BaseRestClientExpectTest;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.VCloudDirectorClient;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for writing KeyStone Rest Client Expect tests
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class BaseVCloudDirectorRestClientExpectTest extends BaseRestClientExpectTest<VCloudDirectorClient> {
|
||||||
|
|
||||||
|
public static final String user = "adrian@jclouds.org";
|
||||||
|
public static final String org = "JClouds";
|
||||||
|
public static final String password = "password";
|
||||||
|
public static final String token = "mIaR3/6Lna8DWImd7/JPR5rK8FcUHabt+G/UCJV5pJQ=";
|
||||||
|
|
||||||
|
protected HttpRequest loginRequest = HttpRequest.builder().method("POST").endpoint(
|
||||||
|
URI.create("http://localhost/api/sessions")).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "*/*").put("Authorization",
|
||||||
|
"Basic YWRyaWFuQGpjbG91ZHMub3JnQEpDbG91ZHM6cGFzc3dvcmQ=").build()).build();
|
||||||
|
|
||||||
|
protected HttpResponse sessionResponse = HttpResponse.builder().statusCode(200).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("x-vcloud-authorization", token).put("Set-Cookie",
|
||||||
|
String.format("vcloud-token=%s; Secure; Path=/", token)).build()).payload(
|
||||||
|
payloadFromResourceWithContentType("/session.xml", VCloudDirectorMediaType.SESSION_XML + ";version=1.5"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public BaseVCloudDirectorRestClientExpectTest() {
|
||||||
|
provider = "vcloud-director";
|
||||||
|
identity = String.format("%s@%s", user, org);
|
||||||
|
credential = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
*(Link.builder().regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless(Link.builder().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.vcloud.director.v1_5.login;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.rest.BaseRestClientExpectTest;
|
||||||
|
import org.jclouds.rest.BaseRestClientExpectTest.RegisterContext;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.Link;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.Session;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Allows us to test a client via its side effects.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "SessionClientExpectTest")
|
||||||
|
// only needed as SessionClient is not(Link.builder().registered in(Link.builder().rest.properties
|
||||||
|
@RegisterContext(sync = SessionClient.class, async = SessionAsyncClient.class)
|
||||||
|
public class SessionClientExpectTest extends BaseRestClientExpectTest<SessionClient> {
|
||||||
|
public static final String user = "adrian@jclouds.org";
|
||||||
|
public static final String org = "JClouds";
|
||||||
|
public static final Session SESSION = Session.builder().user(user).org(org).href(
|
||||||
|
URI.create("https://vcloudbeta.bluelock.com/api/session/")).addLink(
|
||||||
|
Link.builder().rel("down").type("application/vnd.vmware.vcloud.orgList+xml").href(
|
||||||
|
URI.create("https://vcloudbeta.bluelock.com/api/org/")).build()).addLink(
|
||||||
|
Link.builder().rel("down").type("application/vnd.vmware.admin.vcloud+xml").href(
|
||||||
|
URI.create("https://vcloudbeta.bluelock.com/api/admin/")).build()).addLink(
|
||||||
|
Link.builder().rel("down").type("application/vnd.vmware.vcloud.query.queryList+xml").href(
|
||||||
|
URI.create("https://vcloudbeta.bluelock.com/api/query")).build()).addLink(
|
||||||
|
Link.builder().rel("entityResolver").type("application/vnd.vmware.vcloud.entity+xml").href(
|
||||||
|
URI.create("https://vcloudbeta.bluelock.com/api/entity/")).build()).build();
|
||||||
|
|
||||||
|
public void testWhenResponseIs2xxLoginReturnsValidSession() {
|
||||||
|
URI loginUrl = URI.create("https://vcloudbeta.bluelock.com/api/sessions");
|
||||||
|
|
||||||
|
String token = "mIaR3/6Lna8DWImd7/JPR5rK8FcUHabt+G/UCJV5pJQ=";
|
||||||
|
|
||||||
|
SessionClient client = requestSendsResponse(
|
||||||
|
|
||||||
|
HttpRequest.builder().method("POST").endpoint(loginUrl).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("Accept", "*/*").put("Authorization",
|
||||||
|
"Basic YWRyaWFuQGpjbG91ZHMub3JnQEpDbG91ZHM6cGFzc3dvcmQ=").build()).build(),
|
||||||
|
|
||||||
|
HttpResponse.builder().statusCode(200).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("x-vcloud-authorization", token).put("Set-Cookie",
|
||||||
|
String.format("vcloud-token=%s; Secure; Path=/", token)).build())
|
||||||
|
.payload(
|
||||||
|
payloadFromResourceWithContentType("/session.xml", VCloudDirectorMediaType.SESSION_XML
|
||||||
|
+ ";version=1.5")).build()
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(client.loginUserInOrgWithPassword(loginUrl, user, org, "password"), SessionWithToken.builder()
|
||||||
|
.session(SESSION)
|
||||||
|
|
||||||
|
.token(token).build());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWhenResponseIs2xxGetSessionReturnsValidSession() {
|
||||||
|
URI sessionUrl = URI.create("https://vcloudbeta.bluelock.com/api/session");
|
||||||
|
|
||||||
|
String token = "mIaR3/6Lna8DWImd7/JPR5rK8FcUHabt+G/UCJV5pJQ=";
|
||||||
|
|
||||||
|
SessionClient client = requestSendsResponse(
|
||||||
|
|
||||||
|
HttpRequest.builder().method("GET").endpoint(sessionUrl).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("x-vcloud-authorization", token).put("Accept", "*/*")
|
||||||
|
.build()).build(),
|
||||||
|
|
||||||
|
HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(
|
||||||
|
payloadFromResourceWithContentType("/session.xml", VCloudDirectorMediaType.SESSION_XML
|
||||||
|
+ ";version=1.5")).build()
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(client.getSessionWithToken(sessionUrl, token), SESSION);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLogoutWhenResponseIs2xx() {
|
||||||
|
URI sessionUrl = URI.create("https://vcloudbeta.bluelock.com/api/session");
|
||||||
|
|
||||||
|
String token = "mIaR3/6Lna8DWImd7/JPR5rK8FcUHabt+G/UCJV5pJQ=";
|
||||||
|
|
||||||
|
SessionClient client = requestSendsResponse(
|
||||||
|
|
||||||
|
HttpRequest.builder().method("DELETE").endpoint(sessionUrl).headers(
|
||||||
|
ImmutableMultimap.<String, String> builder().put("x-vcloud-authorization", token).put("Accept", "*/*")
|
||||||
|
.build()).build(),
|
||||||
|
|
||||||
|
HttpResponse.builder().statusCode(204).build()
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
client.logoutSessionWithToken(sessionUrl, token);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
*(Link.builder().regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless(Link.builder().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.vcloud.director.v1_5.login;
|
||||||
|
|
||||||
|
import static org.jclouds.rest.RestContextFactory.contextSpec;
|
||||||
|
import static org.jclouds.rest.RestContextFactory.createContextBuilder;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.compute.BaseVersionedServiceLiveTest;
|
||||||
|
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
|
||||||
|
import org.jclouds.rest.RestContext;
|
||||||
|
import org.jclouds.rest.RestContextSpec;
|
||||||
|
import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
|
||||||
|
import org.testng.annotations.AfterGroups;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code SessionClient}. Note this class is tested completely independently of
|
||||||
|
* VCloudClient as it is a dependency of the VCloud context working.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = { "live", "apitests" }, testName = "SessionClientLiveTest")
|
||||||
|
public class SessionClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
|
public SessionClientLiveTest() {
|
||||||
|
provider = "vcloud-director";
|
||||||
|
}
|
||||||
|
|
||||||
|
private RestContext<SessionClient, SessionAsyncClient> context;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = { "live" })
|
||||||
|
public void setupClient() {
|
||||||
|
setupCredentials();
|
||||||
|
Properties overrides = setupProperties();
|
||||||
|
RestContextSpec<SessionClient, SessionAsyncClient> contextSpec = contextSpec("vcloud-director", endpoint,
|
||||||
|
apiVersion, buildVersion, "", identity, credential, SessionClient.class, SessionAsyncClient.class);
|
||||||
|
|
||||||
|
context = createContextBuilder(contextSpec, overrides).withModules(
|
||||||
|
ImmutableSet.<Module> of(new SLF4JLoggingModule())).buildContext();
|
||||||
|
|
||||||
|
// session client isn't typically exposed to the user, as it is implicit
|
||||||
|
client = context.utils().injector().getInstance(SessionClient.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SessionClient client;
|
||||||
|
private SessionWithToken sessionWithToken;
|
||||||
|
|
||||||
|
@Test(testName = "POST /sessions")
|
||||||
|
public void testLogin() {
|
||||||
|
String user = identity.substring(0, identity.lastIndexOf('@'));
|
||||||
|
String org = identity.substring(identity.lastIndexOf('@') + 1);
|
||||||
|
String password = credential;
|
||||||
|
|
||||||
|
sessionWithToken = client.loginUserInOrgWithPassword(URI.create(endpoint + "/sessions"), user, org, password);
|
||||||
|
assertEquals(sessionWithToken.getSession().getUser(), user);
|
||||||
|
assertEquals(sessionWithToken.getSession().getOrg(), org);
|
||||||
|
assertTrue(sessionWithToken.getSession().getLinks().size() > 0);
|
||||||
|
assertNotNull(sessionWithToken.getToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(testName = "GET /session", dependsOnMethods = "testLogin")
|
||||||
|
public void testGetSession() {
|
||||||
|
assertEquals(client.getSessionWithToken(sessionWithToken.getSession().getHref(), sessionWithToken.getToken()),
|
||||||
|
sessionWithToken.getSession());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(testName = "DELETE /session", dependsOnMethods = "testGetSession")
|
||||||
|
public void testLogout() {
|
||||||
|
client.logoutSessionWithToken(sessionWithToken.getSession().getHref(), sessionWithToken.getToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterGroups(groups = "live")
|
||||||
|
protected void tearDown() {
|
||||||
|
if (context != null)
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<configuration scan="false">
|
||||||
|
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<file>target/test-data/jclouds.log</file>
|
||||||
|
|
||||||
|
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||||
|
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<file>target/test-data/jclouds-wire.log</file>
|
||||||
|
|
||||||
|
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||||
|
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<file>target/test-data/jclouds-compute.log</file>
|
||||||
|
|
||||||
|
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||||
|
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="SSHFILE" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<file>target/test-data/jclouds-ssh.log</file>
|
||||||
|
|
||||||
|
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||||
|
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root>
|
||||||
|
<level value="warn" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<logger name="org.jclouds">
|
||||||
|
<level value="DEBUG" />
|
||||||
|
<appender-ref ref="FILE" />
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="jclouds.wire">
|
||||||
|
<level value="DEBUG" />
|
||||||
|
<appender-ref ref="WIREFILE" />
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="jclouds.headers">
|
||||||
|
<level value="DEBUG" />
|
||||||
|
<appender-ref ref="WIREFILE" />
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="jclouds.compute">
|
||||||
|
<level value="DEBUG" />
|
||||||
|
<appender-ref ref="COMPUTEFILE" />
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="jclouds.ssh">
|
||||||
|
<level value="DEBUG" />
|
||||||
|
<appender-ref ref="SSHFILE" />
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
</configuration>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Session xmlns="http://www.vmware.com/vcloud/v1.5" user="adrian@jclouds.org" org="JClouds" type="application/vnd.vmware.vcloud.session+xml" href="https://vcloudbeta.bluelock.com/api/session/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://vcloudbeta.bluelock.com/api/v1.5/schema/master.xsd">
|
||||||
|
<Link rel="down" type="application/vnd.vmware.vcloud.orgList+xml" href="https://vcloudbeta.bluelock.com/api/org/"/>
|
||||||
|
<Link rel="down" type="application/vnd.vmware.admin.vcloud+xml" href="https://vcloudbeta.bluelock.com/api/admin/"/>
|
||||||
|
<Link rel="down" type="application/vnd.vmware.vcloud.query.queryList+xml" href="https://vcloudbeta.bluelock.com/api/query"/>
|
||||||
|
<Link rel="entityResolver" type="application/vnd.vmware.vcloud.entity+xml" href="https://vcloudbeta.bluelock.com/api/entity/"/>
|
||||||
|
</Session>
|
Loading…
Reference in New Issue