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.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.HttpUtils;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.inject.Inject;
@ -49,7 +49,7 @@ public class AtmosStorageClientErrorRetryHandler implements HttpRetryHandler {
protected Logger logger = Logger.NULL;
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
Utils.closeClientButKeepContentStream(response);
HttpUtils.closeClientButKeepContentStream(response);
command.incrementFailureCount();
if (!command.isReplayable()) {
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.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.HttpUtils;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.inject.Inject;
@ -64,7 +64,7 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
return false;
if (response.getStatusCode() == 400 || response.getStatusCode() == 403
|| response.getStatusCode() == 409) {
byte[] content = Utils.closeClientButKeepContentStream(response);
byte[] content = HttpUtils.closeClientButKeepContentStream(response);
command.incrementFailureCount();
try {
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.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.http.handlers.RedirectionRetryHandler;
import org.jclouds.util.Utils;
/**
* 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) {
if (response.getFirstHeaderOrNull(HttpHeaders.LOCATION) == null
&& (response.getStatusCode() == 301 || response.getStatusCode() == 307)) {
byte[] content = Utils.closeClientButKeepContentStream(response);
byte[] content = HttpUtils.closeClientButKeepContentStream(response);
if (command.getRequest().getMethod() == HttpMethod.HEAD) {
command.redirectAsGet();
return true;

View File

@ -33,9 +33,9 @@ import org.jclouds.http.HttpConstants;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import com.google.inject.Inject;
@ -64,7 +64,7 @@ public class AzureBlobClientErrorRetryHandler implements HttpRetryHandler {
}
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
byte[] content = Utils.closeClientButKeepContentStream(response);
byte[] content = HttpUtils.closeClientButKeepContentStream(response);
command.incrementFailureCount();
if (!command.isReplayable()) {
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.internal.ListableBlobPropertiesImpl;
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.util.DateService;
import org.joda.time.DateTime;
@ -128,7 +128,7 @@ public class ContainerNameEnumerationResultsHandler extends
currentContentEncoding = null;
currentContentLanguage = null;
} else if (qName.equals("Url")) {
currentUrl = LocationAndCredentials.parse(currentText.toString().trim()).uri;
currentUrl = HttpUtils.createUri(currentText.toString().trim());
} else if (qName.equals("LastModified")) {
currentLastModified = dateParser.rfc822DateParse(currentText.toString().trim());
} else if (qName.equals("Etag")) {

View File

@ -30,10 +30,15 @@ import java.util.Properties;
import javax.inject.Inject;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpPropertiesBuilder;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class BlobStoreContextFactory {
private final Properties properties;
@ -42,13 +47,15 @@ public class BlobStoreContextFactory {
this.properties = properties;
}
@SuppressWarnings("unchecked")
public BlobStoreContext<?, ?> createContext(URI blobStore, String account, String key,
Module... modules) {
String hint = checkNotNull(blobStore.getHost(), "host");
checkNotNull(account, "account");
checkNotNull(key, "key");
public BlobStoreContext<?, ?> createContext(URI blobStore, Module... modules) {
return createContext(blobStore, Credentials.parse(blobStore), modules);
}
@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 propertiesBuilderClassName = checkNotNull(
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.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.bouncycastle.crypto.Digest;
@ -50,11 +60,137 @@ import org.bouncycastle.util.encoders.Base64;
import org.jclouds.logging.Logger;
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.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
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
.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.HttpRequestFilter;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x;
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.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
@ -430,7 +430,7 @@ public class RestAnnotationProcessor<T> {
} else if (in.indexOf('&') == -1) {
map.put(in, null);
} else {
String[] parts = Utils.urlDecode(in).split("&");
String[] parts = HttpUtils.urlDecode(in).split("&");
for (int partIndex = 0; partIndex < parts.length; partIndex++) {
String[] keyValue = parts[partIndex].split("=");
map.put(keyValue[0], keyValue.length == 2 ? keyValue[1] : null);
@ -454,10 +454,10 @@ public class RestAnnotationProcessor<T> {
StringBuilder formBuilder = new StringBuilder();
while (pairs.hasNext()) {
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("")) {
formBuilder.append("=");
formBuilder.append(Utils.urlEncode(pair.getValue(), skips));
formBuilder.append(HttpUtils.urlEncode(pair.getValue(), skips));
}
if (pairs.hasNext())
formBuilder.append("&");
@ -953,7 +953,7 @@ public class RestAnnotationProcessor<T> {
private Multimap<String, String> encodeValues(Multimap<String, String> unencoded, char... skips) {
Multimap<String, String> encoded = LinkedHashMultimap.create();
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;
}

View File

@ -23,15 +23,9 @@
*/
package org.jclouds.util;
import static com.google.common.base.Preconditions.checkState;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
@ -40,13 +34,10 @@ import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.apache.commons.io.IOUtils;
import org.jclouds.http.HttpResponse;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ComputationException;
import com.google.common.collect.MapMaker;
/**
* // TODO: Adrian: Document this!
@ -73,84 +64,6 @@ public class Utils {
@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));
}
/**
*
* @param <E>

View File

@ -21,66 +21,50 @@
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.internal;
package org.jclouds.domain;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.blobstore.internal.LocationAndCredentials;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "blobstore.LocationAndCredentialsTest")
public class LocationAndCredentialsTest {
@Test(groups = "unit", testName = "blobstore.CredentialsTest")
public class CredentialsTest {
public void testAzure() {
LocationAndCredentials creds = LocationAndCredentials
.parse("blobstore://account:Base64==@azureblob/container-hyphen/prefix");
assertEquals(creds.acccount, "account");
assertEquals(creds.key, "Base64==");
assertEquals(creds.uri, URI
Credentials creds = Credentials.parse(URI
.create("blobstore://account:Base64==@azureblob/container-hyphen/prefix"));
assertEquals(creds.account, "account");
assertEquals(creds.key, "Base64==");
}
public void testCloudFiles() {
LocationAndCredentials creds = LocationAndCredentials
.parse("blobstore://account:h3c@cloudfiles/container-hyphen/prefix");
assertEquals(creds.acccount, "account");
assertEquals(creds.key, "h3c");
assertEquals(creds.uri, URI
Credentials creds = Credentials.parse(URI
.create("blobstore://account:h3c@cloudfiles/container-hyphen/prefix"));
assertEquals(creds.account, "account");
assertEquals(creds.key, "h3c");
}
public void testS3() {
LocationAndCredentials creds = LocationAndCredentials
.parse("blobstore://0AB:aA+/0@s3/buck-et/prefix");
assertEquals(creds.acccount, "0AB");
Credentials creds = Credentials.parse(URI
.create("blobstore://0AB:aA%2B%2F0@s3/buck-et/prefix"));
assertEquals(creds.account, "0AB");
assertEquals(creds.key, "aA+/0");
assertEquals(creds.uri, URI.create("blobstore://s3/buck-et/prefix"));
}
public void testS3Space() {
LocationAndCredentials creds = LocationAndCredentials
.parse("blobstore://0AB:aA+/0@s3/buck-et/pre fix");
assertEquals(creds.acccount, "0AB");
Credentials creds = Credentials.parse(URI
.create("blobstore://0AB:aA%2B%2F0@s3/buck-et/pre%20fix"));
assertEquals(creds.account, "0AB");
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 java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@ -48,6 +49,53 @@ import org.testng.annotations.Test;
@Test(groups = "performance", sequential = true, testName = "jclouds.HttpUtils")
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")
void testBouncyCastleDigestSerialResponseTime(byte[] key, String message, String base64Digest)
throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {

View File

@ -42,14 +42,4 @@ public class UtilsTest {
"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>
</parent>
<artifactId>jclouds-ant-plugin</artifactId>
<properties>
<jclouds.test.listener></jclouds.test.listener>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>

View File

@ -23,26 +23,51 @@
*/
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.Task;
import org.jclouds.compute.ComputeService;
import org.jclouds.rimuhosting.miro.RimuHostingContextBuilder;
import org.jclouds.rimuhosting.miro.RimuHostingPropertiesBuilder;
import org.jclouds.compute.ComputeService;
import com.google.common.io.Resources;
import com.google.inject.Injector;
/**
* @author Ivan Meredith
*/
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 String action;
private ServerElement serverElement;
public void execute() throws BuildException {
if (ACTION_CREATE.equalsIgnoreCase(action)) {
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);

View File

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

View File

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

View File

@ -23,13 +23,16 @@
*/
package org.jclouds.vfs.provider.blobstore;
import java.net.URI;
import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.provider.URLFileNameParser;
import org.apache.commons.vfs.provider.UriParser;
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
@ -49,9 +52,11 @@ public class BlobStoreFileNameParser extends URLFileNameParser {
throws FileSystemException {
// 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();
@ -73,7 +78,7 @@ public class BlobStoreFileNameParser extends URLFileNameParser {
FileType fileType = UriParser.normalisePath(name);
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);
}

View File

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

View File

@ -23,11 +23,13 @@
*/
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.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.text.DateFormat;
import java.util.Date;
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.cache.SoftRefFilesCache;
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 com.google.common.collect.Lists;
@ -72,10 +74,10 @@ public class BlobStoreShell {
if (args.length != 1)
throw new IllegalArgumentException(INVALID_SYNTAX);
LocationAndCredentials locationAndCredentials;
URI location;
try {
locationAndCredentials = LocationAndCredentials.parse(args[0]);
checkArgument(locationAndCredentials.uri.getScheme().equals("blobstore"), "wrong scheme");
location = HttpUtils.createUri(args[0]);
checkArgument(location.getScheme().equals("blobstore"), "wrong scheme");
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("%s%n%s", e.getMessage(), INVALID_SYNTAX));
}

View File

@ -35,10 +35,11 @@ public class FileNameTestCase extends AbstractVfsTestCase {
/**
* Tests parsing a URI into its parts.
*/
public void testParseUri() throws Exception {
public void testParseUriNoCreds() throws Exception {
try {
// Simple name
BlobStoreFileName name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance().parseUri(
null, null, "blobstore://service/container/file");
BlobStoreFileName name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance()
.parseUri(null, null, "blobstore://service/container/file");
assertEquals("blobstore", name.getScheme());
assertNull(name.getUserName());
assertNull(name.getPassword());
@ -49,10 +50,15 @@ public class FileNameTestCase extends AbstractVfsTestCase {
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
name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance().parseUri(null, null,
"blobstore://service/container");
BlobStoreFileName name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance()
.parseUri(null, null, "blobstore://service/container");
assertEquals("blobstore", name.getScheme());
assertNull(name.getUserName());
assertNull(name.getPassword());
@ -62,10 +68,16 @@ public class FileNameTestCase extends AbstractVfsTestCase {
assertEquals("/", name.getPath());
assertEquals("blobstore://service/container/", name.getRootURI());
assertEquals("blobstore://service/container/", name.getURI());
fail();
} catch (NullPointerException e) {
}
}
public void testParseUri() throws Exception {
// Name with username
name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance().parseUri(null, null,
"blobstore://user@service/container/file");
BlobStoreFileName name = (BlobStoreFileName) BlobStoreFileNameParser.getInstance().parseUri(
null, null, "blobstore://user@service/container/file");
assertEquals("blobstore", name.getScheme());
assertEquals("user", name.getUserName());
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" />
* @author Adrian Cole
*/
@Timeout(duration = 90, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface HostingDotComVCloudClient extends VCloudClient {
@Override
@Timeout(duration = 240, timeUnit = TimeUnit.SECONDS)
@Timeout(duration = 300, timeUnit = TimeUnit.SECONDS)
HostingDotComVApp instantiateVAppTemplate(String appName, String templateId,
InstantiateVAppTemplateOptions... options);
@Override
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
HostingDotComVApp getVApp(String vAppId);
}