Issue 129: only use uri to get abstract services. credentials are embedded in the uri, urlencoded as necessary

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2387 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-12-09 01:56:27 +00:00
parent 8067f64990
commit 6aeb907620
23 changed files with 448 additions and 369 deletions

View File

@ -30,8 +30,8 @@ import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpConstants; import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.HttpUtils;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -49,7 +49,7 @@ public class AtmosStorageClientErrorRetryHandler implements HttpRetryHandler {
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
Utils.closeClientButKeepContentStream(response); HttpUtils.closeClientButKeepContentStream(response);
command.incrementFailureCount(); command.incrementFailureCount();
if (!command.isReplayable()) { if (!command.isReplayable()) {
logger.warn("Cannot retry after server error, command is not replayable: %1$s", command); logger.warn("Cannot retry after server error, command is not replayable: %1$s", command);

View File

@ -33,8 +33,8 @@ import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.HttpUtils;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -64,7 +64,7 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
return false; return false;
if (response.getStatusCode() == 400 || response.getStatusCode() == 403 if (response.getStatusCode() == 400 || response.getStatusCode() == 403
|| response.getStatusCode() == 409) { || response.getStatusCode() == 409) {
byte[] content = Utils.closeClientButKeepContentStream(response); byte[] content = HttpUtils.closeClientButKeepContentStream(response);
command.incrementFailureCount(); command.incrementFailureCount();
try { try {
AWSError error = utils.parseAWSErrorFromContent(command, response, new String(content)); AWSError error = utils.parseAWSErrorFromContent(command, response, new String(content));

View File

@ -33,9 +33,9 @@ import org.jclouds.aws.util.AWSUtils;
import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.http.handlers.RedirectionRetryHandler; import org.jclouds.http.handlers.RedirectionRetryHandler;
import org.jclouds.util.Utils;
/** /**
* Handles Retryable responses with error codes in the 3xx range * Handles Retryable responses with error codes in the 3xx range
@ -55,7 +55,7 @@ public class AWSRedirectionRetryHandler extends RedirectionRetryHandler {
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null
&& (response.getStatusCode() == 301 || response.getStatusCode() == 307)) { && (response.getStatusCode() == 301 || response.getStatusCode() == 307)) {
byte[] content = Utils.closeClientButKeepContentStream(response); byte[] content = HttpUtils.closeClientButKeepContentStream(response);
if (command.getRequest().getMethod() == HttpMethod.HEAD) { if (command.getRequest().getMethod() == HttpMethod.HEAD) {
command.redirectAsGet(); command.redirectAsGet();
return true; return true;

View File

@ -33,9 +33,9 @@ import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -64,7 +64,7 @@ public class AzureBlobClientErrorRetryHandler implements HttpRetryHandler {
} }
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
byte[] content = Utils.closeClientButKeepContentStream(response); byte[] content = HttpUtils.closeClientButKeepContentStream(response);
command.incrementFailureCount(); command.incrementFailureCount();
if (!command.isReplayable()) { if (!command.isReplayable()) {
logger.warn("Cannot retry after server error, command is not replayable: %1$s", command); logger.warn("Cannot retry after server error, command is not replayable: %1$s", command);

View File

@ -32,7 +32,7 @@ import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
import org.jclouds.azure.storage.blob.domain.ListableBlobProperties; import org.jclouds.azure.storage.blob.domain.ListableBlobProperties;
import org.jclouds.azure.storage.blob.domain.internal.ListableBlobPropertiesImpl; import org.jclouds.azure.storage.blob.domain.internal.ListableBlobPropertiesImpl;
import org.jclouds.azure.storage.blob.domain.internal.TreeSetListBlobsResponse; import org.jclouds.azure.storage.blob.domain.internal.TreeSetListBlobsResponse;
import org.jclouds.blobstore.internal.LocationAndCredentials; import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.DateService; import org.jclouds.util.DateService;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -128,7 +128,7 @@ public class ContainerNameEnumerationResultsHandler extends
currentContentEncoding = null; currentContentEncoding = null;
currentContentLanguage = null; currentContentLanguage = null;
} else if (qName.equals("Url")) { } else if (qName.equals("Url")) {
currentUrl = LocationAndCredentials.parse(currentText.toString().trim()).uri; currentUrl = HttpUtils.createUri(currentText.toString().trim());
} else if (qName.equals("LastModified")) { } else if (qName.equals("LastModified")) {
currentLastModified = dateParser.rfc822DateParse(currentText.toString().trim()); currentLastModified = dateParser.rfc822DateParse(currentText.toString().trim());
} else if (qName.equals("Etag")) { } else if (qName.equals("Etag")) {

View File

@ -30,10 +30,15 @@ import java.util.Properties;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpPropertiesBuilder; import org.jclouds.http.HttpPropertiesBuilder;
import com.google.inject.Module; import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class BlobStoreContextFactory { public class BlobStoreContextFactory {
private final Properties properties; private final Properties properties;
@ -42,13 +47,15 @@ public class BlobStoreContextFactory {
this.properties = properties; this.properties = properties;
} }
@SuppressWarnings("unchecked") public BlobStoreContext<?, ?> createContext(URI blobStore, Module... modules) {
public BlobStoreContext<?, ?> createContext(URI blobStore, String account, String key, return createContext(blobStore, Credentials.parse(blobStore), modules);
Module... modules) { }
String hint = checkNotNull(blobStore.getHost(), "host");
checkNotNull(account, "account");
checkNotNull(key, "key");
@SuppressWarnings("unchecked")
public BlobStoreContext<?, ?> createContext(URI blobStore, Credentials creds, Module... modules) {
String hint = checkNotNull(blobStore.getHost(), "host");
String account = checkNotNull(creds.account, "account");
String key = creds.key;
String propertiesBuilderKey = String.format("%s.propertiesbuilder", hint); String propertiesBuilderKey = String.format("%s.propertiesbuilder", hint);
String propertiesBuilderClassName = checkNotNull( String propertiesBuilderClassName = checkNotNull(
properties.getProperty(propertiesBuilderKey), propertiesBuilderKey); properties.getProperty(propertiesBuilderKey), propertiesBuilderKey);

View File

@ -1,143 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jclouds.util.Utils;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
/**
* 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 class,
* and we could simply use URI.create("uri").getUserData();
*
* @author Adrian Cole
*/
public class LocationAndCredentials {
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
public static final Pattern PATTERN_THAT_BREAKS_URI = Pattern.compile("[a-z0-9]+://.*/.*@.*"); // slash
// in
// userdata
// breaks
// URI.create()
public final URI uri;
public final String acccount;
public final String key;
public LocationAndCredentials(URI uri, String acccount, String key) {
this.uri = checkNotNull(uri, "uri");
checkArgument(uri.getHost() != null, "type missing from %s", uri.toASCIIString());
checkArgument(uri.getPath() != null, "path missing from %s", uri.toASCIIString());
this.acccount = acccount;
this.key = key;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((acccount == null) ? 0 : acccount.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode());
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LocationAndCredentials other = (LocationAndCredentials) obj;
if (acccount == null) {
if (other.acccount != null)
return false;
} else if (!acccount.equals(other.acccount))
return false;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
if (uri == null) {
if (other.uri != null)
return false;
} else if (!uri.equals(other.uri))
return false;
return true;
}
public static LocationAndCredentials parse(String uriPath) {
if (uriPath.indexOf('@') != 1) {
List<String> parts = Lists.newArrayList(Splitter.on('@').split(uriPath));
String path = parts.remove(parts.size() - 1);
parts.add(Utils.urlEncode(path, '/', ':'));
uriPath = Joiner.on('@').join(parts);
} else {
List<String> parts = Lists.newArrayList(Splitter.on('/').split(uriPath));
String path = parts.remove(parts.size() - 1);
parts.add(Utils.urlEncode(path, ':'));
uriPath = Joiner.on('/').join(parts);
}
LocationAndCredentials locationAndCredentials;
if (PATTERN_THAT_BREAKS_URI.matcher(uriPath).matches()) {
// Compile and use regular expression
Matcher matcher = URI_PATTERN.matcher(uriPath);
if (matcher.find()) {
String scheme = matcher.group(1);
String rest = matcher.group(4);
String account = matcher.group(2);
String key = matcher.group(3);
locationAndCredentials = new LocationAndCredentials(URI.create(String.format("%s://%s",
scheme, rest)), account, key);
} else {
throw new IllegalArgumentException("bad syntax");
}
} else {
URI uri = URI.create(uriPath);
String account = null;
String key = null;
if (uri.getUserInfo() != null) {
List<String> userInfo = Lists.newArrayList(Splitter.on(':').split(uri.getUserInfo()));
account = userInfo.get(0);
key = userInfo.size() > 1 ? userInfo.get(1) : null;
}
locationAndCredentials = new LocationAndCredentials(uri, account, key);
}
return locationAndCredentials;
}
}

View File

@ -0,0 +1,95 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.List;
import org.jclouds.http.HttpUtils;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
/**
* @author Adrian Cole
*/
public class Credentials {
public final String account;
public final String key;
public Credentials(String account, String key) {
this.account = account;
this.key = key;
}
public static Credentials parse(URI uri) {
checkNotNull(uri, "uri");
List<String> userInfo = Lists.newArrayList(Splitter.on(':').split(uri.getUserInfo()));
String account = checkNotNull(userInfo.get(0));
if (HttpUtils.isUrlEncoded(account)) {
account = HttpUtils.urlDecode(account);
}
String key = userInfo.size() > 1 ? userInfo.get(1) : null;
if (key != null && HttpUtils.isUrlEncoded(key)) {
key = HttpUtils.urlDecode(key);
}
return new Credentials(account, key);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((account == null) ? 0 : account.hashCode());
result = prime * result + ((key == null) ? 0 : key.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Credentials other = (Credentials) obj;
if (account == null) {
if (other.account != null)
return false;
} else if (!account.equals(other.account))
return false;
if (key == null) {
if (other.key != null)
return false;
} else if (!key.equals(other.key))
return false;
return true;
}
}

View File

@ -25,19 +25,29 @@ package org.jclouds.http;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.Digest;
@ -50,11 +60,137 @@ import org.bouncycastle.util.encoders.Base64;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.SortedSetMultimap; import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap; import com.google.common.collect.TreeMultimap;
public class HttpUtils { public class HttpUtils {
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
public static final Pattern PATTERN_THAT_BREAKS_URI = Pattern.compile("[a-z0-9]+://.*/.*@.*"); // slash
@Resource
protected static Logger logger = Logger.NULL;
/**
* Web browsers do not always handle '+' characters well, use the well-supported '%20' instead.
*/
public static String urlEncode(String in, char... skipEncode) {
if (isUrlEncoded(in))
return in;
try {
String returnVal = URLEncoder.encode(in, "UTF-8").replaceAll("\\+", "%20").replaceAll(
"\\*", "%2A").replaceAll("%7E", "~");
for (char c : skipEncode) {
returnVal = returnVal.replaceAll(plainToEncodedChars.get(c + ""), c + "");
}
return returnVal;
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Bad encoding on input: " + in, e);
}
}
public static boolean isUrlEncoded(String in) {
return in.matches(".*%[a-fA-F0-9][a-fA-F0-9].*");
}
static Map<String, String> plainToEncodedChars = new MapMaker()
.makeComputingMap(new Function<String, String>() {
public String apply(String plain) {
try {
return URLEncoder.encode(plain, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Bad encoding on input: " + plain, e);
}
}
});
public static String urlDecode(String in) {
try {
return URLDecoder.decode(in, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Bad encoding on input: " + in, e);
}
}
/**
* Content stream may need to be read. However, we should always close the http stream.
*/
public static byte[] closeClientButKeepContentStream(HttpResponse response) {
if (response.getContent() != null) {
try {
byte[] data = IOUtils.toByteArray(response.getContent());
response.setContent(new ByteArrayInputStream(data));
return data;
} catch (IOException e) {
logger.error(e, "Error consuming input");
} finally {
IOUtils.closeQuietly(response.getContent());
}
}
return null;
}
public static URI parseEndPoint(String hostHeader) {
URI redirectURI = URI.create(hostHeader);
String scheme = redirectURI.getScheme();
checkState(redirectURI.getScheme().startsWith("http"), String.format(
"header %s didn't parse an http scheme: [%s]", hostHeader, scheme));
int port = redirectURI.getPort() > 0 ? redirectURI.getPort() : redirectURI.getScheme()
.equals("https") ? 443 : 80;
String host = redirectURI.getHost();
checkState(!host.matches("[/]"), String.format(
"header %s didn't parse an http host correctly: [%s]", hostHeader, host));
URI endPoint = URI.create(String.format("%s://%s:%d", scheme, host, port));
return endPoint;
}
public static URI replaceHostInEndPoint(URI endPoint, String host) {
return URI.create(endPoint.toString().replace(endPoint.getHost(), host));
}
/**
* 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
* class, and we could simply use URI.create("uri").getUserData();
*
* @author Adrian Cole
*/
public static URI createUri(String uriPath) {
if (uriPath.indexOf('@') != 1) {
List<String> parts = Lists.newArrayList(Splitter.on('@').split(uriPath));
String path = parts.remove(parts.size() - 1);
parts.add(urlEncode(path, '/', ':'));
uriPath = Joiner.on('@').join(parts);
} else {
List<String> parts = Lists.newArrayList(Splitter.on('/').split(uriPath));
String path = parts.remove(parts.size() - 1);
parts.add(urlEncode(path, ':'));
uriPath = Joiner.on('/').join(parts);
}
if (PATTERN_THAT_BREAKS_URI.matcher(uriPath).matches()) {
// Compile and use regular expression
Matcher matcher = URI_PATTERN.matcher(uriPath);
if (matcher.find()) {
String scheme = matcher.group(1);
String rest = matcher.group(4);
String account = matcher.group(2);
String key = matcher.group(3);
return URI
.create(String.format("%s://%s:%s@%s", scheme, account, urlEncode(key), rest));
} else {
throw new IllegalArgumentException("bad syntax");
}
} else {
return URI.create(uriPath);
}
}
public static final Pattern IP_PATTERN = Pattern public static final Pattern IP_PATTERN = Pattern
.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)" .compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"

View File

@ -65,6 +65,7 @@ import org.jboss.resteasy.util.IsHttpMethod;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x; import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x;
import org.jclouds.http.functions.ReturnInputStream; import org.jclouds.http.functions.ReturnInputStream;
@ -93,7 +94,6 @@ import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -430,7 +430,7 @@ public class RestAnnotationProcessor<T> {
} else if (in.indexOf('&') == -1) { } else if (in.indexOf('&') == -1) {
map.put(in, null); map.put(in, null);
} else { } else {
String[] parts = Utils.urlDecode(in).split("&"); String[] parts = HttpUtils.urlDecode(in).split("&");
for (int partIndex = 0; partIndex < parts.length; partIndex++) { for (int partIndex = 0; partIndex < parts.length; partIndex++) {
String[] keyValue = parts[partIndex].split("="); String[] keyValue = parts[partIndex].split("=");
map.put(keyValue[0], keyValue.length == 2 ? keyValue[1] : null); map.put(keyValue[0], keyValue.length == 2 ? keyValue[1] : null);
@ -454,10 +454,10 @@ public class RestAnnotationProcessor<T> {
StringBuilder formBuilder = new StringBuilder(); StringBuilder formBuilder = new StringBuilder();
while (pairs.hasNext()) { while (pairs.hasNext()) {
Map.Entry<String, String> pair = pairs.next(); Map.Entry<String, String> pair = pairs.next();
formBuilder.append(Utils.urlEncode(pair.getKey(), skips)); formBuilder.append(HttpUtils.urlEncode(pair.getKey(), skips));
if (pair.getValue() != null && !pair.getValue().equals("")) { if (pair.getValue() != null && !pair.getValue().equals("")) {
formBuilder.append("="); formBuilder.append("=");
formBuilder.append(Utils.urlEncode(pair.getValue(), skips)); formBuilder.append(HttpUtils.urlEncode(pair.getValue(), skips));
} }
if (pairs.hasNext()) if (pairs.hasNext())
formBuilder.append("&"); formBuilder.append("&");
@ -953,7 +953,7 @@ public class RestAnnotationProcessor<T> {
private Multimap<String, String> encodeValues(Multimap<String, String> unencoded, char... skips) { private Multimap<String, String> encodeValues(Multimap<String, String> unencoded, char... skips) {
Multimap<String, String> encoded = LinkedHashMultimap.create(); Multimap<String, String> encoded = LinkedHashMultimap.create();
for (Entry<String, String> entry : unencoded.entries()) { for (Entry<String, String> entry : unencoded.entries()) {
encoded.put(entry.getKey(), Utils.urlEncode(entry.getValue(), skips)); encoded.put(entry.getKey(), HttpUtils.urlEncode(entry.getValue(), skips));
} }
return encoded; return encoded;
} }

View File

@ -23,15 +23,9 @@
*/ */
package org.jclouds.util; package org.jclouds.util;
import static com.google.common.base.Preconditions.checkState;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -40,13 +34,10 @@ import java.util.regex.Pattern;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpResponse;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ComputationException; import com.google.common.collect.ComputationException;
import com.google.common.collect.MapMaker;
/** /**
* // TODO: Adrian: Document this! * // TODO: Adrian: Document this!
@ -73,84 +64,6 @@ public class Utils {
@Resource @Resource
protected static Logger logger = Logger.NULL; protected static Logger logger = Logger.NULL;
/**
* Web browsers do not always handle '+' characters well, use the well-supported '%20' instead.
*/
public static String urlEncode(String in, char... skipEncode) {
if (isUrlEncoded(in))
return in;
try {
String returnVal = URLEncoder.encode(in, "UTF-8").replaceAll("\\+", "%20").replaceAll(
"\\*", "%2A").replaceAll("%7E", "~");
for (char c : skipEncode) {
returnVal = returnVal.replaceAll(plainToEncodedChars.get(c + ""), c + "");
}
return returnVal;
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Bad encoding on input: " + in, e);
}
}
public static boolean isUrlEncoded(String in) {
return in.matches(".*%[a-fA-F0-9][a-fA-F0-9].*");
}
static Map<String, String> plainToEncodedChars = new MapMaker()
.makeComputingMap(new Function<String, String>() {
public String apply(String plain) {
try {
return URLEncoder.encode(plain, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Bad encoding on input: " + plain, e);
}
}
});
public static String urlDecode(String in) {
try {
return URLDecoder.decode(in, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Bad encoding on input: " + in, e);
}
}
/**
* Content stream may need to be read. However, we should always close the http stream.
*/
public static byte[] closeClientButKeepContentStream(HttpResponse response) {
if (response.getContent() != null) {
try {
byte[] data = IOUtils.toByteArray(response.getContent());
response.setContent(new ByteArrayInputStream(data));
return data;
} catch (IOException e) {
logger.error(e, "Error consuming input");
} finally {
IOUtils.closeQuietly(response.getContent());
}
}
return null;
}
public static URI parseEndPoint(String hostHeader) {
URI redirectURI = URI.create(hostHeader);
String scheme = redirectURI.getScheme();
checkState(redirectURI.getScheme().startsWith("http"), String.format(
"header %s didn't parse an http scheme: [%s]", hostHeader, scheme));
int port = redirectURI.getPort() > 0 ? redirectURI.getPort() : redirectURI.getScheme()
.equals("https") ? 443 : 80;
String host = redirectURI.getHost();
checkState(!host.matches("[/]"), String.format(
"header %s didn't parse an http host correctly: [%s]", hostHeader, host));
URI endPoint = URI.create(String.format("%s://%s:%d", scheme, host, port));
return endPoint;
}
public static URI replaceHostInEndPoint(URI endPoint, String host) {
return URI.create(endPoint.toString().replace(endPoint.getHost(), host));
}
/** /**
* *
* @param <E> * @param <E>

View File

@ -21,66 +21,50 @@
* under the License. * under the License.
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.blobstore.internal; package org.jclouds.domain;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
import org.jclouds.blobstore.internal.LocationAndCredentials;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", testName = "blobstore.LocationAndCredentialsTest") @Test(groups = "unit", testName = "blobstore.CredentialsTest")
public class LocationAndCredentialsTest { public class CredentialsTest {
public void testAzure() { public void testAzure() {
LocationAndCredentials creds = LocationAndCredentials Credentials creds = Credentials.parse(URI
.parse("blobstore://account:Base64==@azureblob/container-hyphen/prefix");
assertEquals(creds.acccount, "account");
assertEquals(creds.key, "Base64==");
assertEquals(creds.uri, URI
.create("blobstore://account:Base64==@azureblob/container-hyphen/prefix")); .create("blobstore://account:Base64==@azureblob/container-hyphen/prefix"));
assertEquals(creds.account, "account");
assertEquals(creds.key, "Base64==");
} }
public void testCloudFiles() { public void testCloudFiles() {
LocationAndCredentials creds = LocationAndCredentials Credentials creds = Credentials.parse(URI
.parse("blobstore://account:h3c@cloudfiles/container-hyphen/prefix");
assertEquals(creds.acccount, "account");
assertEquals(creds.key, "h3c");
assertEquals(creds.uri, URI
.create("blobstore://account:h3c@cloudfiles/container-hyphen/prefix")); .create("blobstore://account:h3c@cloudfiles/container-hyphen/prefix"));
assertEquals(creds.account, "account");
assertEquals(creds.key, "h3c");
} }
public void testS3() { public void testS3() {
LocationAndCredentials creds = LocationAndCredentials Credentials creds = Credentials.parse(URI
.parse("blobstore://0AB:aA+/0@s3/buck-et/prefix"); .create("blobstore://0AB:aA%2B%2F0@s3/buck-et/prefix"));
assertEquals(creds.acccount, "0AB"); assertEquals(creds.account, "0AB");
assertEquals(creds.key, "aA+/0"); assertEquals(creds.key, "aA+/0");
assertEquals(creds.uri, URI.create("blobstore://s3/buck-et/prefix"));
} }
public void testS3Space() { public void testS3Space() {
LocationAndCredentials creds = LocationAndCredentials Credentials creds = Credentials.parse(URI
.parse("blobstore://0AB:aA+/0@s3/buck-et/pre fix"); .create("blobstore://0AB:aA%2B%2F0@s3/buck-et/pre%20fix"));
assertEquals(creds.acccount, "0AB"); assertEquals(creds.account, "0AB");
assertEquals(creds.key, "aA+/0"); assertEquals(creds.key, "aA+/0");
assertEquals(creds.uri, URI.create("blobstore://s3/buck-et/pre%20fix"));
} }
public void testPercent() {
LocationAndCredentials creds = LocationAndCredentials
.parse("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%.txt");
assertEquals(creds.acccount, null);
assertEquals(creds.key, null);
assertEquals(
creds.uri,
URI
.create("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%25.txt"));
}
} }

View File

@ -26,6 +26,7 @@ package org.jclouds.util;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
@ -48,6 +49,53 @@ import org.testng.annotations.Test;
@Test(groups = "performance", sequential = true, testName = "jclouds.HttpUtils") @Test(groups = "performance", sequential = true, testName = "jclouds.HttpUtils")
public class HttpUtilsTest extends PerformanceTest { public class HttpUtilsTest extends PerformanceTest {
public void testIsEncoded() {
assert HttpUtils.isUrlEncoded("/read-tests/%73%6f%6d%65%20%66%69%6c%65");
assert !HttpUtils.isUrlEncoded("/read-tests/ tep");
}
public void testNoDoubleEncode() {
assertEquals(HttpUtils.urlEncode("/read-tests/%73%6f%6d%65%20%66%69%6c%65", '/'),
"/read-tests/%73%6f%6d%65%20%66%69%6c%65");
assertEquals(HttpUtils.urlEncode("/read-tests/ tep", '/'), "/read-tests/%20tep");
}
public void testAzure() {
URI creds = HttpUtils
.createUri("blobstore://account:Base64==@azureblob/container-hyphen/prefix");
assertEquals(creds, URI
.create("blobstore://account:Base64==@azureblob/container-hyphen/prefix"));
}
public void testCloudFiles() {
URI creds = HttpUtils.createUri("blobstore://account:h3c@cloudfiles/container-hyphen/prefix");
assertEquals(creds, URI.create("blobstore://account:h3c@cloudfiles/container-hyphen/prefix"));
}
public void testS3() {
URI creds = HttpUtils.createUri("blobstore://0AB:aA+/0@s3/buck-et/prefix");
assertEquals(creds, URI.create("blobstore://0AB:aA%2B%2F0@s3/buck-et/prefix"));
}
public void testS3Space() {
URI creds = HttpUtils.createUri("blobstore://0AB:aA+/0@s3/buck-et/pre fix");
assertEquals(creds, URI.create("blobstore://0AB:aA%2B%2F0@s3/buck-et/pre%20fix"));
}
public void testPercent() {
URI creds = HttpUtils
.createUri("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%.txt");
assertEquals(
creds,
URI
.create("https://jclouds.blob.core.windows.net/jclouds-getpath/write-tests/file1%25.txt"));
}
@Test(dataProvider = "hmacsha1") @Test(dataProvider = "hmacsha1")
void testBouncyCastleDigestSerialResponseTime(byte[] key, String message, String base64Digest) void testBouncyCastleDigestSerialResponseTime(byte[] key, String message, String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException { throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {

View File

@ -42,14 +42,4 @@ public class UtilsTest {
"hello world"); "hello world");
} }
public void testIsEncoded() {
assert Utils.isUrlEncoded("/read-tests/%73%6f%6d%65%20%66%69%6c%65");
assert !Utils.isUrlEncoded("/read-tests/ tep");
}
public void testNoDoubleEncode() {
assertEquals(Utils.urlEncode("/read-tests/%73%6f%6d%65%20%66%69%6c%65", '/'),
"/read-tests/%73%6f%6d%65%20%66%69%6c%65");
assertEquals(Utils.urlEncode("/read-tests/ tep", '/'), "/read-tests/%20tep");
}
} }

View File

@ -34,6 +34,9 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>jclouds-ant-plugin</artifactId> <artifactId>jclouds-ant-plugin</artifactId>
<properties>
<jclouds.test.listener></jclouds.test.listener>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.apache.ant</groupId> <groupId>org.apache.ant</groupId>
@ -47,4 +50,4 @@
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -23,30 +23,55 @@
*/ */
package org.jclouds.tools.ant; package org.jclouds.tools.ant;
import org.apache.tools.ant.Task; import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.Properties;
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.jclouds.compute.ComputeService;
import org.jclouds.rimuhosting.miro.RimuHostingContextBuilder; import org.jclouds.rimuhosting.miro.RimuHostingContextBuilder;
import org.jclouds.rimuhosting.miro.RimuHostingPropertiesBuilder; import org.jclouds.rimuhosting.miro.RimuHostingPropertiesBuilder;
import org.jclouds.compute.ComputeService;
import com.google.common.io.Resources;
import com.google.inject.Injector; import com.google.inject.Injector;
/** /**
* @author Ivan Meredith * @author Ivan Meredith
*/ */
public class ComputeTask extends Task { public class ComputeTask extends Task {
private final Map<URI, ComputeService> computeMap;
public ComputeTask() throws IOException {
this(null);//TODO MapMaker
}
static Properties loadDefaultProperties() throws IOException {
Properties properties = new Properties();
properties.load(Resources.newInputStreamSupplier(Resources.getResource("compute.properties"))
.getInput());
return properties;
}
public ComputeTask(Map<URI, ComputeService> computeMap) {
this.computeMap = computeMap;
}
private final String ACTION_CREATE = "create"; private final String ACTION_CREATE = "create";
private String action; private String action;
private ServerElement serverElement; private ServerElement serverElement;
public void execute() throws BuildException { public void execute() throws BuildException {
if(ACTION_CREATE.equalsIgnoreCase(action)){ if (ACTION_CREATE.equalsIgnoreCase(action)) {
if(getServerElement() != null){ if (getServerElement() != null) {
Injector injector = new RimuHostingContextBuilder(new RimuHostingPropertiesBuilder("test", "Test").relaxSSLHostname().build()).buildInjector(); Injector injector = new RimuHostingContextBuilder(new RimuHostingPropertiesBuilder(
"test", "Test").relaxSSLHostname().build()).buildInjector();
ComputeService computeService = injector.getInstance(ComputeService.class); ComputeService computeService = injector.getInstance(ComputeService.class);
computeService.createServerAndWait("test.com","MIRO1B","lenny"); computeService.createServerAndWait("test.com", "MIRO1B", "lenny");
} }
} }
} }

View File

@ -23,7 +23,8 @@
*/ */
package org.jclouds.blobstore; package org.jclouds.blobstore;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -31,12 +32,13 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URI;
import java.util.Properties; import java.util.Properties;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jclouds.blobstore.internal.LocationAndCredentials;
import org.jclouds.blobstore.util.BlobStoreUtils; import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.http.HttpUtils;
import com.google.common.io.Resources; import com.google.common.io.Resources;
@ -53,10 +55,10 @@ public class GetPath {
public static void main(String... args) throws IOException { public static void main(String... args) throws IOException {
if (args.length < 2) if (args.length < 2)
throw new IllegalArgumentException(INVALID_SYNTAX); throw new IllegalArgumentException(INVALID_SYNTAX);
LocationAndCredentials locationAndCredentials; URI locationAndCredentials;
try { try {
locationAndCredentials = LocationAndCredentials.parse(args[0]); locationAndCredentials = HttpUtils.createUri(args[0]);
checkArgument(locationAndCredentials.uri.getScheme().equals("blobstore"), "wrong scheme"); checkArgument(locationAndCredentials.getScheme().equals("blobstore"), "wrong scheme");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("%s%n%s", e.getMessage(), INVALID_SYNTAX)); throw new IllegalArgumentException(String.format("%s%n%s", e.getMessage(), INVALID_SYNTAX));
} }
@ -67,14 +69,12 @@ public class GetPath {
destinationDir.mkdirs(); destinationDir.mkdirs();
BlobStoreContext<?, ?> context = init(locationAndCredentials); BlobStoreContext<?, ?> context = init(locationAndCredentials);
String path = locationAndCredentials.uri.getPath(); String path = locationAndCredentials.getPath();
if (path.startsWith("/")) if (path.startsWith("/"))
path = path.substring(1); path = path.substring(1);
String container = BlobStoreUtils.parseContainerFromPath(path); String container = BlobStoreUtils.parseContainerFromPath(path);
String directory = BlobStoreUtils.parsePrefixFromPath(path); String directory = BlobStoreUtils.parsePrefixFromPath(path);
copyDirectoryToDestination(context, container, directory, destinationDir); copyDirectoryToDestination(context, container, directory, destinationDir);
context.close();
} }
private static void copyDirectoryToDestination(BlobStoreContext<?, ?> context, String container, private static void copyDirectoryToDestination(BlobStoreContext<?, ?> context, String container,
@ -107,12 +107,10 @@ public class GetPath {
} }
} }
private static BlobStoreContext<?, ?> init(LocationAndCredentials locationAndCredentials) private static BlobStoreContext<?, ?> init(URI locationAndCredentials) throws IOException {
throws IOException {
Properties properties = new Properties(); Properties properties = new Properties();
properties.load(Resources.newInputStreamSupplier(Resources.getResource("jclouds.properties")) properties.load(Resources.newInputStreamSupplier(Resources.getResource("jclouds.properties"))
.getInput()); .getInput());
return new BlobStoreContextFactory(properties).createContext(locationAndCredentials.uri, return new BlobStoreContextFactory(properties).createContext(locationAndCredentials);
locationAndCredentials.acccount, locationAndCredentials.key);
} }
} }

View File

@ -54,23 +54,23 @@ public class PropertiesTest {
} }
public void testAzure() { public void testAzure() {
assertEquals(properties.getProperty("azureblob.contextBuilder"), assertEquals(properties.getProperty("azureblob.contextbuilder"),
AzureBlobStoreContextBuilder.class.getName()); AzureBlobStoreContextBuilder.class.getName());
assertEquals(properties.getProperty("azureblob.propertiesBuilder"), assertEquals(properties.getProperty("azureblob.propertiesbuilder"),
AzureBlobPropertiesBuilder.class.getName()); AzureBlobPropertiesBuilder.class.getName());
} }
public void testCloudFiles() { public void testCloudFiles() {
assertEquals(properties.getProperty("cloudfiles.contextBuilder"), assertEquals(properties.getProperty("cloudfiles.contextbuilder"),
CloudFilesBlobStoreContextBuilder.class.getName()); CloudFilesBlobStoreContextBuilder.class.getName());
assertEquals(properties.getProperty("cloudfiles.propertiesBuilder"), assertEquals(properties.getProperty("cloudfiles.propertiesbuilder"),
CloudFilesPropertiesBuilder.class.getName()); CloudFilesPropertiesBuilder.class.getName());
} }
public void testBlobStore() { public void testBlobStore() {
assertEquals(properties.getProperty("s3.contextBuilder"), S3BlobStoreContextBuilder.class assertEquals(properties.getProperty("s3.contextbuilder"), S3BlobStoreContextBuilder.class
.getName()); .getName());
assertEquals(properties.getProperty("s3.propertiesBuilder"), S3PropertiesBuilder.class assertEquals(properties.getProperty("s3.propertiesbuilder"), S3PropertiesBuilder.class
.getName()); .getName());
} }
} }

View File

@ -23,13 +23,16 @@
*/ */
package org.jclouds.vfs.provider.blobstore; package org.jclouds.vfs.provider.blobstore;
import java.net.URI;
import org.apache.commons.vfs.FileName; import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType; import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.provider.URLFileNameParser; import org.apache.commons.vfs.provider.URLFileNameParser;
import org.apache.commons.vfs.provider.UriParser; import org.apache.commons.vfs.provider.UriParser;
import org.apache.commons.vfs.provider.VfsComponentContext; import org.apache.commons.vfs.provider.VfsComponentContext;
import org.jclouds.blobstore.internal.LocationAndCredentials; import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpUtils;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -49,9 +52,11 @@ public class BlobStoreFileNameParser extends URLFileNameParser {
throws FileSystemException { throws FileSystemException {
// if there are unencoded characters in the password, things break. // if there are unencoded characters in the password, things break.
LocationAndCredentials creds = LocationAndCredentials.parse(filename); URI uri = HttpUtils.createUri(filename);
filename = creds.uri.toASCIIString(); filename = uri.toASCIIString();
Credentials creds = Credentials.parse(uri);
StringBuffer name = new StringBuffer(); StringBuffer name = new StringBuffer();
@ -73,7 +78,7 @@ public class BlobStoreFileNameParser extends URLFileNameParser {
FileType fileType = UriParser.normalisePath(name); FileType fileType = UriParser.normalisePath(name);
String path = name.toString(); String path = name.toString();
return new BlobStoreFileName(auth.getHostName(), creds.acccount, creds.key, path, fileType, return new BlobStoreFileName(auth.getHostName(), creds.account, creds.key, path, fileType,
container); container);
} }

View File

@ -24,6 +24,7 @@
package org.jclouds.vfs.provider.blobstore; package org.jclouds.vfs.provider.blobstore;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -41,7 +42,8 @@ import org.apache.commons.vfs.provider.http.HttpFileSystemConfigBuilder;
import org.apache.commons.vfs.util.UserAuthenticatorUtils; import org.apache.commons.vfs.util.UserAuthenticatorUtils;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.BlobStoreContextFactory; import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.blobstore.internal.LocationAndCredentials; import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpUtils;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import com.google.inject.Module; import com.google.inject.Module;
@ -79,16 +81,17 @@ public class BlobStoreFileProvider extends AbstractOriginatingFileProvider {
Properties properties = new Properties(); Properties properties = new Properties();
properties.load(Resources.newInputStreamSupplier( properties.load(Resources.newInputStreamSupplier(
Resources.getResource("jclouds.properties")).getInput()); Resources.getResource("jclouds.properties")).getInput());
LocationAndCredentials locationAndCredentials = LocationAndCredentials.parse(uriToParse); URI location = HttpUtils.createUri(uriToParse);
blobStore = new BlobStoreContextFactory(properties).createContext( blobStore = new BlobStoreContextFactory(properties).createContext(
locationAndCredentials.uri, location,
UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData, new Credentials(UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(
UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(rootName authData, UserAuthenticationData.USERNAME, UserAuthenticatorUtils
.getUserName()))), .toChar(rootName.getUserName()))), UserAuthenticatorUtils
UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData, .toString(UserAuthenticatorUtils.getData(authData,
UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(rootName UserAuthenticationData.PASSWORD, UserAuthenticatorUtils
.getPassword()))),modules).getBlobStore(); .toChar(rootName.getPassword())))), modules)
.getBlobStore();
} catch (IOException e) { } catch (IOException e) {
throw new FileSystemException("vfs.provider.blobstore/properties.error", name, e); throw new FileSystemException("vfs.provider.blobstore/properties.error", name, e);
} finally { } finally {

View File

@ -23,11 +23,13 @@
*/ */
package org.jclouds.vfs.tools.blobstore; package org.jclouds.vfs.tools.blobstore;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URI;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -43,7 +45,7 @@ import org.apache.commons.vfs.Selectors;
import org.apache.commons.vfs.VFS; import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.cache.SoftRefFilesCache; import org.apache.commons.vfs.cache.SoftRefFilesCache;
import org.apache.commons.vfs.impl.DefaultFileSystemManager; import org.apache.commons.vfs.impl.DefaultFileSystemManager;
import org.jclouds.blobstore.internal.LocationAndCredentials; import org.jclouds.http.HttpUtils;
import org.jclouds.vfs.provider.blobstore.BlobStoreFileProvider; import org.jclouds.vfs.provider.blobstore.BlobStoreFileProvider;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -72,10 +74,10 @@ public class BlobStoreShell {
if (args.length != 1) if (args.length != 1)
throw new IllegalArgumentException(INVALID_SYNTAX); throw new IllegalArgumentException(INVALID_SYNTAX);
LocationAndCredentials locationAndCredentials; URI location;
try { try {
locationAndCredentials = LocationAndCredentials.parse(args[0]); location = HttpUtils.createUri(args[0]);
checkArgument(locationAndCredentials.uri.getScheme().equals("blobstore"), "wrong scheme"); checkArgument(location.getScheme().equals("blobstore"), "wrong scheme");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("%s%n%s", e.getMessage(), INVALID_SYNTAX)); throw new IllegalArgumentException(String.format("%s%n%s", e.getMessage(), INVALID_SYNTAX));
} }

View File

@ -35,37 +35,49 @@ public class FileNameTestCase extends AbstractVfsTestCase {
/** /**
* Tests parsing a URI into its parts. * Tests parsing a URI into its parts.
*/ */
public void testParseUriNoCreds() throws Exception {
try {
// Simple name
BlobStoreFileName name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance()
.parseUri(null, null, "blobstore://service/container/file");
assertEquals("blobstore", name.getScheme());
assertNull(name.getUserName());
assertNull(name.getPassword());
assertEquals("service", name.getHostName());
assertEquals(443, name.getPort());
assertEquals(name.getDefaultPort(), name.getPort());
assertEquals("container", name.getContainer());
assertEquals("/file", name.getPath());
assertEquals("blobstore://service/container/", name.getRootURI());
assertEquals("blobstore://service/container/file", name.getURI());
fail();
} catch (NullPointerException e) {
}
try {
// Name with no path
BlobStoreFileName name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance()
.parseUri(null, null, "blobstore://service/container");
assertEquals("blobstore", name.getScheme());
assertNull(name.getUserName());
assertNull(name.getPassword());
assertEquals("service", name.getHostName());
assertEquals(443, name.getPort());
assertEquals("container", name.getContainer());
assertEquals("/", name.getPath());
assertEquals("blobstore://service/container/", name.getRootURI());
assertEquals("blobstore://service/container/", name.getURI());
fail();
} catch (NullPointerException e) {
}
}
public void testParseUri() throws Exception { public void testParseUri() throws Exception {
// Simple name
BlobStoreFileName name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance().parseUri(
null, null, "blobstore://service/container/file");
assertEquals("blobstore", name.getScheme());
assertNull(name.getUserName());
assertNull(name.getPassword());
assertEquals("service", name.getHostName());
assertEquals(443, name.getPort());
assertEquals(name.getDefaultPort(), name.getPort());
assertEquals("container", name.getContainer());
assertEquals("/file", name.getPath());
assertEquals("blobstore://service/container/", name.getRootURI());
assertEquals("blobstore://service/container/file", name.getURI());
// Name with no path
name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance().parseUri(null, null,
"blobstore://service/container");
assertEquals("blobstore", name.getScheme());
assertNull(name.getUserName());
assertNull(name.getPassword());
assertEquals("service", name.getHostName());
assertEquals(443, name.getPort());
assertEquals("container", name.getContainer());
assertEquals("/", name.getPath());
assertEquals("blobstore://service/container/", name.getRootURI());
assertEquals("blobstore://service/container/", name.getURI());
// Name with username // Name with username
name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance().parseUri(null, null, BlobStoreFileName name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance().parseUri(
"blobstore://user@service/container/file"); null, null, "blobstore://user@service/container/file");
assertEquals("blobstore", name.getScheme()); assertEquals("blobstore", name.getScheme());
assertEquals("user", name.getUserName()); assertEquals("user", name.getUserName());
assertNull(name.getPassword()); assertNull(name.getPassword());

View File

@ -37,15 +37,16 @@ import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
* @see <a href="https://community.vcloudexpress.terremark.com/en-us/discussion_forums/f/60.aspx" /> * @see <a href="https://community.vcloudexpress.terremark.com/en-us/discussion_forums/f/60.aspx" />
* @author Adrian Cole * @author Adrian Cole
*/ */
@Timeout(duration = 90, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface HostingDotComVCloudClient extends VCloudClient { public interface HostingDotComVCloudClient extends VCloudClient {
@Override @Override
@Timeout(duration = 240, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 300, timeUnit = TimeUnit.SECONDS)
HostingDotComVApp instantiateVAppTemplate(String appName, String templateId, HostingDotComVApp instantiateVAppTemplate(String appName, String templateId,
InstantiateVAppTemplateOptions... options); InstantiateVAppTemplateOptions... options);
@Override @Override
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
HostingDotComVApp getVApp(String vAppId); HostingDotComVApp getVApp(String vAppId);
} }