package com.cloud.bridge.service.core.s3; import java.net.MalformedURLException; import java.net.URL; import java.util.Iterator; import java.util.Map; /* @auth John Zucker * Provide a suitable subclass of format class to reflect the choice of bucket referencing format supported by * AWS S3 in constructing the URL for requesting RESTful services. The three possibilities are * (*) hostname followed by bucket as path information (sometimes termed the path style) * (*) bucketname before hostname, so that bucketname appears addressible as a subdomain (termed the subdomain style) * (*) bucketname as a DNS resolvable entry so that path information conveys extra parameters (termed the * virtual hosting style). * The path information is held as a Map of key-value pairs termed pathArgs. * Specification as provided at http://docs.amazonwebservices.com/AmazonS3/latest/dev/VirtualHosting.html. * The class allows for the correct subclass to be selected and the allowable suboptions to be stored. */ public abstract class S3HostCallingFormat { protected static S3HostCallingFormat pathStyleHostFormat = new pathStyleHostFormat(); protected static S3HostCallingFormat subdomainFormat = new subdomainFormat(); protected static S3HostCallingFormat virtualHostingFormat = new virtualHostingFormat(); // implemented in the returned subclasses public abstract boolean usesLocatedBuckets(); // false iff URL is constructed in path style, true otherwise public abstract String getEndpoint (String server, int port, String bucket); public abstract String getPathBase (String bucket, String key); public abstract URL getURL (boolean isSecure, String server, int port, String bucket, String key, Map<?, ?> pathArgs) throws MalformedURLException; public static S3HostCallingFormat getpathStyleHostFormat() { return pathStyleHostFormat; } public static S3HostCallingFormat getsubdomainFormat() { return subdomainFormat; } public static S3HostCallingFormat getvirtualHostingFormat() { return virtualHostingFormat; } // as defined below public static String pathArgsMapToString(Map<?, ?> pathArgs) { StringBuffer pathArgsString = new StringBuffer(); String argument = null; boolean firstArgPosition = true; Iterator<?> argumentIterator; if (pathArgs != null) { for (argumentIterator = pathArgs.keySet().iterator(); argumentIterator.hasNext(); ) { argument = (String)argumentIterator.next(); pathArgsString.append(firstArgPosition ? "?" : "&"); firstArgPosition = false; } } String argumentValue = (String)pathArgs.get(argument); if (argumentValue != null) { pathArgsString.append("="); pathArgsString.append(argumentValue); } return pathArgsString.toString(); } private static class virtualHostingFormat extends S3HostCallingFormat.subdomainFormat { private virtualHostingFormat() { super(); } public String getServer(String server, String bucket) { return bucket; } } private static class subdomainFormat extends S3HostCallingFormat { public boolean usesLocatedBuckets() { return true; } public String getServer(String server, String bucket) { return bucket + "." + server; } public String getEndpoint(String server, int port, String bucket) { return getServer(server, bucket) + ":" + port; } public String getPathBase(String bucket, String key) { return "/" + key; } public URL getURL(boolean isSecure, String server, int port, String bucket, String key, Map <?,?> pathArgs) throws MalformedURLException { if ((bucket == null) || (bucket.length() == 0)) { String pathArguments = pathArgsMapToString(pathArgs); return new URL(isSecure ? "https" : "http", server, port, "/" + pathArguments); } String serverToUse = getServer(server, bucket); String pathBase = getPathBase(bucket, key); String pathArguments = pathArgsMapToString(pathArgs); return new URL(isSecure ? "https" : "http", serverToUse, port, pathBase + pathArguments); } } private static class pathStyleHostFormat extends S3HostCallingFormat { public boolean usesLocatedBuckets() { return false; } public String getPathBase(String bucket, String key) { return isBucketSpecified(bucket) ? "/" + bucket + "/" + key : "/"; } public String getEndpoint(String server, int port, String bucket) { return server + ":" + port; } public URL getURL(boolean isSecure, String server, int port, String bucket, String key, Map<?, ?> pathArgs) throws MalformedURLException { String pathBase = isBucketSpecified(bucket) ? "/" + bucket + "/" + key : "/"; String pathArguments = pathArgsMapToString(pathArgs); return new URL(isSecure ? "https" : "http", server, port, pathBase + pathArguments); } private boolean isBucketSpecified(String bucket) { if (bucket == null) return false; return bucket.length() != 0; } } }