Issue 230: corrected URI parsing so that we can access ibm image manifests

This commit is contained in:
Adrian Cole 2010-06-09 22:46:25 -07:00
parent ab5e8b3ab4
commit 50b1aa3cae
7 changed files with 114 additions and 37 deletions

View File

@ -250,10 +250,16 @@ public class HttpUtils {
/** /**
* Used to extract the URI and authentication data from a String. Note that the java URI class * Used to extract the URI and authentication data from a String. Note that the java URI class
* breaks, if there are special characters like '/' present. Otherwise, we wouldn't need this * breaks, if there are special characters like '/' present. Otherwise, we wouldn't need this
* class, and we could simply use URI.create("uri").getUserData(); * class, and we could simply use URI.create("uri").getUserData(); Also, URI breaks if there
* are curly braces.
* *
*/ */
public static URI createUri(String uriPath) { public static URI createUri(String uriPath) {
List<String> onQuery = Lists.newArrayList(Splitter.on('?').split(uriPath));
if (onQuery.size() == 2){
onQuery.add(urlEncode(onQuery.remove(1), '=','&'));
uriPath = Joiner.on('?').join(onQuery);
}
if (uriPath.indexOf('@') != 1) { if (uriPath.indexOf('@') != 1) {
List<String> parts = Lists.newArrayList(Splitter.on('@').split(uriPath)); List<String> parts = Lists.newArrayList(Splitter.on('@').split(uriPath));
String path = parts.remove(parts.size() - 1); String path = parts.remove(parts.size() - 1);

View File

@ -45,6 +45,12 @@ public class HttpUtilsTest extends PerformanceTest {
assertEquals(HttpUtils.urlEncode("/read-tests/ tep", '/'), "/read-tests/%20tep"); assertEquals(HttpUtils.urlEncode("/read-tests/ tep", '/'), "/read-tests/%20tep");
} }
public void testIBM() {
URI ibm = HttpUtils
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram/assetDetail/generalDetails.faces?guid={A31FF849-0E97-431A-0324-097385A46298}&v=1.2");
assertEquals(ibm.getQuery(), "guid={A31FF849-0E97-431A-0324-097385A46298}&v=1.2");
}
public void testAtmos() { public void testAtmos() {
URI creds = HttpUtils URI creds = HttpUtils
.createUri("compute://domain/user:Base64==@azureblob/container-hyphen/prefix"); .createUri("compute://domain/user:Base64==@azureblob/container-hyphen/prefix");

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.ibmdev.config;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Map;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.config.ParserModule.DateAdapter;
import org.jclouds.http.functions.config.ParserModule.LongDateAdapter;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
*
*
* @author Adrian Cole
*/
public class IBMDeveloperCloudParserModule extends AbstractModule {
@Singleton
public static class CurlyBraceCapableURIAdapter implements JsonDeserializer<URI> {
@Override
public URI deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context)
throws JsonParseException {
String toParse = jsonElement.getAsJsonPrimitive().getAsString();
URI toReturn = HttpUtils.createUri(toParse);
return toReturn;
}
}
@SuppressWarnings("unchecked")
@Provides
@Singleton
@Named(Constants.PROPERTY_GSON_ADAPTERS)
public Map<Class, Object> provideCustomAdapterBindings(CurlyBraceCapableURIAdapter adapter) {
return ImmutableMap.<Class, Object> of(URI.class, adapter);
}
@Override
protected void configure() {
bind(DateAdapter.class).to(LongDateAdapter.class);
}
}

View File

@ -32,8 +32,6 @@ import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError; import org.jclouds.http.annotation.ServerError;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.functions.config.ParserModule.DateAdapter;
import org.jclouds.http.functions.config.ParserModule.LongDateAdapter;
import org.jclouds.ibmdev.IBMDeveloperCloud; import org.jclouds.ibmdev.IBMDeveloperCloud;
import org.jclouds.ibmdev.IBMDeveloperCloudAsyncClient; import org.jclouds.ibmdev.IBMDeveloperCloudAsyncClient;
import org.jclouds.ibmdev.IBMDeveloperCloudClient; import org.jclouds.ibmdev.IBMDeveloperCloudClient;
@ -63,6 +61,7 @@ public class IBMDeveloperCloudRestClientModule extends
super(IBMDeveloperCloudClient.class, IBMDeveloperCloudAsyncClient.class); super(IBMDeveloperCloudClient.class, IBMDeveloperCloudAsyncClient.class);
} }
@Provides @Provides
@Singleton @Singleton
public BasicAuthentication provideBasicAuthentication( public BasicAuthentication provideBasicAuthentication(
@ -92,7 +91,7 @@ public class IBMDeveloperCloudRestClientModule extends
@Override @Override
protected void configure() { protected void configure() {
bind(DateAdapter.class).to(LongDateAdapter.class); install(new IBMDeveloperCloudParserModule());
super.configure(); super.configure();
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.ibmdev.domain; package org.jclouds.ibmdev.domain;
import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.Set; import java.util.Set;
@ -61,10 +62,8 @@ public class Image {
} }
private String name; private String name;
/**
* Note that this isn't a URI, as parsing fails due to IBM including '{' characters in the path. private URI manifest;
*/
private String manifest;
private int state; private int state;
private Visibility visibility; private Visibility visibility;
private String owner; private String owner;
@ -74,10 +73,7 @@ public class Image {
private String location; private String location;
private Set<String> supportedInstanceTypes = Sets.newLinkedHashSet(); private Set<String> supportedInstanceTypes = Sets.newLinkedHashSet();
private Set<String> productCodes = Sets.newLinkedHashSet(); private Set<String> productCodes = Sets.newLinkedHashSet();
/** private URI documentation;
* Note that this isn't a URI, as parsing fails due to IBM including '{' characters in the path.
*/
private String documentation;
private String id; private String id;
private String description; private String description;
@ -89,11 +85,11 @@ public class Image {
this.name = name; this.name = name;
} }
public String getManifest() { public URI getManifest() {
return manifest; return manifest;
} }
public void setManifest(String manifest) { public void setManifest(URI manifest) {
this.manifest = manifest; this.manifest = manifest;
} }
@ -169,11 +165,11 @@ public class Image {
this.productCodes = productCodes; this.productCodes = productCodes;
} }
public String getDocumentation() { public URI getDocumentation() {
return documentation; return documentation;
} }
public void setDocumentation(String documentation) { public void setDocumentation(URI documentation) {
this.documentation = documentation; this.documentation = documentation;
} }

View File

@ -25,7 +25,9 @@ import java.io.IOException;
import java.util.Date; import java.util.Date;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.config.ParserModule; import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.ibmdev.config.IBMDeveloperCloudParserModule;
import org.jclouds.ibmdev.domain.Image; import org.jclouds.ibmdev.domain.Image;
import org.jclouds.ibmdev.domain.Image.Visibility; import org.jclouds.ibmdev.domain.Image.Visibility;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
@ -47,13 +49,8 @@ public class ParseImageFromJsonTest {
@BeforeTest @BeforeTest
protected void setUpInjector() throws IOException { protected void setUpInjector() throws IOException {
Injector injector = Guice.createInjector(new ParserModule() { Injector injector = Guice.createInjector(new ParserModule(),
@Override new IBMDeveloperCloudParserModule());
protected void configure() {
bind(DateAdapter.class).to(LongDateAdapter.class);
super.configure();
}
});
handler = injector.getInstance(ParseImageFromJson.class); handler = injector.getInstance(ParseImageFromJson.class);
} }
@ -62,7 +59,8 @@ public class ParseImageFromJsonTest {
Image image = new Image(); Image image = new Image();
image.setName("Rational Requirements Composer"); image.setName("Rational Requirements Composer");
image image
.setManifest("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/parameters.xml"); .setManifest(HttpUtils
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/parameters.xml"));
image.setState(1); image.setState(1);
image.setVisibility(Visibility.PUBLIC); image.setVisibility(Visibility.PUBLIC);
image.setOwner("mutdosch@us.ibm.com"); image.setOwner("mutdosch@us.ibm.com");
@ -73,7 +71,8 @@ public class ParseImageFromJsonTest {
image.setSupportedInstanceTypes(ImmutableSet.of("LARGE", "MEDIUM")); image.setSupportedInstanceTypes(ImmutableSet.of("LARGE", "MEDIUM"));
// image.setProductCodes(); // image.setProductCodes();
image image
.setDocumentation("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/GettingStarted.html"); .setDocumentation(HttpUtils
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/GettingStarted.html"));
image.setId("10005598"); image.setId("10005598");
image image
.setDescription("Rational Requirements Composer helps teams define and use requirements effectively across the project lifecycle."); .setDescription("Rational Requirements Composer helps teams define and use requirements effectively across the project lifecycle.");

View File

@ -24,7 +24,9 @@ import java.util.Date;
import java.util.Set; import java.util.Set;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.config.ParserModule; import org.jclouds.http.functions.config.ParserModule;
import org.jclouds.ibmdev.config.IBMDeveloperCloudParserModule;
import org.jclouds.ibmdev.domain.Image; import org.jclouds.ibmdev.domain.Image;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -45,13 +47,8 @@ public class ParseImagesFromJsonTest {
@BeforeTest @BeforeTest
protected void setUpInjector() throws IOException { protected void setUpInjector() throws IOException {
Injector injector = Guice.createInjector(new ParserModule() { Injector injector = Guice.createInjector(new ParserModule(),
@Override new IBMDeveloperCloudParserModule());
protected void configure() {
bind(DateAdapter.class).to(LongDateAdapter.class);
super.configure();
}
});
handler = injector.getInstance(ParseImagesFromJson.class); handler = injector.getInstance(ParseImagesFromJson.class);
} }
@ -60,7 +57,8 @@ public class ParseImagesFromJsonTest {
image1.setName("Rational Build Forge Agent"); image1.setName("Rational Build Forge Agent");
image1 image1
.setManifest("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{A233F5A0-05A5-F21D-3E92-3793B722DFBD}/1.0/parameters.xml"); .setManifest(HttpUtils
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{A233F5A0-05A5-F21D-3E92-3793B722DFBD}/1.0/parameters.xml"));
image1.setState(1); image1.setState(1);
image1.setVisibility(Image.Visibility.PUBLIC); image1.setVisibility(Image.Visibility.PUBLIC);
image1.setOwner("SYSTEM"); image1.setOwner("SYSTEM");
@ -71,7 +69,8 @@ public class ParseImagesFromJsonTest {
image1.setSupportedInstanceTypes(ImmutableSet.of("SMALL", "MEDIUM", "LARGE")); image1.setSupportedInstanceTypes(ImmutableSet.of("SMALL", "MEDIUM", "LARGE"));
image1.setProductCodes(ImmutableSet.of("fd2d0478b132490897526b9b4433a334")); image1.setProductCodes(ImmutableSet.of("fd2d0478b132490897526b9b4433a334"));
image1 image1
.setDocumentation("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{A233F5A0-05A5-F21D-3E92-3793B722DFBD}/1.0/GettingStarted.html"); .setDocumentation(HttpUtils
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{A233F5A0-05A5-F21D-3E92-3793B722DFBD}/1.0/GettingStarted.html"));
image1.setId("2"); image1.setId("2");
image1 image1
.setDescription("Rational Build Forge provides an adaptive process execution framework that automates, orchestrates, manages, and tracks all the processes between each handoff within the assembly line of software development, creating an automated software factory."); .setDescription("Rational Build Forge provides an adaptive process execution framework that automates, orchestrates, manages, and tracks all the processes between each handoff within the assembly line of software development, creating an automated software factory.");
@ -79,7 +78,8 @@ public class ParseImagesFromJsonTest {
Image image2 = new Image(); Image image2 = new Image();
image2.setName("Rational Requirements Composer"); image2.setName("Rational Requirements Composer");
image2 image2
.setManifest("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/parameters.xml"); .setManifest(HttpUtils
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/parameters.xml"));
image2.setState(1); image2.setState(1);
image2.setVisibility(Image.Visibility.PUBLIC); image2.setVisibility(Image.Visibility.PUBLIC);
image2.setOwner("mutdosch@us.ibm.com"); image2.setOwner("mutdosch@us.ibm.com");
@ -90,7 +90,8 @@ public class ParseImagesFromJsonTest {
image2.setSupportedInstanceTypes(ImmutableSet.of("LARGE", "MEDIUM")); image2.setSupportedInstanceTypes(ImmutableSet.of("LARGE", "MEDIUM"));
// image.setProductCodes(); // image.setProductCodes();
image2 image2
.setDocumentation("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/GettingStarted.html"); .setDocumentation(HttpUtils
.createUri("https://www-180.ibm.com/cloud/enterprise/beta/ram.ws/RAMSecure/artifact/{28C7B870-2C0A-003F-F886-B89F5B413B77}/1.0/GettingStarted.html"));
image2.setId("10005598"); image2.setId("10005598");
image2 image2
.setDescription("Rational Requirements Composer helps teams define and use requirements effectively across the project lifecycle."); .setDescription("Rational Requirements Composer helps teams define and use requirements effectively across the project lifecycle.");