diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e342df --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +target +.settings +.project +.checkstyle +.classpath +*/.checkstyle-rules.xml \ No newline at end of file diff --git a/README b/README index 0470962..81c25d1 100644 --- a/README +++ b/README @@ -1,12 +1,13 @@ In order to build: 1) Download the repository (which if you're doing this, you already have) -2) type "ant compile" (or "ant package if you'd like the full package) +2) type "ant compile" (or "ant package" if you'd like the full package) In order to run unit tests 1) Edit the file src/test/resource/cloudfiles.properties, changing the username and password as needed 2) run "ant test" to run the unit tests -3) run "ant test-report" if you'd like to create a hand-dandy html report on the tests. +3) run "ant test-report" if you'd like to create a handy-dandy html report + on the tests. diff --git a/build.xml b/build.xml index f40ed2d..770b389 100644 --- a/build.xml +++ b/build.xml @@ -8,7 +8,7 @@ - + @@ -57,6 +57,7 @@ @@ -64,8 +65,8 @@ - + @@ -91,7 +92,7 @@ - + @@ -100,7 +101,7 @@ - + @@ -127,12 +128,13 @@ - + + - + @@ -142,7 +144,7 @@ - + diff --git a/cloudfiles.bat b/cloudfiles.bat new file mode 100644 index 0000000..50b11cb --- /dev/null +++ b/cloudfiles.bat @@ -0,0 +1,4 @@ +@ECHO OFF +SET SCRIPT_DIR=%~dp0 +java -classpath %SCRIPT_DIR%lib/httpcore-4.1.jar;%SCRIPT_DIR%lib/commons-cli-1.1.jar;%SCRIPT_DIR%lib/httpclient-4.0.3.jar;%SCRIPT_DIR%lib/commons-lang-2.4.jar;%SCRIPT_DIR%lib/junit.jar;%SCRIPT_DIR%lib/commons-codec-1.3.jar;%SCRIPT_DIR%lib/commons-io-1.4.jar;%SCRIPT_DIR%lib/commons-logging-1.1.1.jar;%SCRIPT_DIR%lib/log4j-1.2.15.jar;%SCRIPT_DIR%dist/java-cloudfiles.jar;%SCRIPT_DIR%. com.rackspacecloud.client.cloudfiles.sample.FilesCli %* +@ECHO ON diff --git a/cloudfiles.properties b/cloudfiles.properties index 2199a22..ff04326 100644 --- a/cloudfiles.properties +++ b/cloudfiles.properties @@ -1,5 +1,9 @@ version=v1 -auth_url=https://api.mosso.com/auth connection_timeout=5000 + +# Auth info +auth_url=https://auth.api.rackspacecloud.com/v1.0 auth_token_name=X-Auth-Token +#auth_user_header=X-Storage-User +#auth_pass_header=X-Storage-Pass diff --git a/cloudfiles.sh b/cloudfiles.sh new file mode 100755 index 0000000..c9572a4 --- /dev/null +++ b/cloudfiles.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +export CLASSPATH=lib/httpcore-4.1.jar:lib/commons-cli-1.1.jar:lib/httpclient-4.0.3.jar:lib/commons-lang-2.4.jar:lib/junit.jar:lib/commons-codec-1.3.jar:lib/commons-io-1.4.jar:lib/commons-logging-1.1.1.jar:lib/log4j-1.2.15.jar:dist/java-cloudfiles.jar:. + +java com.rackspacecloud.client.cloudfiles.sample.FilesCli $@ diff --git a/lib/commons-httpclient-3.1.jar b/lib/commons-httpclient-3.1.jar deleted file mode 100644 index 7c59774..0000000 Binary files a/lib/commons-httpclient-3.1.jar and /dev/null differ diff --git a/lib/httpclient-4.1.3.jar b/lib/httpclient-4.1.3.jar new file mode 100644 index 0000000..dfa8793 Binary files /dev/null and b/lib/httpclient-4.1.3.jar differ diff --git a/lib/httpcore-4.1.4.jar b/lib/httpcore-4.1.4.jar new file mode 100644 index 0000000..1606a2e Binary files /dev/null and b/lib/httpcore-4.1.4.jar differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..568610c --- /dev/null +++ b/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + + org.sonatype.oss + oss-parent + 7 + + + java-cloudfiles + java-cloudfiles + com.rackspacecloud + 1.0-SNAPSHOT + jar + + + + commons-cli + commons-cli + 1.2 + + + commons-io + commons-io + 2.1 + + + commons-lang + commons-lang + 2.6 + + + commons-codec + commons-codec + 1.6 + + + commons-logging + commons-logging + 1.1.1 + + + org.apache.httpcomponents + httpcore + 4.1.4 + + + org.apache.httpcomponents + httpclient + 4.1.2 + + + log4j + log4j + 1.2.16 + + + junit + junit + 4.10 + test + + + + + install + + + src/main/java/com/rackspacecloud/client/cloudfiles/ + com/rackspacecloud/client/cloudfiles/ + + MIME.types + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.8 + + true + true + + + + + + + scm:git:git@github.com/rackspace/java-cloudfiles.git + scm:git:git@github.com/rackspace/java-cloudfiles.git + git@github.com/rackspace/java-cloudfiles.git + + \ No newline at end of file diff --git a/run_cli.sh b/run_cli.sh deleted file mode 100755 index 6084f85..0000000 --- a/run_cli.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -export CLASSPATH=lib/commons-cli-1.1.jar:lib/commons-httpclient-3.1.jar:lib/commons-lang-2.4.jar:lib/junit.jar:lib/commons-codec-1.3.jar:lib/commons-io-1.4.jar:lib/commons-logging-1.1.1.jar:lib/log4j-1.2.15.jar:dist/cloud_files.jar:. - -java com.mosso.client.cloudfiles.sample.FilesCli diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesCDNContainer.java b/src/main/java/com/mosso/client/cloudfiles/FilesCDNContainer.java deleted file mode 100644 index a2eadcb..0000000 --- a/src/main/java/com/mosso/client/cloudfiles/FilesCDNContainer.java +++ /dev/null @@ -1,116 +0,0 @@ -/** - * - */ -package com.mosso.client.cloudfiles; - -/** - * @author lvaughn - * - */ -public class FilesCDNContainer { - private boolean enabled; -// private String userAgentACL; -// private String referrerACL; - private int ttl; - private String cdnURL; - private String name; - - public FilesCDNContainer() { - } - - public FilesCDNContainer(String cdnURL) { - this.cdnURL = cdnURL; - } - - public FilesCDNContainer(String name, boolean enabled, int ttl) { - this.enabled = enabled; - this.ttl = ttl; - this.name = name; - //this(enabled, ttl, null, null); - } - -// public FilesCDNContainer(boolean enabled, int ttl, String userAgentACL, String referrerACL) { -// this.enabled = enabled; -// this.ttl = ttl; -// this.userAgentACL = userAgentACL; -// this.referrerACL = referrerACL; -// } - - /** - * @return Is this container CDN enabled - */ - public boolean isEnabled() { - return enabled; - } - /** - * @param enabled the enabled to set - */ - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } -// /** -// * @return the userAgentACL -// */ -// public String getUserAgentACL() { -// return userAgentACL; -// } -// /** -// * @param userAgentACL the userAgentACL to set -// */ -// public void setUserAgentACL(String userAgentACL) { -// this.userAgentACL = userAgentACL; -// } -// /** -// * @return the refererACL -// */ -// public String getReferrerACL() { -// return referrerACL; -// } -// /** -// * @param refererACL the refererACL to set -// */ -// public void setReferrerACL(String referrerACL) { -// this.referrerACL = referrerACL; -// } - /** - * @return the ttl - */ - public int getTtl() { - return ttl; - } - /** - * @param ttl the ttl to set - */ - public void setTtl(int ttl) { - this.ttl = ttl; - } - - /** - * @return the cdnURL - */ - public String getCdnURL() { - return cdnURL; - } - - /** - * @param cdnURL the cdnURL to set - */ - public void setCdnURL(String cdnURL) { - this.cdnURL = cdnURL; - } - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - -} diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesUtil.java b/src/main/java/com/mosso/client/cloudfiles/FilesUtil.java deleted file mode 100644 index 079d299..0000000 --- a/src/main/java/com/mosso/client/cloudfiles/FilesUtil.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * See COPYING for license information. - */ - -package com.mosso.client.cloudfiles; - -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.IOException; -import java.util.Properties; - -import org.apache.log4j.Logger; - -/** - * Cloud Files utilities - */ -public class FilesUtil { - private static Logger logger = Logger.getLogger(FilesUtil.class); - /** - * The name of the properties file we're looking for - */ - private final static String file = "cloudfiles.properties"; - - /** - * A cache of the properties - */ - private static Properties props = null; - - /** - * Find the properties file in the class path and load it. - * - * @throws IOException - */ - private static void loadPropertiesFromClasspath() throws IOException { - props = new Properties(); - InputStream inputStream = FilesUtil.class.getClassLoader() - .getResourceAsStream(file); - - if (inputStream == null) { - throw new FileNotFoundException("Property file '" + file - + "' not found in the classpath"); - } - props.load(inputStream); - } - - /** - * Look up a property from the properties file. - * - * @param key The name of the property to be found - * @return The value of the property - */ - public static String getProperty(String key) - { - if (props == null) - { - try - { - loadPropertiesFromClasspath(); - } - catch (Exception IOException) - { - logger.warn("Unable to load properties file."); - return null; - } - } - return props.getProperty(key); - } - - /** - * Look up a property from the properties file. - * - * @param key The name of the property to be found - * @return The value of the property - */ - public static String getProperty(String key, String defaultValue) - { - if (props == null) - { - try - { - loadPropertiesFromClasspath(); - } - catch (Exception IOException) - { - logger.warn("Unable to load properties file."); - return null; - } - } - return props.getProperty(key, defaultValue); - } - - /** - * Looks up the value of a key from the properties file and converts it to an integer. - * - * @param key - * @return The value of that key - */ - public static int getIntProperty(String key) { - String property = getProperty(key); - - if (property == null) { - logger.warn("Could not load integer property " + key); - return -1; - } - try { - return Integer.parseInt(property); - } - catch (NumberFormatException nfe) { - logger.warn("Invalid format for a number in properties file: " + property, nfe); - return -1; - } - } -} diff --git a/src/main/java/com/mosso/client/cloudfiles/wrapper/RequestEntityWrapper.java b/src/main/java/com/mosso/client/cloudfiles/wrapper/RequestEntityWrapper.java deleted file mode 100644 index 7b4d7f4..0000000 --- a/src/main/java/com/mosso/client/cloudfiles/wrapper/RequestEntityWrapper.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * - */ -package com.mosso.client.cloudfiles.wrapper; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.commons.httpclient.methods.RequestEntity; - -import com.mosso.client.cloudfiles.IFilesTransferCallback; - -/** - * @author lvaughn - * - */ -public class RequestEntityWrapper implements RequestEntity { - private RequestEntity entity; - private IFilesTransferCallback callback = null; - - public RequestEntityWrapper(RequestEntity entity, IFilesTransferCallback callback) { - this.entity = entity; - this.callback = callback; - } - - /* (non-Javadoc) - * @see org.apache.commons.httpclient.methods.RequestEntity#getContentLength() - */ - public long getContentLength() { - return entity.getContentLength(); - } - - /* (non-Javadoc) - * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType() - */ - public String getContentType() { - return entity.getContentType(); - } - - /* (non-Javadoc) - * @see org.apache.commons.httpclient.methods.RequestEntity#isRepeatable() - */ - public boolean isRepeatable() { - return entity.isRepeatable(); - } - - /* (non-Javadoc) - * @see org.apache.commons.httpclient.methods.RequestEntity#writeRequest(java.io.OutputStream) - */ - public void writeRequest(OutputStream stream) throws IOException { - entity.writeRequest(new OutputStreamWrapper(stream, callback)); - - } - -} diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesAccountInfo.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesAccountInfo.java similarity index 95% rename from src/main/java/com/mosso/client/cloudfiles/FilesAccountInfo.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesAccountInfo.java index 6d80c1b..950bc5d 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesAccountInfo.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesAccountInfo.java @@ -1,7 +1,7 @@ /** * */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; /** * @author lvaughn diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesAuthorizationException.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesAuthorizationException.java similarity index 83% rename from src/main/java/com/mosso/client/cloudfiles/FilesAuthorizationException.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesAuthorizationException.java index 9ce2935..e5cb01a 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesAuthorizationException.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesAuthorizationException.java @@ -2,10 +2,10 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.StatusLine; +import org.apache.http.Header; +import org.apache.http.StatusLine; public class FilesAuthorizationException extends FilesException { diff --git a/src/main/java/com/rackspacecloud/client/cloudfiles/FilesCDNContainer.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesCDNContainer.java new file mode 100644 index 0000000..9752907 --- /dev/null +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesCDNContainer.java @@ -0,0 +1,167 @@ +/** + * + */ +package com.rackspacecloud.client.cloudfiles; + +/** + * @author lvaughn + * + */ +public class FilesCDNContainer { + private boolean enabled; + private String userAgentACL; + private String referrerACL; + private int ttl; + private String cdnURL; + private String sslURL = null; + private String streamingURL = null; + private String name; + private boolean retainLogs; + + /** + * @return the retainLogs + */ + public boolean getRetainLogs() { + return retainLogs; + } + + /** + * @param retainLogs the retainLogs to set + */ + public void setRetainLogs(boolean retainLogs) { + this.retainLogs = retainLogs; + } + + public FilesCDNContainer() { + } + + public FilesCDNContainer(String cdnURL) { + this.cdnURL = cdnURL; + } + + public FilesCDNContainer(String cdnURL, String sslUrl) { + this.cdnURL = cdnURL; + this.sslURL = sslUrl; + } + + public FilesCDNContainer(String cdnURL, String sslUrl, String streamingUrl) { + this.cdnURL = cdnURL; + this.sslURL = sslUrl; + this.streamingURL = streamingUrl; + } + + public FilesCDNContainer(String name, boolean enabled, int ttl, boolean retainLogs) { + this.enabled = enabled; + this.ttl = ttl; + this.name = name; + this.retainLogs = retainLogs; + } + + + + /** + * @return Is this container CDN enabled + */ + public boolean isEnabled() { + return enabled; + } + /** + * @param enabled the enabled to set + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + /** + * @return the userAgentACL + */ + public String getUserAgentACL() { + return userAgentACL; + } + /** + * @param userAgentACL the userAgentACL to set + */ + public void setUserAgentACL(String userAgentACL) { + this.userAgentACL = "".equals(userAgentACL) ? null : userAgentACL; + } + /** + * @return the refererACL + */ + public String getReferrerACL() { + return referrerACL; + } + /** + * @param refererACL the refererACL to set + */ + public void setReferrerACL(String referrerACL) { + this.referrerACL = "".equals(referrerACL) ? null : referrerACL; + } + /** + * @return the ttl + */ + public int getTtl() { + return ttl; + } + /** + * @param ttl the ttl to set + */ + public void setTtl(int ttl) { + this.ttl = ttl; + } + + /** + * @return the cdnURL + */ + public String getCdnURL() { + return cdnURL; + } + + /** + * @param cdnURL the cdnURL to set + */ + public void setCdnURL(String cdnURL) { + this.cdnURL = cdnURL; + } + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return The URL for accessing content in this container via the CDN + */ + public String getSSLURL() { + return sslURL; + } + + /** + * + * @param sslURL the sslURL to set + */ + void setSSLURL(String sslURL) { + this.sslURL = sslURL; + } + + /** + * @return The Streaming URL for accessing content in this container via the CDN + */ + public String getStreamingURL() { + return this.streamingURL; + } + + /** + * + * @param sstreamingURL the streamingURL to set + */ + void setStreamingURL(String streamingURL) { + this.streamingURL = streamingURL; + } +} diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesClient.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesClient.java similarity index 54% rename from src/main/java/com/mosso/client/cloudfiles/FilesClient.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesClient.java index 965c4ea..20dd367 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesClient.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesClient.java @@ -2,49 +2,73 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; -import org.apache.log4j.Logger; -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.EncoderException; -import org.apache.commons.codec.net.URLCodec; -import org.apache.commons.httpclient.*; -import org.apache.commons.httpclient.methods.*; -import org.apache.commons.httpclient.params.HttpMethodParams; -import org.apache.commons.lang.text.StrTokenizer; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import com.mosso.client.cloudfiles.wrapper.RequestEntityWrapper; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.EncoderException; +import org.apache.commons.codec.net.URLCodec; +import org.apache.commons.lang.text.StrTokenizer; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpException; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.PlainSocketFactory; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.FileEntity; +import org.apache.http.entity.InputStreamEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpParams; +import org.apache.http.protocol.HTTP; +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import com.rackspacecloud.client.cloudfiles.wrapper.RequestEntityWrapper; + /** * * A client for Cloud Files. Here follows a basic example of logging in, creating a container and an * object, retrieving the object, and then deleting both the object and container. For more examples, - * see the code in com.mosso.client.cloudfiles.sample, which contains a series of examples. + * see the code in com.rackspacecloud.client.cloudfiles.sample, which contains a series of examples. * *
  * 
@@ -76,12 +100,12 @@
  *  assert(myClient.deleteContainer("myContainer");
  * 
* - * @see com.mosso.client.cloudfiles.sample.FilesCli - * @see com.mosso.client.cloudfiles.sample.FilesAuth - * @see com.mosso.client.cloudfiles.sample.FilesCopy - * @see com.mosso.client.cloudfiles.sample.FilesList - * @see com.mosso.client.cloudfiles.sample.FilesRemove - * @see com.mosso.client.cloudfiles.sample.FilesMakeContainer + * @see com.rackspacecloud.client.cloudfiles.sample.FilesCli + * @see com.rackspacecloud.client.cloudfiles.sample.FilesAuth + * @see com.rackspacecloud.client.cloudfiles.sample.FilesCopy + * @see com.rackspacecloud.client.cloudfiles.sample.FilesList + * @see com.rackspacecloud.client.cloudfiles.sample.FilesRemove + * @see com.rackspacecloud.client.cloudfiles.sample.FilesMakeContainer * * @author lvaughn */ @@ -99,40 +123,73 @@ public class FilesClient private String authToken = null; private boolean isLoggedin = false; private boolean useETag = true; - - private HttpClient client = new HttpClient(new MultiThreadedHttpConnectionManager()); + private boolean snet = false; + private String snetAddr = "https://snet-"; + + private HttpClient client = null; private static Logger logger = Logger.getLogger(FilesClient.class); /** + * @param client The HttpClient to talk to Swift * @param username The username to log in to * @param password The password * @param account The Cloud Files account to use * @param connectionTimeOut The connection timeout, in ms. */ - public FilesClient(String username, String password, String account, int connectionTimeOut) - { + public FilesClient(HttpClient client, String username, String password, String authUrl, String account, int connectionTimeOut) { + this.client = client; this.username = username; this.password = password; this.account = account; - if (account != null && account.length() > 0) { - this.authenticationURL = FilesUtil.getProperty("auth_url")+VERSION+"/"+account+FilesUtil.getProperty("auth_url_post"); + if(authUrl == null) { + authUrl = FilesUtil.getProperty("auth_url"); + } + if(account != null && account.length() > 0) { + this.authenticationURL = authUrl + VERSION + "/" + account + FilesUtil.getProperty("auth_url_post"); } else { - this.authenticationURL = FilesUtil.getProperty("auth_url"); + this.authenticationURL = authUrl; } this.connectionTimeOut = connectionTimeOut; - client.getParams().setParameter("http.socket.timeout", this.connectionTimeOut ); setUserAgent(FilesConstants.USER_AGENT); - if (logger.isDebugEnabled()) { - logger.debug("UserName: "+ this.username); - logger.debug("AuthenticationURL: "+ this.authenticationURL); - logger.debug("ConnectionTimeOut: "+ this.connectionTimeOut); + if(logger.isDebugEnabled()) { + logger.debug("UserName: " + this.username); + logger.debug("AuthenticationURL: " + this.authenticationURL); + logger.debug("ConnectionTimeOut: " + this.connectionTimeOut); } - //logger.debug("LGV:" + client.getHttpConnectionManager()); - } + } + + /** + * @param username The username to log in to + * @param password The password + * @param account The Cloud Files account to use + * @param connectionTimeOut The connection timeout, in ms. + */ + public FilesClient(String username, String password, String authUrl, String account, final int connectionTimeOut) + { + this(new DefaultHttpClient() { + protected HttpParams createHttpParams() { + BasicHttpParams params = new BasicHttpParams(); + org.apache.http.params.HttpConnectionParams.setSoTimeout(params, connectionTimeOut); + params.setParameter("http.socket.timeout", connectionTimeOut); + return params; + } + + @Override + protected ClientConnectionManager createClientConnectionManager() { + SchemeRegistry schemeRegistry = new SchemeRegistry(); + schemeRegistry.register( + new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); + schemeRegistry.register( + new Scheme("https", 443, SSLSocketFactory.getSocketFactory())); + return new ThreadSafeClientConnManager(createHttpParams(), schemeRegistry); + } + }, username, password, authUrl, account, connectionTimeOut); + + } /** * This method uses the default connection time out of CONNECTON_TIMEOUT. If account @@ -140,11 +197,11 @@ public FilesClient(String username, String password, String account, int connect * * @param username * @param password - * @param account + * @param authUrl */ - public FilesClient(String username, String password, String account) + public FilesClient(String username, String password, String authUrl) { - this (username, password, account, FilesUtil.getIntProperty("connection_timeout")); + this (username, password, authUrl, null, FilesUtil.getIntProperty("connection_timeout")); } /** @@ -155,7 +212,7 @@ public FilesClient(String username, String password, String account) */ public FilesClient(String username, String apiAccessKey) { - this (username, apiAccessKey, null, FilesUtil.getIntProperty("connection_timeout")); + this (username, apiAccessKey, null, null, FilesUtil.getIntProperty("connection_timeout")); //lConnectionManagerogger.warn("LGV"); //logger.debug("LGV:" + client.getHttpConnectionManager()); } @@ -168,7 +225,8 @@ public FilesClient(String username, String apiAccessKey) public FilesClient() { this (FilesUtil.getProperty("username"), - FilesUtil.getProperty("password"), + FilesUtil.getProperty("password"), + null, FilesUtil.getProperty("account"), FilesUtil.getIntProperty("connection_timeout")); } @@ -209,33 +267,53 @@ public void setAccount(String account) */ public boolean login() throws IOException, HttpException { - GetMethod method = new GetMethod(authenticationURL); - method.getParams().setSoTimeout(connectionTimeOut); - - method.setRequestHeader(FilesConstants.X_STORAGE_USER, username); - method.setRequestHeader(FilesConstants.X_STORAGE_PASS, password); - - logger.debug ("Logging in user: "+username+" using URL: "+authenticationURL); - client.executeMethod(method); + HttpGet method = new HttpGet(authenticationURL); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); - FilesResponse response = new FilesResponse(method); + method.setHeader(FilesUtil.getProperty("auth_user_header", FilesConstants.X_STORAGE_USER_DEFAULT), + username); + method.setHeader(FilesUtil.getProperty("auth_pass_header", FilesConstants.X_STORAGE_PASS_DEFAULT), + password); + FilesResponse response = new FilesResponse(client.execute(method)); + if (response.loginSuccess()) { isLoggedin = true; - storageURL = response.getStorageURL(); + if(usingSnet() || envSnet()){ + storageURL = snetAddr + response.getStorageURL().substring(8); + } + else{ + storageURL = response.getStorageURL(); + } cdnManagementURL = response.getCDNManagementURL(); authToken = response.getAuthToken(); logger.debug("storageURL: " + storageURL); logger.debug("authToken: " + authToken); logger.debug("cdnManagementURL:" + cdnManagementURL); - logger.debug("ConnectionManager:" + client.getHttpConnectionManager()); + logger.debug("ConnectionManager:" + client.getConnectionManager()); } - method.releaseConnection(); + method.abort(); return this.isLoggedin; } + + /** + * Log in to CloudFiles. This method performs the authentication and sets up the client's internal state. + * + * @throws IOException There was an IO error doing network communication + * @throws HttpException There was an error with the http protocol + */ + public boolean login(String authToken, String storageURL, String cdnManagmentUrl) throws IOException, HttpException + { + isLoggedin = true; + this.storageURL = storageURL; + this.cdnManagementURL = cdnManagmentUrl; + this.authToken = authToken; + return true; + } + /** * List all of the containers available in an account, ordered by container name. * @@ -286,33 +364,29 @@ public List listContainersInfo(int limit, String marker) thr if (!this.isLoggedin()) { throw new FilesAuthorizationException("You must be logged in", null, null); } - GetMethod method = null; + HttpGet method = null; try { - method = new GetMethod(storageURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - LinkedList parameters = new LinkedList(); if(limit > 0) { - parameters.add(new NameValuePair("limit", String.valueOf(limit))); + parameters.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if(marker != null) { - parameters.add(new NameValuePair("marker", marker)); + parameters.add(new BasicNameValuePair("marker", marker)); } - parameters.add(new NameValuePair("format", "xml")); - method.setQueryString(parameters.toArray(new NameValuePair[parameters.size()])); - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + parameters.add(new BasicNameValuePair("format", "xml")); + String uri = makeURI(storageURL, parameters); + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.removeRequestHeader(FilesConstants.X_AUTH_TOKEN); + method.removeHeaders(FilesConstants.X_AUTH_TOKEN); if(login()) { - method = new GetMethod(storageURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - method.setQueryString(parameters.toArray(new NameValuePair[parameters.size()])); - client.executeMethod(method); - response = new FilesResponse(method); + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -352,7 +426,7 @@ else if ("count".equals(data.getNodeName())) { count = Integer.parseInt(data.getTextContent()); } else { - logger.warn("Unexpected container-info tag:" + data.getNodeName()); + logger.debug("Unexpected container-info tag:" + data.getNodeName()); } } if (name != null) { @@ -379,7 +453,7 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) } finally { if (method != null) - method.releaseConnection(); + method.abort(); } } @@ -432,37 +506,30 @@ public List listContainers(int limit, String marker) throws IOEx if (!this.isLoggedin()) { throw new FilesAuthorizationException("You must be logged in", null, null); } - GetMethod method = null; + HttpGet method = null; try { - method = new GetMethod(storageURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); LinkedList parameters = new LinkedList(); if(limit > 0) { - parameters.add(new NameValuePair("limit", String.valueOf(limit))); + parameters.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if(marker != null) { - parameters.add(new NameValuePair("marker", marker)); + parameters.add(new BasicNameValuePair("marker", marker)); } - if (parameters.size() > 0) { - method.setQueryString(parameters.toArray(new NameValuePair[parameters.size()])); - } - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + String uri = parameters.size() > 0 ? makeURI(storageURL, parameters) : storageURL; + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method = new GetMethod(storageURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - if (parameters.size() > 0) { - method.setQueryString(parameters.toArray(new NameValuePair[parameters.size()])); - } - client.executeMethod(method); - response = new FilesResponse(method); + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -472,7 +539,7 @@ public List listContainers(int limit, String marker) throws IOEx if (response.getStatusCode() == HttpStatus.SC_OK) { // logger.warn(method.getResponseCharSet()); - StrTokenizer tokenize = new StrTokenizer(inputStreamToString(response.getResponseBodyAsStream(), method.getResponseCharSet())); + StrTokenizer tokenize = new StrTokenizer(response.getResponseBodyAsString()); tokenize.setDelimiterString("\n"); String [] containers = tokenize.getTokenArray(); ArrayList containerList = new ArrayList(); @@ -494,10 +561,11 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) } } catch (Exception ex) { + ex.printStackTrace(); throw new FilesException("Unexpected error, probably parsing Server XML", ex); } finally { - if (method != null) method.releaseConnection(); + if (method != null) method.abort(); } } @@ -516,52 +584,66 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) * @throws FilesException There was another error in the request to the server. * @throws FilesAuthorizationException The client's login was invalid. */ - public List listObjectsStaringWith (String container, String startsWith, String path, int limit, String marker) throws IOException, HttpException, FilesException + public List listObjectsStartingWith (String container, String startsWith, String path, int limit, String marker) throws IOException, FilesException { + return listObjectsStartingWith(container, startsWith, path, limit, marker, null); + } + /** + * List all of the objects in a container with the given starting string. + * + * @param container The container name + * @param startsWith The string to start with + * @param path Only look for objects in this path + * @param limit Return at most limit objects + * @param marker Returns objects lexicographically greater than marker. Used in conjunction with limit to paginate the list. + * @param delimter Use this argument as the delimiter that separates "directories" + * + * @return A list of FilesObjects starting with the given string + * @throws IOException There was an IO error doing network communication + * @throws HttpException There was an error with the http protocol + * @throws FilesException There was another error in the request to the server. + * @throws FilesAuthorizationException The client's login was invalid. + */ + public List listObjectsStartingWith (String container, String startsWith, String path, int limit, String marker, Character delimiter) throws IOException, FilesException + { if (!this.isLoggedin()) { throw new FilesAuthorizationException("You must be logged in", null, null); } - if (!isValidContianerName(container)) { + if (!isValidContainerName(container)) { throw new FilesInvalidNameException(container); } - GetMethod method = null; - try { - method = new GetMethod(storageURL+"/"+sanitizeForURI(container)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - + HttpGet method = null; + try { LinkedList parameters = new LinkedList(); - parameters.add(new NameValuePair ("format", "xml")); + parameters.add(new BasicNameValuePair ("format", "xml")); if (startsWith != null) { - parameters.add(new NameValuePair (FilesConstants.LIST_CONTAINER_NAME_QUERY, startsWith)); - } + parameters.add(new BasicNameValuePair (FilesConstants.LIST_CONTAINER_NAME_QUERY, startsWith)); } if(path != null) { - parameters.add(new NameValuePair("path", path)); + parameters.add(new BasicNameValuePair("path", path)); } if(limit > 0) { - parameters.add(new NameValuePair("limit", String.valueOf(limit))); + parameters.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if(marker != null) { - parameters.add(new NameValuePair("marker", marker)); + parameters.add(new BasicNameValuePair("marker", marker)); } - - if (parameters.size() > 0) { - method.setQueryString(parameters.toArray(new NameValuePair[parameters.size()])); + if (delimiter != null) { + parameters.add(new BasicNameValuePair("delimiter", delimiter.toString())); } - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + + String uri = parameters.size() > 0 ? makeURI(storageURL+"/"+sanitizeForURI(container), parameters) : storageURL; + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.removeRequestHeader(FilesConstants.X_AUTH_TOKEN); + method.removeHeaders(FilesConstants.X_AUTH_TOKEN); if(login()) { - method = new GetMethod(storageURL+"/"+sanitizeForURI(container)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - if (parameters.size() > 0) { - method.setQueryString(parameters.toArray(new NameValuePair[parameters.size()])); - } - client.executeMethod(method); - response = new FilesResponse(method); + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -584,13 +666,19 @@ public List listObjectsStaringWith (String container, String starts NodeList objectNodes = containerList.getChildNodes(); for(int i=0; i < objectNodes.getLength(); ++i) { Node objectNode = objectNodes.item(i); - if(!"object".equals(objectNode.getNodeName())) continue; + String nodeName = objectNode.getNodeName(); + if(!("object".equals(nodeName) || "subdir".equals(nodeName))) continue; String name = null; String eTag = null; long size = -1; String mimeType = null; String lastModified = null; NodeList objectData = objectNode.getChildNodes(); + if ("subdir".equals(nodeName)) { + size = 0; + mimeType = "application/directory"; + name = objectNode.getAttributes().getNamedItem("name").getNodeValue(); + } for(int j=0; j < objectData.getLength(); ++j) { Node data = objectData.item(j); if ("name".equals(data.getNodeName())) { @@ -616,7 +704,7 @@ else if ("last_modified".equals(data.getNodeName())) { FilesObject obj = new FilesObject(name, container, this); if (eTag != null) obj.setMd5sum(eTag); if (mimeType != null) obj.setMimeType(mimeType); - if (size > 0) obj.setSize(size); + if (size >= 0) obj.setSize(size); if (lastModified != null) obj.setLastModified(lastModified); objectList.add(obj); } @@ -636,19 +724,54 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) throw new FilesException("Unexpected Server Result", response.getResponseHeaders(), response.getStatusLine()); } } + catch (FilesNotFoundException fnfe) { + throw fnfe; + } catch (Exception ex) { logger.error("Error parsing xml", ex); throw new FilesException("Error parsing server resposne", ex); } finally { - if (method != null) method.releaseConnection(); + if (method != null) method.abort(); } } + /** + * List the objects in a container in lexicographic order. + * + * @param container The container name + * + * @return A list of FilesObjects starting with the given string + * @throws IOException There was an IO error doing network communication + * @throws HttpException There was an error with the http protocol + * @throws FilesException There was another error in the request to the server. + * @throws FilesAuthorizationException The client's login was invalid. + */ + public List listObjects(String container) throws IOException, FilesAuthorizationException, FilesException { + return listObjectsStartingWith(container, null, null, -1, null, null); + } + + /** + * List the objects in a container in lexicographic order. + * + * @param container The container name + * @param delimter Use this argument as the delimiter that separates "directories" + * + * @return A list of FilesObjects starting with the given string + * @throws IOException There was an IO error doing network communication + * @throws HttpException There was an error with the http protocol + * @throws FilesException There was another error in the request to the server. + * @throws FilesAuthorizationException The client's login was invalid. + */ + public List listObjects(String container, Character delimiter) throws IOException, FilesAuthorizationException, FilesException { + return listObjectsStartingWith(container, null, null, -1, null, delimiter); + } + /** * List the objects in a container in lexicographic order. * * @param container The container name + * @param limit Return at most limit objects * * @return A list of FilesObjects starting with the given string * @throws IOException There was an IO error doing network communication @@ -656,24 +779,23 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) * @throws FilesException There was another error in the request to the server. * @throws FilesAuthorizationException The client's login was invalid. */ - public List listObjects(String container) throws IOException, HttpException, FilesAuthorizationException, FilesException { - return listObjectsStaringWith(container, null, null, -1, null); + public List listObjects(String container, int limit) throws IOException, HttpException, FilesAuthorizationException, FilesException { + return listObjectsStartingWith(container, null, null, limit, null, null); } /** * List the objects in a container in lexicographic order. * * @param container The container name - * @param limit Return at most limit objects + * @param path Only look for objects in this path * * @return A list of FilesObjects starting with the given string * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException There was another error in the request to the server. - * @throws FilesAuthorizationException The client's login was invalid. */ - public List listObjects(String container, int limit) throws IOException, HttpException, FilesAuthorizationException, FilesException { - return listObjectsStaringWith(container, null, null, limit, null); + public List listObjects(String container, String path) throws IOException, HttpException, FilesAuthorizationException, FilesException { + return listObjectsStartingWith(container, null, path, -1, null, null); } /** @@ -681,14 +803,15 @@ public List listObjects(String container, int limit) throws IOExcep * * @param container The container name * @param path Only look for objects in this path + * @param delimter Use this argument as the delimiter that separates "directories" * * @return A list of FilesObjects starting with the given string * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException There was another error in the request to the server. */ - public List listObjects(String container, String path) throws IOException, HttpException, FilesAuthorizationException, FilesException { - return listObjectsStaringWith(container, null, path, -1, null); + public List listObjects(String container, String path, Character delimiter) throws IOException, HttpException, FilesAuthorizationException, FilesException { + return listObjectsStartingWith(container, null, path, -1, null, delimiter); } /** @@ -706,7 +829,7 @@ public List listObjects(String container, String path) throws IOExc * @throws FilesAuthorizationException The client's login was invalid. */ public List listObjects(String container, String path, int limit) throws IOException, HttpException, FilesAuthorizationException, FilesException { - return listObjectsStaringWith(container, null, path, limit, null); + return listObjectsStartingWith(container, null, path, limit, null); } /** @@ -723,7 +846,7 @@ public List listObjects(String container, String path, int limit) t * @throws FilesException There was another error in the request to the server. */ public List listObjects(String container, String path, int limit, String marker) throws IOException, HttpException, FilesAuthorizationException, FilesException { - return listObjectsStaringWith(container, null, path, limit, marker); + return listObjectsStartingWith(container, null, path, limit, marker); } /** @@ -740,7 +863,7 @@ public List listObjects(String container, String path, int limit, S * @throws FilesAuthorizationException The client's login was invalid. */ public List listObjects(String container, int limit, String marker) throws IOException, HttpException, FilesAuthorizationException, FilesException { - return listObjectsStaringWith(container, null, null, limit, marker); + return listObjectsStartingWith(container, null, null, limit, marker); } /** @@ -776,35 +899,40 @@ public boolean containerExists (String container) throws IOException, HttpExcept public FilesAccountInfo getAccountInfo() throws IOException, HttpException, FilesAuthorizationException, FilesException { if (this.isLoggedin()) { - HeadMethod method = new HeadMethod(storageURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); + HttpHead method = null; - FilesResponse response = new FilesResponse(method); - if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.removeRequestHeader(FilesConstants.X_AUTH_TOKEN); - if(login()) { - method = new HeadMethod(storageURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - response = new FilesResponse(method); + try { + method = new HttpHead(storageURL); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.removeHeaders(FilesConstants.X_AUTH_TOKEN); + if(login()) { + method.abort(); + method = new HttpHead(storageURL); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); + } + else { + throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); + } + } + + if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) + { + int nContainers = response.getAccountContainerCount(); + long totalSize = response.getAccountBytesUsed(); + return new FilesAccountInfo(totalSize,nContainers); } else { - throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); + throw new FilesException("Unexpected return from server", response.getResponseHeaders(), response.getStatusLine()); } } - - if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) - { - int nContainers = response.getAccountContainerCount(); - long totalSize = response.getAccountBytesUsed(); - return new FilesAccountInfo(totalSize,nContainers); - } - else { - throw new FilesException("Unexpected return from server", response.getResponseHeaders(), response.getStatusLine()); - } + finally { + if (method != null) method.abort(); + } } else { throw new FilesAuthorizationException("You must be logged in", null, null); @@ -825,26 +953,23 @@ public FilesContainerInfo getContainerInfo (String container) throws IOException { if (this.isLoggedin()) { - if (isValidContianerName(container)) + if (isValidContainerName(container)) { - HeadMethod method = null; + HttpHead method = null; try { - method = new HeadMethod(storageURL+"/"+sanitizeForURI(container)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - - FilesResponse response = new FilesResponse(method); + method = new HttpHead(storageURL+"/"+sanitizeForURI(container)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.removeRequestHeader(FilesConstants.X_AUTH_TOKEN); + method.removeHeaders(FilesConstants.X_AUTH_TOKEN); if(login()) { - method = new HeadMethod(storageURL+"/"+sanitizeForURI(container)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - response = new FilesResponse(method); + method = new HttpHead(storageURL+"/"+sanitizeForURI(container)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -866,7 +991,7 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) } } finally { - if (method != null) method.releaseConnection(); + if (method != null) method.abort(); } } else @@ -892,26 +1017,22 @@ public void createContainer(String name) throws IOException, HttpException, File { if (this.isLoggedin()) { - if (isValidContianerName(name)) + if (isValidContainerName(name)) { - // logger.warn(name + ":" + sanitizeForURI(name)); - PutMethod method = new PutMethod(storageURL+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + HttpPut method = new HttpPut(storageURL+"/"+sanitizeForURI(name)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); try { - client.executeMethod(method); - - FilesResponse response = new FilesResponse(method); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method = new PutMethod(storageURL+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - response = new FilesResponse(method); + method = new HttpPut(storageURL+"/"+sanitizeForURI(name)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -931,7 +1052,7 @@ else if (response.getStatusCode() == HttpStatus.SC_ACCEPTED) } } finally { - method.releaseConnection(); + method.abort(); } } else @@ -959,23 +1080,21 @@ public boolean deleteContainer(String name) throws IOException, HttpException, F { if (this.isLoggedin()) { - if (isValidContianerName(name)) + if (isValidContainerName(name)) { - DeleteMethod method = new DeleteMethod(storageURL+"/"+sanitizeForURI(name)); + HttpDelete method = new HttpDelete(storageURL+"/"+sanitizeForURI(name)); try { - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method = new DeleteMethod(storageURL+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - response = new FilesResponse(method); + method = new HttpDelete(storageURL+"/"+sanitizeForURI(name)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -999,7 +1118,7 @@ else if (response.getStatusCode() == HttpStatus.SC_CONFLICT) } } finally { - method.releaseConnection(); + method.abort(); } } else @@ -1028,25 +1147,22 @@ public String cdnEnableContainer(String name) throws IOException, HttpException, String returnValue = null; if (this.isLoggedin()) { - if (isValidContianerName(name)) + if (isValidContainerName(name)) { - PutMethod method = null; + HttpPut method = null; try { - method = new PutMethod(cdnManagementURL+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - - FilesResponse response = new FilesResponse(method); + method = new HttpPut(cdnManagementURL+"/"+sanitizeForURI(name)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method = new PutMethod(cdnManagementURL+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - response = new FilesResponse(method); + method = new HttpPut(cdnManagementURL+"/"+sanitizeForURI(name)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -1066,7 +1182,7 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { } } finally { - method.releaseConnection(); + method.abort(); } } else @@ -1081,13 +1197,20 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { return returnValue; } + public String cdnUpdateContainer(String name, int ttl, boolean enabled, boolean retainLogs) + throws IOException, HttpException, FilesException + { + return cdnUpdateContainer(name, ttl, enabled, null, null, retainLogs); + } + /** * Enables access of files in this container via the Content Delivery Network. * * @param name The name of the container to enable * @param ttl How long the CDN can use the content before checking for an update. A negative value will result in this not being changed. - * @param enabled True if this folder should be accessible, false otherwise - * @return The CDN Url of the container + * @param enabled True if this container should be accessible, false otherwise + * @param retainLogs True if cdn access logs should be kept for this container, false otherwise + * @return The CDN Url of the container * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException There was an error talking to the CDN Service @@ -1096,56 +1219,54 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { * @param referrerAcl Unused for now * @param userAgentACL Unused for now */ -// private String cdnUpdateContainer(String name, int ttl, boolean enabled, String referrerAcl, String userAgentACL) - public String cdnUpdateContainer(String name, int ttl, boolean enabled) + private String cdnUpdateContainer(String name, int ttl, boolean enabled, String referrerAcl, String userAgentACL, boolean retainLogs) throws IOException, HttpException, FilesException { String returnValue = null; if (this.isLoggedin()) { - if (isValidContianerName(name)) + if (isValidContainerName(name)) { - PostMethod method = null; + HttpPost method = null; try { - method = new PostMethod(cdnManagementURL+"/"+sanitizeForURI(name)); + method = new HttpPost(cdnManagementURL+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); // TTL if (ttl > 0) { - method.setRequestHeader(FilesConstants.X_CDN_TTL, Integer.toString(ttl)); + method.setHeader(FilesConstants.X_CDN_TTL, Integer.toString(ttl)); } - // Enabled - method.setRequestHeader(FilesConstants.X_CDN_ENABLED, Boolean.toString(enabled)); + // Enabled + method.setHeader(FilesConstants.X_CDN_ENABLED, Boolean.toString(enabled)); -// // Referrer ACL -// if(referrerAcl != null) { -// method.setRequestHeader(FilesConstants.X_CDN_REFERRER_ACL, referrerAcl); -// } + // Log Retention + method.setHeader(FilesConstants.X_CDN_RETAIN_LOGS, Boolean.toString(retainLogs)); -// // User Agent ACL -// if(userAgentACL != null) { -// method.setRequestHeader(FilesConstants.X_CDN_USER_AGENT_ACL, userAgentACL); -// } - client.executeMethod(method); + // Referrer ACL + if(referrerAcl != null) { + method.setHeader(FilesConstants.X_CDN_REFERRER_ACL, referrerAcl); + } - FilesResponse response = new FilesResponse(method); + // User Agent ACL + if(userAgentACL != null) { + method.setHeader(FilesConstants.X_CDN_USER_AGENT_ACL, userAgentACL); + } + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - new PostMethod(cdnManagementURL+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + new HttpPost(cdnManagementURL+"/"+sanitizeForURI(name)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); // TTL if (ttl > 0) { - method.setRequestHeader(FilesConstants.X_CDN_TTL, Integer.toString(ttl)); + method.setHeader(FilesConstants.X_CDN_TTL, Integer.toString(ttl)); } // Enabled - method.setRequestHeader(FilesConstants.X_CDN_ENABLED, Boolean.toString(enabled)); - - client.executeMethod(method); - response = new FilesResponse(method); + method.setHeader(FilesConstants.X_CDN_ENABLED, Boolean.toString(enabled)); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -1165,7 +1286,7 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { } } finally { if (method != null) { - method.releaseConnection(); + method.abort(); } } } @@ -1179,22 +1300,7 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { } return returnValue; } - - /* * - * Enables access of files in this container via the Content Delivery Network. - * - * @param name The name of the container to enable - * @param ttl How long the CDN can use the content before checking for an update. A negative value will result in this not being changed. - * @param enabled True if this folder should be accesible, false otherwise - * @return The CDN Url of the container - * @throws IOException There was an IO error doing network communication - * @throws HttpException There was an error with the http protocol - * @throws FilesAuthorizationException Authentication failed - */ -// public String cdnUpdateContainer(String name, int ttl, boolean enabled) throws IOException, HttpException, FilesAuthorizationException -// { -// return cdnUpdateContainer(name, ttl, enabled, (String) null, (String) null); -// } + /** * Gets current CDN sharing status of the container @@ -1204,29 +1310,27 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException There was an error talking to the CloudFiles Server + * @throws FilesNotFoundException The Container has never been CDN enabled */ - public FilesCDNContainer getCDNContainerInfo(String container) throws IOException, HttpException, FilesException + public FilesCDNContainer getCDNContainerInfo(String container) throws IOException, FilesNotFoundException, HttpException, FilesException { if (isLoggedin()) { - if (isValidContianerName(container)) + if (isValidContainerName(container)) { - HeadMethod method = null; + HttpHead method = null; try { - method= new HeadMethod(cdnManagementURL+"/"+sanitizeForURI(container)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - - FilesResponse response = new FilesResponse(method); + method= new HttpHead(cdnManagementURL+"/"+sanitizeForURI(container)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method= new HeadMethod(cdnManagementURL+"/"+sanitizeForURI(container)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - response = new FilesResponse(method); + method= new HttpHead(cdnManagementURL+"/"+sanitizeForURI(container)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -1237,14 +1341,25 @@ public FilesCDNContainer getCDNContainerInfo(String container) throws IOExceptio { FilesCDNContainer result = new FilesCDNContainer(response.getCdnUrl()); result.setName(container); + result.setSSLURL(response.getCdnSslUrl()); + result.setStreamingURL(response.getCdnStreamingUrl()); for (Header hdr : response.getResponseHeaders()) { String name = hdr.getName().toLowerCase(); if ("x-cdn-enabled".equals(name)) { result.setEnabled(Boolean.valueOf(hdr.getValue())); } + else if ("x-log-retention".equals(name)) { + result.setRetainLogs(Boolean.valueOf(hdr.getValue())); + } else if ("x-ttl".equals(name)) { result.setTtl(Integer.parseInt(hdr.getValue())); } + else if ("x-referrer-acl".equals(name)) { + result.setReferrerACL(hdr.getValue()); + } + else if ("x-user-agent-acl".equals(name)) { + result.setUserAgentACL(hdr.getValue()); + } } return result; } @@ -1252,13 +1367,17 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { logger.warn("Unauthorized access"); throw new FilesAuthorizationException("User not Authorized!",response.getResponseHeaders(), response.getStatusLine()); } + else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { + throw new FilesNotFoundException("Container is not CDN enabled",response.getResponseHeaders(), response.getStatusLine()); + } + else { throw new FilesException("Unexpected result from server: ", response.getResponseHeaders(), response.getStatusLine()); } } finally { if (method != null) { - method.releaseConnection(); + method.abort(); } } } @@ -1272,21 +1391,79 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { } } - /* * - * Not currently used (but soon will be) - * @param container - */ - // public void purgeCDNContainer(String container) { -/// // Stub -// } - - /* * - * Not currently used (but soon will be) - * @param container + /** + * Gets current CDN sharing status of the container + * + * @param name The name of the container to enable + * @return Information on the container + * @throws IOException There was an IO error doing network communication + * @throws HttpException There was an error with the http protocol + * @throws FilesException There was an error talking to the CloudFiles Server + * @throws FilesNotFoundException The Container has never been CDN enabled */ -// public void purgeCDNObject(String container, String object) { - // // Stub -// } + public boolean isCDNEnabled(String container) throws IOException, HttpException, FilesException + { + if (isLoggedin()) { + if (isValidContainerName(container)) + { + HttpHead method = null; + try { + method= new HttpHead(cdnManagementURL+"/"+sanitizeForURI(container)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); + + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + if(login()) { + method= new HttpHead(cdnManagementURL+"/"+sanitizeForURI(container)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); + } + else { + throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); + } + } + + if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) + { + for (Header hdr : response.getResponseHeaders()) { + String name = hdr.getName().toLowerCase(); + if ("x-cdn-enabled".equals(name)) { + return Boolean.valueOf(hdr.getValue()); + } + } + throw new FilesException("Server did not return X-CDN-Enabled header: ", response.getResponseHeaders(), response.getStatusLine()); + } + else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + logger.warn("Unauthorized access"); + throw new FilesAuthorizationException("User not Authorized!",response.getResponseHeaders(), response.getStatusLine()); + } + else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { + return false; + } + + else { + throw new FilesException("Unexpected result from server: ", response.getResponseHeaders(), response.getStatusLine()); + } + } + finally { + if (method != null) { + method.abort(); + } + } + } + else + { + throw new FilesInvalidNameException(container); + } + } + else { + throw new FilesAuthorizationException("You must be logged in", null, null); + } + } + /** * Creates a path (but not any of the sub portions of the path) @@ -1299,7 +1476,7 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { */ public void createPath(String container, String path) throws HttpException, IOException, FilesException { - if (!isValidContianerName(container)) + if (!isValidContainerName(container)) throw new FilesInvalidNameException(container); if (!isValidObjectName(path)) throw new FilesInvalidNameException(path); @@ -1377,35 +1554,28 @@ public List listCdnContainers(int limit, String marker) throws IOExcepti { if (this.isLoggedin()) { - GetMethod method = null; + HttpGet method = null; try { - method = new GetMethod(cdnManagementURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - LinkedList params = new LinkedList(); + LinkedList params = new LinkedList(); if (limit > 0) { - params.add(new NameValuePair("limit", String.valueOf(limit))); + params.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if (marker != null) { - params.add(new NameValuePair("marker", marker)); + params.add(new BasicNameValuePair("marker", marker)); } - if (params.size() > 0) { - method.setQueryString(params.toArray(new NameValuePair[params.size()])); - } - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + String uri = (params.size() > 0) ? makeURI(cdnManagementURL, params) : cdnManagementURL; + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method = new GetMethod(cdnManagementURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - if (params.size() > 0) { - method.setQueryString(params.toArray(new NameValuePair[params.size()])); - } - client.executeMethod(method); - response = new FilesResponse(method); + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -1414,7 +1584,7 @@ public List listCdnContainers(int limit, String marker) throws IOExcepti if (response.getStatusCode() == HttpStatus.SC_OK) { - StrTokenizer tokenize = new StrTokenizer(inputStreamToString(response.getResponseBodyAsStream(), method.getResponseCharSet())); + StrTokenizer tokenize = new StrTokenizer(response.getResponseBodyAsString()); tokenize.setDelimiterString("\n"); String [] containers = tokenize.getTokenArray(); List returnValue = new ArrayList(); @@ -1433,13 +1603,141 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { } } finally { - if (method != null) method.releaseConnection(); + if (method != null) method.abort(); } } else { throw new FilesAuthorizationException("You must be logged in", null, null); } } + + /** + * Purges all items from a given container from the CDN + * + * @param container The name of the container + * @param emailAddresses An optional comma separated list of email addresses to be notified when the purge is complete. + * null if desired. + * @throws IOException Error talking to the cdn management server + * @throws HttpException Error with HTTP + * @throws FilesAuthorizationException Log in was not successful, or account is suspended + * @throws FilesException Other error + */ + public void purgeCDNContainer(String container, String emailAddresses) throws IOException, HttpException, FilesAuthorizationException, FilesException { + if (! isLoggedin) { + throw new FilesAuthorizationException("You must be logged in", null, null); + } + if (!isValidContainerName(container)) { + throw new FilesInvalidNameException(container); + } + HttpDelete method = null; + try { + String deleteUri = cdnManagementURL + "/" + sanitizeForURI(container); + method = new HttpDelete(deleteUri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + if (emailAddresses != null) { + method.setHeader(FilesConstants.X_PURGE_EMAIL, emailAddresses); + } + + FilesResponse response = new FilesResponse(client.execute(method)); + + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + if(login()) { + method = new HttpDelete(deleteUri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + if (emailAddresses != null) { + method.setHeader(FilesConstants.X_PURGE_EMAIL, emailAddresses); + } + response = new FilesResponse(client.execute(method)); + } + else { + throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); + } + } + + if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) + { + return; + } + else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + throw new FilesAuthorizationException("User not Authorized!",response.getResponseHeaders(), response.getStatusLine()); + } + else { + throw new FilesException("Unexpected server response",response.getResponseHeaders(), response.getStatusLine()); + } + } + finally { + if (method != null) method.abort(); + } + + } + + /** + * Purges all items from a given container from the CDN + * + * @param container The name of the container + * @param object The name of the object + * @param emailAddresses An optional comma separated list of email addresses to be notified when the purge is complete. + * null if desired. + * @throws IOException Error talking to the cdn management server + * @throws HttpException Error with HTTP + * @throws FilesAuthorizationException Log in was not successful, or account is suspended + * @throws FilesException Other error + */ + public void purgeCDNObject(String container, String object, String emailAddresses) throws IOException, HttpException, FilesAuthorizationException, FilesException { + if (! isLoggedin) { + throw new FilesAuthorizationException("You must be logged in", null, null); + } + if (!isValidContainerName(container)) { + throw new FilesInvalidNameException(container); + } + HttpDelete method = null; + try { + String deleteUri = cdnManagementURL + "/" + sanitizeForURI(container) +"/"+sanitizeAndPreserveSlashes(object); + method = new HttpDelete(deleteUri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + if (emailAddresses != null) { + method.setHeader(FilesConstants.X_PURGE_EMAIL, emailAddresses); + } + + FilesResponse response = new FilesResponse(client.execute(method)); + + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + if(login()) { + method = new HttpDelete(deleteUri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + if (emailAddresses != null) { + method.setHeader(FilesConstants.X_PURGE_EMAIL, emailAddresses); + } + response = new FilesResponse(client.execute(method)); + } + else { + throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); + } + } + + if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) + { + return; + } + else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + throw new FilesAuthorizationException("User not Authorized!",response.getResponseHeaders(), response.getStatusLine()); + } + else { + System.out.println(response.getStatusLine()); + throw new FilesException("Unexpected server response",response.getResponseHeaders(), response.getStatusLine()); + } + } + finally { + if (method != null) method.abort(); + } + + } /** * Gets list of all of the containers associated with this account. @@ -1483,34 +1781,31 @@ public List listCdnContainerInfo(int limit, String marker) th { if (this.isLoggedin()) { - GetMethod method = null; + HttpGet method = null; try { - method = new GetMethod(cdnManagementURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); LinkedList params = new LinkedList(); - params.add(new NameValuePair("format", "xml")); + params.add(new BasicNameValuePair("format", "xml")); if (limit > 0) { - params.add(new NameValuePair("limit", String.valueOf(limit))); + params.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if (marker != null) { - params.add(new NameValuePair("marker", marker)); + params.add(new BasicNameValuePair("marker", marker)); } - method.setQueryString(params.toArray(new NameValuePair[params.size()])); + String uri = params.size() > 0 ? makeURI(cdnManagementURL, params) : cdnManagementURL; + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method = new GetMethod(cdnManagementURL); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - method.setQueryString(params.toArray(new NameValuePair[params.size()])); + method = new HttpGet(uri); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - response = new FilesResponse(method); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -1541,15 +1836,30 @@ public List listCdnContainerInfo(int limit, String marker) th if ("name".equals(data.getNodeName())) { container.setName(data.getTextContent()); } - else if ("cdn_url".equals(data.getNodeName())) { + else if ("cdn_url".equals(data.getNodeName())) { container.setCdnURL(data.getTextContent()); } + else if ("cdn_ssl_url".equals(data.getNodeName())) { + container.setSSLURL(data.getTextContent()); + } + else if ("cdn_streaming_url".equals(data.getNodeName())) { + container.setStreamingURL(data.getTextContent()); + } else if ("cdn_enabled".equals(data.getNodeName())) { container.setEnabled(Boolean.parseBoolean(data.getTextContent())); } + else if ("log_retention".equals(data.getNodeName())) { + container.setRetainLogs(Boolean.parseBoolean(data.getTextContent())); + } else if ("ttl".equals(data.getNodeName())) { container.setTtl(Integer.parseInt(data.getTextContent())); } + else if ("referrer_acl".equals(data.getNodeName())) { + container.setReferrerACL(data.getTextContent()); + } + else if ("useragent_acl".equals(data.getNodeName())) { + container.setUserAgentACL(data.getTextContent()); + } else { //logger.warn("Unexpected container-info tag:" + data.getNodeName()); } @@ -1577,13 +1887,143 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { throw new FilesException("Problem parsing XML", ex); } finally { - if (method != null) method.releaseConnection(); + if (method != null) method.abort(); } } else { throw new FilesAuthorizationException("You must be logged in", null, null); } } + /** + * Create a manifest on the server, including metadata + * + * @param container The name of the container + * @param obj The File containing the file to copy over + * @param contentType The MIME type of the file + * @param name The name of the file on the server + * @param manifest Set manifest content here + * @param callback The object to which any callbacks will be sent (null if you don't want callbacks) + * @throws IOException There was an IO error doing network communication + * @throws HttpException There was an error with the http protocol + * @throws FilesException + */ + public boolean createManifestObject(String container, String contentType, String name, String manifest, IFilesTransferCallback callback) throws IOException, HttpException, FilesException + { + return createManifestObject(container, contentType, name, manifest, new HashMap(), callback); + } + /** + * Create a manifest on the server, including metadata + * + * @param container The name of the container + * @param obj The File containing the file to copy over + * @param contentType The MIME type of the file + * @param name The name of the file on the server + * @param manifest Set manifest content here + * @param metadata A map with the metadata as key names and values as the metadata values + * @throws IOException There was an IO error doing network communication + * @throws HttpException There was an error with the http protocol + * @throws FilesException + */ + public boolean createManifestObject(String container, String contentType, String name, String manifest, Map metadata) throws IOException, HttpException, FilesException + { + return createManifestObject(container, contentType, name, manifest, metadata, null); + } + /** + * Create a manifest on the server, including metadata + * + * @param container The name of the container + * @param obj The File containing the file to copy over + * @param contentType The MIME type of the file + * @param name The name of the file on the server + * @param manifest Set manifest content here + * @param metadata A map with the metadata as key names and values as the metadata values + * @param callback The object to which any callbacks will be sent (null if you don't want callbacks) + * @throws IOException There was an IO error doing network communication + * @throws HttpException There was an error with the http protocol + * @throws FilesException + */ + public boolean createManifestObject(String container, String contentType, String name, String manifest, Map metadata, IFilesTransferCallback callback) throws IOException, HttpException, FilesException + { + byte[] arr = new byte[0]; + if (this.isLoggedin()) + { + String objName = name; + if (isValidContainerName(container) && isValidObjectName(objName)) + { + + HttpPut method = null; + try { + method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method.setHeader(FilesConstants.MANIFEST_HEADER, manifest); + ByteArrayEntity entity = new ByteArrayEntity (arr); + entity.setContentType(contentType); + method.setEntity(new RequestEntityWrapper(entity, callback)); + for(String key : metadata.keySet()) { + // logger.warn("Key:" + key + ":" + sanitizeForURI(metadata.get(key))); + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + } + + FilesResponse response = new FilesResponse(client.execute(method)); + + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + if(login()) { + method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + if (manifest != null){ + method.setHeader(FilesConstants.MANIFEST_HEADER, manifest); + } + entity = new ByteArrayEntity (arr); + entity.setContentType(contentType); + method.setEntity(new RequestEntityWrapper(entity, callback)); + for(String key : metadata.keySet()) { + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + } + response = new FilesResponse(client.execute(method)); + } + else { + throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); + } + } + + if (response.getStatusCode() == HttpStatus.SC_CREATED) + { + return true; + } + else if (response.getStatusCode() == HttpStatus.SC_PRECONDITION_FAILED) + { + throw new FilesException("Etag missmatch", response.getResponseHeaders(), response.getStatusLine()); + } + else if (response.getStatusCode() == HttpStatus.SC_LENGTH_REQUIRED) + { + throw new FilesException("Length miss-match", response.getResponseHeaders(), response.getStatusLine()); + } + else + { + throw new FilesException("Unexpected Server Response", response.getResponseHeaders(), response.getStatusLine()); + } + } + finally{ + if (method != null) method.abort(); + } + } + else + { + if (!isValidObjectName(objName)) { + throw new FilesInvalidNameException(objName); + } + else { + throw new FilesInvalidNameException(container); + } + } + } + else { + throw new FilesAuthorizationException("You must be logged in", null, null); + } + } /** * Store a file on the server @@ -1592,11 +2032,12 @@ else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { * @param obj The File containing the file to copy over * @param contentType The MIME type of the file * @param name The name of the file on the server + * @return The ETAG if the save was successful, null otherwise * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ - public boolean storeObjectAs (String container, File obj, String contentType, String name) throws IOException, HttpException, FilesException + public String storeObjectAs (String container, File obj, String contentType, String name) throws IOException, HttpException, FilesException { return storeObjectAs(container, obj, contentType, name, new HashMap(), null); } @@ -1608,11 +2049,12 @@ public boolean storeObjectAs (String container, File obj, String contentType, St * @param obj The File containing the file to copy over * @param contentType The MIME type of the file * @param name The name of the file on the server + * @return The ETAG if the save was successful, null otherwise * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ - public boolean storeObjectAs (String container, File obj, String contentType, String name, IFilesTransferCallback callback) throws IOException, HttpException, FilesException + public String storeObjectAs (String container, File obj, String contentType, String name, IFilesTransferCallback callback) throws IOException, HttpException, FilesException { return storeObjectAs(container, obj, contentType, name, new HashMap(), callback); } @@ -1625,11 +2067,12 @@ public boolean storeObjectAs (String container, File obj, String contentType, St * @param contentType The MIME type of the file * @param name The name of the file on the server * @param metadata A map with the metadata as key names and values as the metadata values + * @return The ETAG if the save was successful, null otherwise * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesAuthorizationException */ - public boolean storeObjectAs (String container, File obj, String contentType, String name, Map metadata) throws IOException, HttpException, FilesException + public String storeObjectAs (String container, File obj, String contentType, String name, Map metadata) throws IOException, HttpException, FilesException { return storeObjectAs (container, obj, contentType, name, metadata, null); } @@ -1643,15 +2086,16 @@ public boolean storeObjectAs (String container, File obj, String contentType, St * @param name The name of the file on the server * @param metadata A map with the metadata as key names and values as the metadata values * @param metadata The callback object that will be called as the data is sent + * @return The ETAG if the save was successful, null otherwise * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ - public boolean storeObjectAs (String container, File obj, String contentType, String name, Map metadata, IFilesTransferCallback callback) throws IOException, HttpException, FilesException + public String storeObjectAs (String container, File obj, String contentType, String name, Map metadata, IFilesTransferCallback callback) throws IOException, HttpException, FilesException { if (this.isLoggedin()) { - if (isValidContianerName(container) && isValidObjectName(name) ) + if (isValidContainerName(container) && isValidObjectName(name) ) { if (!obj.exists()) { @@ -1663,36 +2107,34 @@ public boolean storeObjectAs (String container, File obj, String contentType, St throw new IOException("The alleged file was a directory"); } - PutMethod method = null; + HttpPut method = null; try { - method = new PutMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(name)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); if (useETag) { - method.setRequestHeader(FilesConstants.E_TAG, md5Sum (obj)); + method.setHeader(FilesConstants.E_TAG, md5Sum (obj)); } - method.setRequestEntity( new RequestEntityWrapper(new FileRequestEntity (obj, contentType), callback)); + method.setEntity( new RequestEntityWrapper(new FileEntity (obj, contentType), callback)); for(String key : metadata.keySet()) { - method.setRequestHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method = new PutMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(name)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(name)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); if (useETag) { - method.setRequestHeader(FilesConstants.E_TAG, md5Sum (obj)); + method.setHeader(FilesConstants.E_TAG, md5Sum (obj)); } - method.setRequestEntity( new RequestEntityWrapper(new FileRequestEntity (obj, contentType), callback)); + method.setEntity( new RequestEntityWrapper(new FileEntity (obj, contentType), callback)); for(String key : metadata.keySet()) { - method.setRequestHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } - client.executeMethod(method); - response = new FilesResponse(method); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -1700,7 +2142,7 @@ public boolean storeObjectAs (String container, File obj, String contentType, St } if (response.getStatusCode() == HttpStatus.SC_CREATED) { - return true; + return response.getResponseHeader(FilesConstants.E_TAG).getValue(); } else if (response.getStatusCode() == HttpStatus.SC_PRECONDITION_FAILED) { @@ -1716,7 +2158,7 @@ else if (response.getStatusCode() == HttpStatus.SC_LENGTH_REQUIRED) } } finally { - if (method != null) method.releaseConnection(); + if (method != null) method.abort(); } } else @@ -1741,11 +2183,12 @@ else if (response.getStatusCode() == HttpStatus.SC_LENGTH_REQUIRED) * @param container The name of the container to place the file in * @param obj The File to transfer * @param contentType The file's MIME type + * @return The ETAG if the save was successful, null otherwise * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ - public boolean storeObject (String container, File obj, String contentType) throws IOException, HttpException, FilesException + public String storeObject (String container, File obj, String contentType) throws IOException, HttpException, FilesException { return storeObjectAs(container, obj, contentType, obj.getName()); } @@ -1785,40 +2228,43 @@ public boolean storeObject(String container, byte obj[], String contentType, Str if (this.isLoggedin()) { String objName = name; - if (isValidContianerName(container) && isValidObjectName(objName)) + if (isValidContainerName(container) && isValidObjectName(objName)) { - PutMethod method = null; + HttpPut method = null; try { - method = new PutMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); if (useETag) { - method.setRequestHeader(FilesConstants.E_TAG, md5Sum (obj)); + method.setHeader(FilesConstants.E_TAG, md5Sum (obj)); } - method.setRequestEntity(new RequestEntityWrapper(new ByteArrayRequestEntity (obj, contentType), callback)); + ByteArrayEntity entity = new ByteArrayEntity (obj); + entity.setContentType(contentType); + method.setEntity(new RequestEntityWrapper(entity, callback)); for(String key : metadata.keySet()) { // logger.warn("Key:" + key + ":" + sanitizeForURI(metadata.get(key))); - method.setRequestHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - method.releaseConnection(); + method.abort(); if(login()) { - method = new PutMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); if (useETag) { - method.setRequestHeader(FilesConstants.E_TAG, md5Sum (obj)); + method.setHeader(FilesConstants.E_TAG, md5Sum (obj)); } - method.setRequestEntity(new RequestEntityWrapper(new ByteArrayRequestEntity (obj, contentType), callback)); + entity = new ByteArrayEntity (obj); + entity.setContentType(contentType); + method.setEntity(new RequestEntityWrapper(entity, callback)); for(String key : metadata.keySet()) { - method.setRequestHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } - client.executeMethod(method); - response = new FilesResponse(method); + response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); @@ -1843,7 +2289,7 @@ else if (response.getStatusCode() == HttpStatus.SC_LENGTH_REQUIRED) } } finally{ - if (method != null) method.releaseConnection(); + if (method != null) method.abort(); } } else @@ -1876,32 +2322,33 @@ else if (response.getStatusCode() == HttpStatus.SC_LENGTH_REQUIRED) * @throws HttpException There was an error with the http protocol * @throws FilesException */ - public boolean storeStreamedObject(String container, InputStream data, String contentType, String name, Map metadata) throws IOException, HttpException, FilesException + public String storeStreamedObject(String container, InputStream data, String contentType, String name, Map metadata) throws IOException, HttpException, FilesException { if (this.isLoggedin()) { String objName = name; - if (isValidContianerName(container) && isValidObjectName(objName)) + if (isValidContainerName(container) && isValidObjectName(objName)) { - PutMethod method = new PutMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.setContentChunked(true); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - method.setRequestEntity(new InputStreamRequestEntity(data, contentType)); + HttpPut method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + InputStreamEntity entity = new InputStreamEntity(data, -1); + entity.setChunked(true); + entity.setContentType(contentType); + method.setEntity(entity); for(String key : metadata.keySet()) { // logger.warn("Key:" + key + ":" + sanitizeForURI(metadata.get(key))); - method.setRequestHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } - method.removeRequestHeader("Content-Length"); + method.removeHeaders("Content-Length"); + try { - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_CREATED) { - logger.debug ("Object stored : " + name); - return true; + return response.getResponseHeader(FilesConstants.E_TAG).getValue(); } else { logger.error(response.getStatusLine()); @@ -1909,7 +2356,7 @@ public boolean storeStreamedObject(String container, InputStream data, String co } } finally { - method.releaseConnection(); + method.abort(); } } else @@ -1935,52 +2382,50 @@ public boolean storeStreamedObject(String container, InputStream data, String co * @param entity The name of the request entity (make sure to set the Content-Type * @param metadata The metadata for the object * @param md5sum The 32 character hex encoded MD5 sum of the data - * @return True of the save was successful + * @return The ETAG if the save was successful, null otherwise * @throws IOException There was a socket level exception talking to CloudFiles * @throws HttpException There was a protocol level error talking to CloudFiles * @throws FilesException There was an error talking to CloudFiles. */ -public boolean storeObjectAs(String container, String name, RequestEntity entity, Map metadata, String md5sum) throws IOException, HttpException, FilesException +public String storeObjectAs(String container, String name, HttpEntity entity, Map metadata, String md5sum) throws IOException, HttpException, FilesException { if (this.isLoggedin()) { String objName = name; - if (isValidContianerName(container) && isValidObjectName(objName)) + if (isValidContainerName(container) && isValidObjectName(objName)) { - PutMethod method = new PutMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - method.setRequestEntity(entity); + HttpPut method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method.setEntity(entity); if (useETag && md5sum != null) { - method.setRequestHeader(FilesConstants.E_TAG, md5sum); + method.setHeader(FilesConstants.E_TAG, md5sum); } - method.setRequestHeader("Content-Type", entity.getContentType()); + method.setHeader(entity.getContentType()); for(String key : metadata.keySet()) { - method.setRequestHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } try { - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); login(); - method = new PutMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - method.setRequestEntity(entity); - method.setRequestHeader("Content-Type", entity.getContentType()); + method = new HttpPut(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method.setEntity(entity); + method.setHeader(entity.getContentType()); for(String key : metadata.keySet()) { - method.setRequestHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); + method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } - client.executeMethod(method); - response = new FilesResponse(method); + response = new FilesResponse(client.execute(method)); } if (response.getStatusCode() == HttpStatus.SC_CREATED) { - logger.debug ("Object stored : " + name); - return true; + return response.getResponseHeader(FilesConstants.E_TAG).getValue(); } else { logger.debug(response.getStatusLine()); @@ -1988,7 +2433,7 @@ public boolean storeObjectAs(String container, String name, RequestEntity entity } } finally { - method.releaseConnection(); + method.abort(); } } else @@ -2006,6 +2451,96 @@ public boolean storeObjectAs(String container, String name, RequestEntity entity } } + /** + * This method copies the object found in the source container with the + * source object name to the destination container with the destination + * object name. + * @param sourceContainer of object to copy + * @param sourceObjName of object to copy + * @param destContainer where object copy will be copied + * @param destObjName of object copy + * @return ETAG if successful, else null + * @throws IOException indicates a socket level error talking to CloudFiles + * @throws HttpException indicates a protocol level error talking to CloudFiles + * @throws FilesException indicates an error talking to CloudFiles + */ + public String copyObject(String sourceContainer, + String sourceObjName, + String destContainer, + String destObjName) + throws HttpException, IOException { + String etag = null; + if (this.isLoggedin()) { + + if (isValidContainerName(sourceContainer) && + isValidObjectName(sourceObjName) && + isValidContainerName(destContainer) && + isValidObjectName(destObjName)) { + + HttpPut method = null; + try { + String sourceURI = sanitizeForURI(sourceContainer) + + "/" + sanitizeForURI(sourceObjName); + String destinationURI = sanitizeForURI(destContainer) + + "/" + sanitizeForURI(destObjName); + + method = new HttpPut(storageURL + "/" + destinationURI); + method.getParams().setIntParameter("http.socket.timeout", + connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method.setHeader(FilesConstants.X_COPY_FROM, sourceURI); + + FilesResponse response = new FilesResponse(client.execute( + method)); + + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + + login(); + method = new HttpPut(storageURL + "/" + destinationURI); + method.getParams().setIntParameter("http.socket.timeout", + connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + method.setHeader(FilesConstants.X_COPY_FROM, sourceURI); + + response = new FilesResponse(client.execute(method)); + } + + if (response.getStatusCode() == HttpStatus.SC_CREATED) { + etag = response.getResponseHeader(FilesConstants.E_TAG) + .getValue(); + + } else { + throw new FilesException("Unexpected status from server", + response.getResponseHeaders(), + response.getStatusLine()); + } + + } finally { + if (method != null) { + method.abort(); + } + } + } else { + if (!isValidContainerName(sourceContainer)) { + throw new FilesInvalidNameException(sourceContainer); + } else if (!isValidObjectName(sourceObjName)) { + throw new FilesInvalidNameException(sourceObjName); + } else if (!isValidContainerName(destContainer)) { + throw new FilesInvalidNameException(destContainer); + } else { + throw new FilesInvalidNameException(destObjName); + } + } + } else { + throw new FilesAuthorizationException("You must be logged in", + null, + null); + } + + return etag; + } + /** * Delete the given object from it's container. * @@ -2016,19 +2551,29 @@ public boolean storeObjectAs(String container, String name, RequestEntity entity * @throws HttpException There was an error with the http protocol * @throws FilesException */ - public void deleteObject (String container, String objName) throws IOException, HttpException, FilesException + public void deleteObject (String container, String objName) throws IOException, FilesNotFoundException, HttpException, FilesException { if (this.isLoggedin()) { - if (isValidContianerName(container) && isValidObjectName(objName)) + if (isValidContainerName(container) && isValidObjectName(objName)) { - DeleteMethod method = null; + HttpDelete method = null; try { - method = new DeleteMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - FilesResponse response = new FilesResponse(method); + method = new HttpDelete(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); + + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + login(); + method = new HttpDelete(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); + } + if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) { @@ -2043,7 +2588,7 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) } } finally { - if (method != null) method.releaseConnection(); + if (method != null) method.abort(); } } else @@ -2071,54 +2616,68 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) * @throws HttpException There was an error with the http protocol * @throws FilesAuthorizationException The Client's Login was invalid. * @throws FilesInvalidNameException The container or object name was not valid + * @throws FilesNotFoundException The file was not found */ - public FilesObjectMetaData getObjectMetaData (String container, String objName) throws IOException, HttpException, FilesAuthorizationException, FilesInvalidNameException + public FilesObjectMetaData getObjectMetaData (String container, String objName) throws IOException, FilesNotFoundException, HttpException, FilesAuthorizationException, FilesInvalidNameException { FilesObjectMetaData metaData; if (this.isLoggedin()) { - if (isValidContianerName(container) && isValidObjectName(objName)) + if (isValidContainerName(container) && isValidObjectName(objName)) { - HeadMethod method = new HeadMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); - - client.executeMethod(method); - - FilesResponse response = new FilesResponse(method); + HttpHead method = new HttpHead(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + try { + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); + + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + login(); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); + } - if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) - { - logger.debug ("Object metadata retreived : "+objName); - String mimeType = response.getContentType(); - String lastModified = response.getLastModified(); - String eTag = response.getETag(); - String contentLength = response.getContentLength(); + if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT || + response.getStatusCode() == HttpStatus.SC_OK) + { + logger.debug ("Object metadata retreived : "+objName); + String mimeType = response.getContentType(); + String lastModified = response.getLastModified(); + String eTag = response.getETag(); + String contentLength = response.getContentLength(); - metaData = new FilesObjectMetaData(mimeType, contentLength, eTag, lastModified); + metaData = new FilesObjectMetaData(mimeType, contentLength, eTag, lastModified); - Header [] headers = response.getResponseHeaders(); - HashMap headerMap = new HashMap(); + Header [] headers = response.getResponseHeaders(); + HashMap headerMap = new HashMap(); - for (Header h: headers) - { - if ( h.getName().startsWith(FilesConstants.X_OBJECT_META) ) + for (Header h: headers) { - headerMap.put(h.getName().substring(FilesConstants.X_OBJECT_META.length()), unencodeURI(h.getValue())); + if ( h.getName().startsWith(FilesConstants.X_OBJECT_META) ) + { + headerMap.put(h.getName().substring(FilesConstants.X_OBJECT_META.length()), unencodeURI(h.getValue())); + } } - } - if (headerMap.size() > 0) - metaData.setMetaData(headerMap); + if (headerMap.size() > 0) + metaData.setMetaData(headerMap); - return metaData; + return metaData; + } + else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) + { + throw new FilesNotFoundException("Container: " + container + " did not have object " + objName, + response.getResponseHeaders(), response.getStatusLine()); + } + else { + throw new FilesException("Unexpected Return Code from Server", + response.getResponseHeaders(), response.getStatusLine()); + } } - else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) - { - logger.info ("Object " + objName + " was not found !"); - return null; + finally { + method.abort(); } - - method.releaseConnection(); } else { @@ -2133,7 +2692,6 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) else { throw new FilesAuthorizationException("You must be logged in", null, null); } - return null; } @@ -2153,27 +2711,29 @@ public byte[] getObject (String container, String objName) throws IOException, H { if (this.isLoggedin()) { - if (isValidContianerName(container) && isValidObjectName(objName)) + if (isValidContainerName(container) && isValidObjectName(objName)) { - GetMethod method = new GetMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + HttpGet method = new HttpGet(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); - client.executeMethod(method); - - FilesResponse response = new FilesResponse(method); + try { + FilesResponse response = new FilesResponse(client.execute(method)); - if (response.getStatusCode() == HttpStatus.SC_OK) - { - logger.debug ("Object data retreived : "+objName); - return response.getResponseBody(); + if (response.getStatusCode() == HttpStatus.SC_OK) + { + logger.debug ("Object data retreived : "+objName); + return response.getResponseBody(); + } + else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) + { + throw new FilesNotFoundException("Container: " + container + " did not have object " + objName, + response.getResponseHeaders(), response.getStatusLine()); + } } - else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) - { - throw new FilesNotFoundException("Container: " + container + " did not have object " + objName, response.getResponseHeaders(), response.getStatusLine()); + finally { + method.abort(); } - - method.releaseConnection(); } else { @@ -2200,13 +2760,14 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesAuthorizationException + * @throws FilesNotFoundException The container does not exist * @throws FilesInvalidNameException */ - public InputStream getObjectAsStream (String container, String objName) throws IOException, HttpException, FilesAuthorizationException, FilesInvalidNameException + public InputStream getObjectAsStream (String container, String objName) throws IOException, HttpException, FilesAuthorizationException, FilesInvalidNameException, FilesNotFoundException { if (this.isLoggedin()) { - if (isValidContianerName(container) && isValidObjectName(objName)) + if (isValidContainerName(container) && isValidObjectName(objName)) { if (objName.length() > FilesConstants.OBJECT_NAME_LENGTH) { @@ -2215,26 +2776,96 @@ public InputStream getObjectAsStream (String container, String objName) throws I logger.warn ("Truncated Object Name is: " + objName); } - GetMethod method = new GetMethod(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); - method.getParams().setSoTimeout(connectionTimeOut); - method.setRequestHeader(FilesConstants.X_AUTH_TOKEN, authToken); + HttpGet method = new HttpGet(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + FilesResponse response = new FilesResponse(client.execute(method)); - client.executeMethod(method); - - FilesResponse response = new FilesResponse(method); + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + login(); + method = new HttpGet(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); + } - if (response.getStatusCode() == HttpStatus.SC_OK) + if (response.getStatusCode() == HttpStatus.SC_OK) { logger.info ("Object data retreived : "+objName); + // DO NOT RELEASE THIS CONNECTION return response.getResponseBodyAsStream(); } else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { - logger.info ("Object " + objName + " was not found !"); - return null; + method.abort(); + throw new FilesNotFoundException("Container: " + container + " did not have object " + objName, + response.getResponseHeaders(), response.getStatusLine()); + } + } + else + { + if (!isValidObjectName(objName)) { + throw new FilesInvalidNameException(objName); + } + else { + throw new FilesInvalidNameException(container); + } + } + } + else { + throw new FilesAuthorizationException("You must be logged in", null, null); + } + return null; + } + + public InputStream getObjectAsRangedStream (String container, String objName, long offset, long length) throws IOException, HttpException, FilesAuthorizationException, FilesInvalidNameException, FilesNotFoundException + { + if (this.isLoggedin()) + { + if (isValidContainerName(container) && isValidObjectName(objName)) + { + if (objName.length() > FilesConstants.OBJECT_NAME_LENGTH) + { + logger.warn ("Object Name supplied was truncated to Max allowed of " + FilesConstants.OBJECT_NAME_LENGTH + " characters !"); + objName = objName.substring(0, FilesConstants.OBJECT_NAME_LENGTH); + logger.warn ("Truncated Object Name is: " + objName); + } + + HttpGet method = new HttpGet(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + if (offset >= 0) + { + method.setHeader("Range", "bytes="+offset+"-"+length); + } + else + { + method.setHeader("Range", "bytes="+offset+"-"); } + FilesResponse response = new FilesResponse(client.execute(method)); - method.releaseConnection(); + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + login(); + method = new HttpGet(storageURL+"/"+sanitizeForURI(container)+"/"+sanitizeForURI(objName)); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + response = new FilesResponse(client.execute(method)); + } + + if (response.getStatusCode() == HttpStatus.SC_OK) + { + logger.info ("Object data retreived : "+objName); + // DO NOT RELEASE THIS CONNECTION + return response.getResponseBodyAsStream(); + } + else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) + { + method.abort(); + throw new FilesNotFoundException("Container: " + container + " did not have object " + objName, + response.getResponseHeaders(), response.getStatusLine()); + } } else { @@ -2252,6 +2883,7 @@ else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) return null; } + /** * Utility function to write an InputStream to a file * @@ -2371,7 +3003,7 @@ public static String md5Sum (byte[] data) throws IOException public static String sanitizeForURI(String str) { URLCodec codec= new URLCodec(); try { - return codec.encode(str).replaceAll("\\+", "%20").replaceAll("%2F", "/"); + return codec.encode(str).replaceAll("\\+", "%20"); } catch (EncoderException ee) { logger.warn("Error trying to encode string for URI", ee); @@ -2379,6 +3011,17 @@ public static String sanitizeForURI(String str) { } } + public static String sanitizeAndPreserveSlashes(String str) { + URLCodec codec= new URLCodec(); + try { + return codec.encode(str).replaceAll("\\+", "%20").replaceAll("%2F", "/"); + } + catch (EncoderException ee) { + logger.warn("Error trying to encode string for URI", ee); + return str; + } + } + public static String unencodeURI(String str) { URLCodec codec= new URLCodec(); try { @@ -2420,13 +3063,23 @@ public String getStorageURL() /** * @return Get's our storage token. */ + @Deprecated public String getStorageToken() { return authToken; } /** - * Has this instance of the client authenticated itself? + * @return Get's our storage token. + */ + public String getAuthToken() + { + return authToken; + } + + /** + * Has this instance of the client authenticated itself? Note, this does not mean that a call + * right now will work, if the auth token has timed out, you will need to re-auth. * * @return True if we logged in, false otherwise. */ @@ -2512,14 +3165,14 @@ public void setUseETag(boolean useETag) { } public void setUserAgent(String userAgent) { - client.getParams().setParameter(HttpMethodParams.USER_AGENT, userAgent); + client.getParams().setParameter(HTTP.USER_AGENT, userAgent); } public String getUserAgent() { - return client.getParams().getParameter(HttpMethodParams.USER_AGENT).toString(); + return client.getParams().getParameter(HTTP.USER_AGENT).toString(); } - private boolean isValidContianerName(String name) { + public static boolean isValidContainerName(String name) { if (name == null) return false; int length = name.length(); if (length == 0 || length > FilesConstants.CONTAINER_NAME_LENGTH) return false; @@ -2527,7 +3180,7 @@ private boolean isValidContianerName(String name) { //if (name.indexOf('?') != -1) return false; return true; } - private boolean isValidObjectName(String name) { + public static boolean isValidObjectName(String name) { if (name == null) return false; int length = name.length(); if (length == 0 || length > FilesConstants.OBJECT_NAME_LENGTH) return false; @@ -2546,7 +3199,133 @@ public String getCdnManagementURL() { /** * @param config */ - public void setHostConfiguration(HostConfiguration config) { - client.setHostConfiguration(config); - } + public boolean updateObjectManifest(String container, String object, String manifest) throws FilesAuthorizationException, + HttpException, IOException, FilesInvalidNameException + { + return updateObjectMetadataAndManifest(container, object, new HashMap(), manifest); + } + /** + * @param config + */ + public boolean updateObjectMetadata(String container, String object, + Map metadata) throws FilesAuthorizationException, + HttpException, IOException, FilesInvalidNameException + { + return updateObjectMetadataAndManifest(container, object, metadata, null); + } + /** + * @param config + */ + public boolean updateObjectMetadataAndManifest(String container, String object, + Map metadata, String manifest) throws FilesAuthorizationException, + HttpException, IOException, FilesInvalidNameException { + FilesResponse response; + + if (!isLoggedin) { + throw new FilesAuthorizationException("You must be logged in", + null, null); + } + if (!isValidContainerName(container)) + throw new FilesInvalidNameException(container); + if (!isValidObjectName(object)) + throw new FilesInvalidNameException(object); + + String postUrl = storageURL + "/"+FilesClient.sanitizeForURI(container) + + "/"+FilesClient.sanitizeForURI(object); + + HttpPost method = null; + try { + method = new HttpPost(postUrl); + if (manifest != null){ + method.setHeader(FilesConstants.MANIFEST_HEADER, manifest); + } + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + if (!(metadata == null || metadata.isEmpty())) { + for(String key:metadata.keySet()) + method.setHeader(FilesConstants.X_OBJECT_META+key, + FilesClient.sanitizeForURI(metadata.get(key))); + } + HttpResponse resp = client.execute(method); + response = new FilesResponse(resp); + if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + method.abort(); + if(login()) { + method = new HttpPost(postUrl); + method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); + method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); + if (!(metadata == null || metadata.isEmpty())) { + for(String key:metadata.keySet()) + method.setHeader(FilesConstants.X_OBJECT_META+key, + FilesClient.sanitizeForURI(metadata.get(key))); + } + client.execute(method); + } + } + + return true; + } finally { + if (method != null) + method.abort(); + } + + } + + private String makeURI(String base, List parameters) { + return base + "?" + URLEncodedUtils.format(parameters, "UTF-8"); + } + + /* + * + *private void setQueryParameters(HttpRequestBase method, List parameters) throws FilesException{ + URI oldURI = method.getURI(); + try { + URI newURI = URIUtils.createURI(oldURI.getScheme(), oldURI.getHost(), -1, + URLEncoder.encode(oldURI.getPath(), "UTF-8"), URLEncodedUtils.format(parameters, "UTF-8"), null); + logger.warn("Old Path: " + oldURI.getPath()); + logger.warn("New URI: " + newURI); + method.setURI(newURI); + } + catch (UnsupportedEncodingException uee) { + logger.error("Somehow, we don't have UTF-8, this is quite a surprise", uee); + throw new FilesException("Somehow, we don't have UTF-8, this is quite a surprise", uee); + } + catch (URISyntaxException use) { + logger.error("Bad Syntax", use); + throw new FilesException("Bad URL Syntax", use); + } + } + */ + public void useSnet(){ + if(snet){ + } + else{ + snet = true; + if(storageURL != null){ + storageURL = snetAddr + storageURL.substring(8); + } + } + } + public void usePublic(){ + if(!snet){ + } + else{ + snet = false; + if(storageURL != null){ + storageURL = "https://" + storageURL.substring(snetAddr.length()); + } + } + } + public boolean usingSnet(){ + return snet; + } + private boolean envSnet(){ + if (System.getenv("RACKSPACE_SERVICENET") == null) { + return false; + } + else{ + snet = true; + return true; + } + } } diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesConstants.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesConstants.java similarity index 79% rename from src/main/java/com/mosso/client/cloudfiles/FilesConstants.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesConstants.java index 9620a85..5e09da5 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesConstants.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesConstants.java @@ -2,7 +2,7 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; import java.util.Properties; import java.io.IOException; @@ -12,12 +12,12 @@ public class FilesConstants { private static Logger logger = Logger.getLogger(FilesConstants.class); - public static final String USER_AGENT = "java-cloudfiles/1.3.2"; + public static final String USER_AGENT = "java-cloudfiles/1.9.2"; /** HTTP Header token that identifies the username to Cloud Files **/ - public static final String X_STORAGE_USER = "x-auth-user"; + public static final String X_STORAGE_USER_DEFAULT = "x-auth-user"; /** HTTP header token that identifies the password to Cloud Files **/ - public static final String X_STORAGE_PASS = "x-auth-key"; + public static final String X_STORAGE_PASS_DEFAULT = "x-auth-key"; /** HTTP header token that identifies the Storage URL after a successful user login to Cloud Files **/ public static final String X_STORAGE_URL = "X-Storage-Url"; /** HTTP header that identifies the CDN Management URL after a successful login to Cloud Files **/ @@ -35,15 +35,25 @@ public class FilesConstants /** HTTP header token that is returned by calls to the CDN Management API **/ public static final String X_CDN_URI = "X-CDN-URI"; /** HTTP header token that is returned by calls to the CDN Management API **/ + public static final String X_CDN_SSL_URI = "X-CDN-SSL-URI"; + /** HTTP header token that is returned by calls to the CDN Management API **/ + public static final String X_CDN_Streaming_URI = "X-CDN-Streaming-URI"; + /** HTTP header token that is returned by calls to the CDN Management API **/ public static final String X_CDN_TTL = "X-TTL"; /** HTTP header token that is returned by calls to the CDN Management API **/ + public static final String X_CDN_RETAIN_LOGS = "X-Log-Retention"; + /** HTTP header token that is returned by calls to the CDN Management API **/ public static final String X_CDN_ENABLED = "X-CDN-Enabled"; /** HTTP header token that is returned by calls to the CDN Management API **/ public static final String X_CDN_USER_AGENT_ACL = "X-User-Agent-ACL"; /** HTTP header token that is returned by calls to the CDN Management API **/ public static final String X_CDN_REFERRER_ACL = "X-Referrer-ACL "; + /** HTTP header used by Cloud Files for the source of an object being copied. The value of this header is // **/ + public static final String X_COPY_FROM = "X-Copy-From"; /** HTTP Header used by Cloud Files for the MD5Sum of the object being created in a Container **/ public static final String E_TAG = "ETag"; + /** HTTP Header used for Object Manifest **/ + public static final String MANIFEST_HEADER = "X-Object-Manifest"; /** These constants are used for performing queries on the content of a container **/ public static final String LIST_CONTAINER_NAME_QUERY = "prefix"; public static final String LIST_CONTAINER_LIMIT_OBJ_COUNT_QUERY = "limit"; @@ -54,11 +64,13 @@ public class FilesConstants public static final int METADATA_NAME_LENGTH = 1024; public static final int METADATA_VALUE_LENGTH = 1024; + public static final String X_PURGE_EMAIL = "X-Purge-Email"; + /** Prefix Cloud Files expects on all Meta data headers on Objects **/ public static final String X_OBJECT_META = "X-Object-Meta-"; public static Properties MIMETYPES = new Properties (); - + static { try { diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesContainer.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainer.java similarity index 96% rename from src/main/java/com/mosso/client/cloudfiles/FilesContainer.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainer.java index 0c652e7..21d6272 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesContainer.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainer.java @@ -2,9 +2,9 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; -import org.apache.commons.httpclient.HttpException; +import org.apache.http.HttpException; import org.apache.log4j.Logger; import java.util.List; @@ -72,7 +72,7 @@ public void setName(String name) * @throws FilesAuthorizationException * @throws FilesInvalidNameException */ - public List getObjects() throws HttpException, IOException, FilesAuthorizationException, FilesException + public List getObjects() throws IOException, FilesAuthorizationException, FilesException { if (client != null) diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesContainerExistsException.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerExistsException.java similarity index 76% rename from src/main/java/com/mosso/client/cloudfiles/FilesContainerExistsException.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerExistsException.java index 246e8ed..e5d3713 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesContainerExistsException.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerExistsException.java @@ -1,10 +1,11 @@ /** * */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; + +import org.apache.http.Header; +import org.apache.http.StatusLine; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.StatusLine; /** * @author lvaughn diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesContainerInfo.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerInfo.java similarity index 96% rename from src/main/java/com/mosso/client/cloudfiles/FilesContainerInfo.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerInfo.java index 3e16f5d..cff1b95 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesContainerInfo.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerInfo.java @@ -2,7 +2,7 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; /** * Contains basic information about the container diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesContainerNotEmptyException.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerNotEmptyException.java similarity index 74% rename from src/main/java/com/mosso/client/cloudfiles/FilesContainerNotEmptyException.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerNotEmptyException.java index ff50426..9daf3ee 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesContainerNotEmptyException.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesContainerNotEmptyException.java @@ -1,10 +1,10 @@ /** * */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.StatusLine; +import org.apache.http.Header; +import org.apache.http.StatusLine; /** * @author lvaughn diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesException.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesException.java similarity index 88% rename from src/main/java/com/mosso/client/cloudfiles/FilesException.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesException.java index 19add00..4d46b72 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesException.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesException.java @@ -1,11 +1,11 @@ /** * */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.StatusLine; -import org.apache.commons.httpclient.HttpException; +import org.apache.http.Header; +import org.apache.http.StatusLine; +import org.apache.http.HttpException; /** * @author lvaughn @@ -51,7 +51,7 @@ public String getHttpHeadersAsString () StringBuffer httpHeaderString = new StringBuffer(); for (Header h: httpHeaders) - httpHeaderString.append(h.toExternalForm()); + httpHeaderString.append(h.getName() + ": " + h.getValue() + "\n"); return httpHeaderString.toString(); } @@ -85,7 +85,7 @@ public String getHttpStatusMessage () */ public String getHttpVersion () { - return httpStatusLine == null ? null : httpStatusLine.getHttpVersion(); + return httpStatusLine == null ? null : httpStatusLine.getProtocolVersion().toString(); } } diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesInvalidNameException.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesInvalidNameException.java similarity index 86% rename from src/main/java/com/mosso/client/cloudfiles/FilesInvalidNameException.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesInvalidNameException.java index 2402956..d223355 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesInvalidNameException.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesInvalidNameException.java @@ -1,7 +1,7 @@ /** * */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; /** * @author lvaughn diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesNotFoundException.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesNotFoundException.java similarity index 76% rename from src/main/java/com/mosso/client/cloudfiles/FilesNotFoundException.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesNotFoundException.java index 7a9c2c7..5869587 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesNotFoundException.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesNotFoundException.java @@ -1,10 +1,10 @@ /** * */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.StatusLine; +import org.apache.http.Header; +import org.apache.http.StatusLine; /** * @author lvaughn diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesObject.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesObject.java similarity index 92% rename from src/main/java/com/mosso/client/cloudfiles/FilesObject.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesObject.java index 9870514..cafb378 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesObject.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesObject.java @@ -2,10 +2,10 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; import org.apache.log4j.Logger; -import org.apache.commons.httpclient.HttpException; +import org.apache.http.HttpException; import java.io.*; import java.security.NoSuchAlgorithmException; @@ -300,6 +300,9 @@ public static FilesObject uploadObject(File obj, String mimeType, FilesContainer // This should never happen logger.fatal("Install doesn't have MD5, can't upload files", nsae); } + catch (HttpException ex) { + throw new FilesException("Error in network operation", ex); + } return result; } @@ -351,4 +354,32 @@ public String getLastModified() throws HttpException, IOException, FilesAuthoriz public void setLastModified(String lastModified) { this.lastModified = lastModified; } + + /** + * + * @return True if the "object" is really a directory. + */ + public boolean isDirectory() { + return this.size == 0 && "application/directory".equals(this.mimeType); + } + + /** + * + * @return The CDN url for the object (if its container has been CDN enabled), null if + * the container hasn't been CDN enabled. + * @throws HttpException + * @throws IOException + * @throws FilesException + */ + public String getCDNURL () throws FilesException, IOException, HttpException { + try { + FilesCDNContainer c = client.getCDNContainerInfo(container); + return c.getCdnURL() + "/" + name; + } + catch (FilesNotFoundException fnfe) { + // Not enabled + return null; + } + + } } diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesObjectMetaData.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesObjectMetaData.java similarity index 98% rename from src/main/java/com/mosso/client/cloudfiles/FilesObjectMetaData.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesObjectMetaData.java index e0ca523..0651352 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesObjectMetaData.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesObjectMetaData.java @@ -2,7 +2,7 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/mosso/client/cloudfiles/FilesResponse.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesResponse.java similarity index 79% rename from src/main/java/com/mosso/client/cloudfiles/FilesResponse.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/FilesResponse.java index eee7a5c..adb8b9f 100644 --- a/src/main/java/com/mosso/client/cloudfiles/FilesResponse.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesResponse.java @@ -2,12 +2,13 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.StatusLine; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.HttpStatus; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.util.EntityUtils; +import org.apache.http.HttpEntity; import org.apache.log4j.Logger; import java.io.IOException; @@ -15,25 +16,21 @@ public class FilesResponse { - private HttpMethod httpmethod = null; + private HttpResponse response = null; + private HttpEntity entity = null; private static Logger logger = Logger.getLogger(FilesResponse.class); /** * @param method The HttpMethod that generated this response */ - public FilesResponse (HttpMethod method) + public FilesResponse (HttpResponse response) { - httpmethod = method; - + this.response = response; + entity = response.getEntity(); if (logger.isDebugEnabled()) { - logger.debug ("Request Method: "+method.getName()); - logger.debug ("Request Path: " + method.getPath()); - logger.debug ("Status Line: " + getStatusLine()); - Header[] reqHeaders = method.getRequestHeaders(); - for (Header rH: reqHeaders) - logger.debug(rH.toExternalForm()); + logger.debug ("Status Line: " + getStatusLine()); Header [] responseHeaders = getResponseHeaders(); for (int i=0; i < responseHeaders.length;i++) @@ -48,10 +45,9 @@ public FilesResponse (HttpMethod method) */ public boolean loginSuccess () { - if (getStatusCode() == HttpStatus.SC_UNAUTHORIZED ) - return false; + int statusCode = getStatusCode(); - if (getStatusCode() == HttpStatus.SC_NO_CONTENT) + if (statusCode >= 200 && statusCode < 300) return true; return false; @@ -142,7 +138,7 @@ public String getLastModified () */ public Header[] getResponseHeaders() { - return httpmethod.getResponseHeaders(); + return response.getAllHeaders(); } /** @@ -152,7 +148,7 @@ public Header[] getResponseHeaders() */ public StatusLine getStatusLine() { - return httpmethod.getStatusLine(); + return response.getStatusLine(); } /** @@ -162,7 +158,7 @@ public StatusLine getStatusLine() */ public int getStatusCode () { - return httpmethod.getStatusCode(); + return response.getStatusLine().getStatusCode(); } /** @@ -172,7 +168,7 @@ public int getStatusCode () */ public String getStatusMessage () { - return httpmethod.getStatusText(); + return response.getStatusLine().getReasonPhrase(); } /** @@ -180,10 +176,11 @@ public String getStatusMessage () * * @return The method name */ - public String getMethodName () + /*public String getMethodName () { - return httpmethod.getName(); + return response.getName(); } + */ /** * Returns the response body as text @@ -193,7 +190,7 @@ public String getMethodName () */ public String getResponseBodyAsString () throws IOException { - return httpmethod.getResponseBodyAsString(); + return EntityUtils.toString(entity); } /** @@ -204,7 +201,7 @@ public String getResponseBodyAsString () throws IOException */ public InputStream getResponseBodyAsStream () throws IOException { - return httpmethod.getResponseBodyAsStream(); + return entity.getContent(); } /** @@ -215,7 +212,7 @@ public InputStream getResponseBodyAsStream () throws IOException */ public byte[] getResponseBody () throws IOException { - return httpmethod.getResponseBody(); + return EntityUtils.toByteArray(entity); } /** @@ -226,7 +223,7 @@ public byte[] getResponseBody () throws IOException */ public Header getResponseHeader(String headerName) { - return httpmethod.getResponseHeader(headerName); + return response.getFirstHeader(headerName); } /** @@ -294,6 +291,32 @@ public String getCdnUrl () return null; } + /** + * Get the SSL URL For a shared container + * + * @return null if the header is not present or the correct value as defined by the header + */ + public String getCdnSslUrl () + { + Header cdnHeader = getResponseHeader (FilesConstants.X_CDN_SSL_URI); + if (cdnHeader != null ) + return cdnHeader.getValue(); + return null; + } + + /** + * Get the SSL URL For a shared container + * + * @return null if the header is not present or the correct value as defined by the header + */ + public String getCdnStreamingUrl () + { + Header cdnHeader = getResponseHeader (FilesConstants.X_CDN_Streaming_URI); + if (cdnHeader != null ) + return cdnHeader.getValue(); + return null; + } + /** * Returns the response headers with the given name. Note that header-name matching is case insensitive. * @@ -302,6 +325,10 @@ public String getCdnUrl () */ public Header[] getResponseHeaders(String headerName) { - return httpmethod.getResponseHeaders(headerName); + return response.getHeaders(headerName); + } + + public String getContentEncoding() { + return entity.getContentEncoding().getValue(); } } diff --git a/src/main/java/com/rackspacecloud/client/cloudfiles/FilesUtil.java b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesUtil.java new file mode 100644 index 0000000..765b6ef --- /dev/null +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/FilesUtil.java @@ -0,0 +1,136 @@ +/* + * See COPYING for license information. + */ + +package com.rackspacecloud.client.cloudfiles; + +import org.apache.log4j.Logger; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * Cloud Files utilities + */ +public class FilesUtil +{ + private static Logger logger = Logger.getLogger(FilesUtil.class); + + /** + * The name of the properties file we're looking for + */ + private final static String file = "cloudfiles.properties"; + + /** + * A cache of the properties + */ + private static Properties props = null; + + + /** + * Find the properties file in the class path and load it. + * + * @throws IOException + */ + private static synchronized void loadPropertiesFromClasspath() throws IOException + { + props = new Properties(); + InputStream io = FilesUtil.class.getClassLoader().getResourceAsStream(file); + if (io == null) + { + throw new FileNotFoundException("Property file '" + file + "' not found in the classpath."); + } + loadProperties(io); + } + + + /** + * Loads properties from input stream. + * + * @param io + * @throws IOException + */ + public static void loadProperties(final InputStream io) throws IOException + { + if (null == io) + { + throw new IllegalArgumentException("Input stream cannot be null."); + } + props = new Properties(); + props.load(io); + } + + + /** + * Look up a property from the properties file. + * + * @param key The name of the property to be found + * @return The value of the property + */ + public static String getProperty(final String key) + { + if (props == null) + { + try + { + loadPropertiesFromClasspath(); + } + catch (Exception e) + { + logger.warn("Unable to load properties file.", e); + } + } + return props.getProperty(key); + } + + + /** + * Look up a property from the properties file. + * + * @param key The name of the property to be found + * @return The value of the property + */ + public static String getProperty(final String key, final String defaultValue) + { + if (props == null) + { + try + { + loadPropertiesFromClasspath(); + } + catch (Exception e) + { + logger.warn("Unable to load properties file.", e); + } + } + return props.getProperty(key, defaultValue); + } + + + /** + * Looks up the value of a key from the properties file and converts it to an integer. + * + * @param key + * @return The value of that key + */ + public static int getIntProperty(final String key) + { + final String property = getProperty(key); + if (property == null) + { + logger.warn("Could not load integer property " + key + "."); + return -1; + } + try + { + return Integer.parseInt(property); + } + catch (NumberFormatException e) + { + logger.warn("Invalid format for a number in properties file: " + property + ".", e); + return -1; + } + } +} diff --git a/src/main/java/com/mosso/client/cloudfiles/IFilesTransferCallback.java b/src/main/java/com/rackspacecloud/client/cloudfiles/IFilesTransferCallback.java similarity index 72% rename from src/main/java/com/mosso/client/cloudfiles/IFilesTransferCallback.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/IFilesTransferCallback.java index 0d49298..12e5238 100644 --- a/src/main/java/com/mosso/client/cloudfiles/IFilesTransferCallback.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/IFilesTransferCallback.java @@ -1,7 +1,7 @@ /** * */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; /** * @author lvaughn diff --git a/src/main/java/com/mosso/client/cloudfiles/MIME.types b/src/main/java/com/rackspacecloud/client/cloudfiles/MIME.types similarity index 83% rename from src/main/java/com/mosso/client/cloudfiles/MIME.types rename to src/main/java/com/rackspacecloud/client/cloudfiles/MIME.types index 9f91f79..4a790b1 100644 --- a/src/main/java/com/mosso/client/cloudfiles/MIME.types +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/MIME.types @@ -21,7 +21,6 @@ aos application/x-nokia-9000-communicator-add-on-software aps application/mime arc application/octet-stream arj application/arj -#arj application/octet-stream art image/x-jg asf video/x-ms-asf asm text/x-asm @@ -31,10 +30,9 @@ asx application/x-mplayer2 #asx video/x-ms-asf-plugin au audio/basic #au audio/x-au -avi application/x-troff-msvideo #avi video/avi #avi video/msvideo -#avi video/x-msvideo +avi video/x-msvideo avs video/avs-video bcpio application/x-bcpio #bin application/mac-binary @@ -44,7 +42,6 @@ bin application/x-binary #bin application/x-macbinary bm image/bmp bmp image/bmp -#bmp image/x-windows-bmp boo application/book book application/book boz application/x-bzip2 @@ -52,40 +49,25 @@ bsh application/x-bsh bz application/x-bzip bz2 application/x-bzip2 c text/plain -#c text/x-c c++ text/plain cat application/vnd.ms-pki.seccat cc text/plain -#cc text/x-c ccad application/clariscad cco application/x-cocoa cdf application/cdf -#cdf application/x-cdf -#cdf application/x-netcdf cer application/pkix-cert -#cer application/x-x509-ca-cert cha application/x-chat chat application/x-chat class application/java -#class application/java-byte-code -#class application/x-java-class com application/octet-stream -#com text/plain conf text/plain cpio application/x-cpio cpp text/x-c cpt application/mac-compactpro -#cpt application/x-compactpro -#cpt application/x-cpt crl application/pkcs-crl -#crl application/pkix-crl crt application/pkix-cert -#crt application/x-x509-ca-cert -#crt application/x-x509-user-cert csh application/x-csh -#csh text/x-script.csh -css application/x-pointplus -#css text/css +css text/css cxx text/plain dcr application/x-director deepv application/x-deepv @@ -94,7 +76,6 @@ der application/x-x509-ca-cert dif video/x-dv dir application/x-director dl video/dl -#dl video/x-dl doc application/msword dot application/msword dp application/commonground @@ -102,77 +83,51 @@ drw application/drafting dump application/octet-stream dv video/x-dv dvi application/x-dvi -#dwf drawing/x-dwf (old) dwf model/vnd.dwf dwg application/acad -#dwg image/vnd.dwg -#dwg image/x-dwg dxf application/dxf -#dxf image/vnd.dwg -#dxf image/x-dwg dxr application/x-director el text/x-script.elisp elc application/x-bytecode.elisp (compiled elisp) -#elc application/x-elc env application/x-envoy eps application/postscript es application/x-esrehber etx text/x-setext evy application/envoy -#evy application/x-envoy exe application/octet-stream f text/plain -#f text/x-fortran f77 text/x-fortran f90 text/plain -#f90 text/x-fortran fdf application/vnd.fdf fif application/fractals -#fif image/fif fli video/fli -#fli video/x-fli flo image/florian flx text/vnd.fmi.flexstor fmf video/x-atomic3d-feature for text/plain -#for text/x-fortran fpx image/vnd.fpx -#fpx image/vnd.net-fpx frl application/freeloader funk audio/make g text/plain g3 image/g3fax gif image/gif gl video/gl -#gl video/x-gl gsd audio/x-gsm gsm audio/x-gsm gsp application/x-gsp gss application/x-gss gtar application/x-gtar -gz application/x-compressed -#gz application/x-gzip +gz application/x-gzip gzip application/x-gzip -#gzip multipart/x-gzip h text/plain -#h text/x-h hdf application/x-hdf help application/x-helpfile hgl application/vnd.hp-hpgl hh text/plain -#hh text/x-h -#hlb text/x-script hlp application/hlp -#hlp application/x-helpfile -#hlp application/x-winhelp hpg application/vnd.hp-hpgl hpgl application/vnd.hp-hpgl hqx application/binhex -#hqx application/binhex4 -#hqx application/mac-binhex -#hqx application/mac-binhex40 -#hqx application/x-binhex40 -#hqx application/x-mac-binhex40 hta application/hta htc text/x-component htm text/html @@ -186,9 +141,7 @@ idc text/plain ief image/ief iefs image/ief iges application/iges -#iges model/iges igs application/iges -igs model/iges ima application/x-ima imap application/x-httpd-imap inf application/inf @@ -201,58 +154,40 @@ ivr i-world/i-vrml ivy application/x-livescreen jam audio/x-jam java text/plain -#java text/x-java-source jcm application/x-java-commerce jfif image/jpeg -#jfif image/pjpeg -#jpe image/jpeg -#jpe image/pjpeg jpeg image/jpeg -#jpeg image/pjpeg jpg image/jpeg -#jpg image/pjpeg jps image/x-jps js application/x-javascript jut image/jutvision kar audio/midi -#kar music/x-karaoke -#ksh application/x-ksh ksh text/x-script.ksh la audio/nspaudio -#la audio/x-nspaudio lam audio/x-liveaudio latex application/x-latex -#lha application/lha lha application/octet-stream -#lha application/x-lha lhx application/octet-stream list text/plain lma audio/nspaudio -#lma audio/x-nspaudio log text/plain -#lsp application/x-lisp -#lsp text/x-script.lisp lst text/plain lsx text/x-la-asf ltx application/x-latex lzh application/octet-stream -#lzh application/x-lzh -#lzx application/lzx lzx application/octet-stream -#lzx application/x-lzx m text/plain -# m1v video/mpeg -#m2a audio/mpeg +m2a audio/mpeg m2v video/mpeg -#m3u audio/x-mpequrl +m3u audio/x-mpequrl +m4v video/x-m4v man application/x-troff-man mht message/rfc822 -#mhtml message/rfc822 -#mid application/x-midi -#midi audio/midi +mhtml message/rfc822 +midi audio/midi mif application/x-frame -#mjf audio/x-vnd.audioexplosion.mjuicemediafile +mjf audio/x-vnd.audioexplosion.mjuicemediafile mjpg video/x-motion-jpeg mod audio/mod mov video/quicktime @@ -260,58 +195,47 @@ movie video/x-sgi-movie mp2 audio/mpeg mp3 audio/mpeg3 mpa audio/mpeg -#mpa video/mpeg +mpa video/mpeg mpc application/x-project -#mpeg video/mpeg -mpg audio/mpeg -#mpg video/mpeg -#mpga audio/mpeg +mpeg video/mpeg +mpg video/mpeg +mpga audio/mpeg +ogg video/ogg +ogv video/ogg p text/x-pascal p10 application/pkcs10 -#p10 application/x-pkcs10 p12 application/pkcs-12 p12 application/x-pkcs12 p7a application/x-pkcs7-signature -#p7c application/pkcs7-mime p7c application/x-pkcs7-mime p7m application/pkcs7-mime -#p7m application/x-pkcs7-mime p7r application/x-pkcs7-certreqresp p7s application/pkcs7-signature part application/pro_eng pas text/pascal pbm image/x-portable-bitmap -#.pcl application/vnd.hp-pcl pcl application/x-pcl pct image/x-pict pcx image/x-pcx pdb chemical/x-pdb pdf application/pdf pfunk audio/make -#pfunk audio/make.my.funk pgm image/x-portable-graymap -pgm image/x-portable-greymap pic image/pict pict image/pict pkg application/x-newton-compatible-pkg pko application/vnd.ms-pki.pko pl text/plain -pl text/x-script.perl plx application/x-pixclscript pm image/x-xpixmap -#pm text/x-script.perl-module pm4 application/x-pagemaker pm5 application/x-pagemaker png image/png -pnm application/x-portable-anymap pnm image/x-portable-anymap pot application/mspowerpoint -pot application/vnd.ms-powerpoint -pov model/x-pov ppa application/vnd.ms-powerpoint ppm image/x-portable-pixmap pps application/mspowerpoint -pps application/vnd.ms-powerpoint ppt application/mspowerpoint #ppt application/powerpoint #ppt application/vnd.ms-powerpoint @@ -572,9 +496,9 @@ xwd image/x-xwindowdump xyz chemical/x-pdb #z application/x-compress z application/x-compressed -zip application/x-compressed +#zip application/x-compressed #zip application/x-zip-compressed -#zip application/zip +zip application/zip #zip multipart/x-zip zoo application/octet-stream -zsh text/x-script.zsh \ No newline at end of file +zsh text/x-script.zsh diff --git a/src/main/java/com/mosso/client/cloudfiles/sample/FilesAuth.java b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesAuth.java similarity index 84% rename from src/main/java/com/mosso/client/cloudfiles/sample/FilesAuth.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesAuth.java index 6916bb1..230fd55 100644 --- a/src/main/java/com/mosso/client/cloudfiles/sample/FilesAuth.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesAuth.java @@ -2,9 +2,9 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles.sample; +package com.rackspacecloud.client.cloudfiles.sample; -import com.mosso.client.cloudfiles.*; +import com.rackspacecloud.client.cloudfiles.*; public class FilesAuth { diff --git a/src/main/java/com/mosso/client/cloudfiles/sample/FilesCli.java b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesCli.java similarity index 76% rename from src/main/java/com/mosso/client/cloudfiles/sample/FilesCli.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesCli.java index 568a8c6..ed803d6 100644 --- a/src/main/java/com/mosso/client/cloudfiles/sample/FilesCli.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesCli.java @@ -2,7 +2,7 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles.sample; +package com.rackspacecloud.client.cloudfiles.sample; import java.io.BufferedReader; import java.io.File; @@ -11,20 +11,21 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.text.DecimalFormat; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import com.mosso.client.cloudfiles.FilesAccountInfo; -import com.mosso.client.cloudfiles.FilesClient; -import com.mosso.client.cloudfiles.FilesConstants; -import com.mosso.client.cloudfiles.FilesContainer; -import com.mosso.client.cloudfiles.FilesContainerExistsException; -import com.mosso.client.cloudfiles.FilesContainerInfo; -import com.mosso.client.cloudfiles.FilesContainerNotEmptyException; -import com.mosso.client.cloudfiles.FilesInvalidNameException; -import com.mosso.client.cloudfiles.FilesNotFoundException; -import com.mosso.client.cloudfiles.FilesObject; -import com.mosso.client.cloudfiles.FilesObjectMetaData; +import com.rackspacecloud.client.cloudfiles.FilesAccountInfo; +import com.rackspacecloud.client.cloudfiles.FilesClient; +import com.rackspacecloud.client.cloudfiles.FilesConstants; +import com.rackspacecloud.client.cloudfiles.FilesContainer; +import com.rackspacecloud.client.cloudfiles.FilesContainerExistsException; +import com.rackspacecloud.client.cloudfiles.FilesContainerInfo; +import com.rackspacecloud.client.cloudfiles.FilesContainerNotEmptyException; +import com.rackspacecloud.client.cloudfiles.FilesInvalidNameException; +import com.rackspacecloud.client.cloudfiles.FilesNotFoundException; +import com.rackspacecloud.client.cloudfiles.FilesObject; +import com.rackspacecloud.client.cloudfiles.FilesObjectMetaData; /** * @author lvaughn @@ -42,26 +43,11 @@ private boolean doLogin() { System.out.print("Password: "); String password = console.readLine().trim(); - - System.out.print("Account (return if using Mosso directly): "); - String account = console.readLine().trim(); - - if (account.length() == 0) { - account = null; - } - client = new FilesClient(username, password, account); - boolean result = client.login(); - - if (result) { - System.out.println("Logged in!"); - } - else { - System.out.println("Login failed"); - } + final boolean result = doLogin(username, password); return result; - } catch (IOException e) { + } catch (Exception e) { System.out.println("Error logging in!"); e.printStackTrace(); return false; @@ -70,6 +56,11 @@ private boolean doLogin() { } + private boolean doLogin(final String username, final String password) throws Exception { + client = new FilesClient(username, password); + return client.login(); + } + private static final String HELP_STRING = "Commands:\n" + " get List the containers for this account\n" + @@ -93,9 +84,16 @@ private boolean evaluateCommand(String cmd) { System.out.println(HELP_STRING); return true; } + return evaluateCommand(components); + } + + private boolean evaluateCommand(String[] components) { String command = components[0].toLowerCase(); + if ("help".equals(command)) { + System.out.println(HELP_STRING); + } // Exit if("exit".equals(command) || "quit".equals(command)) { System.out.println("Exiting"); @@ -293,7 +291,7 @@ else if(components.length == 3) { System.out.println("Container " + containerName + " does not exist"); return true; } - if (client.storeObject(containerName, file, mimeType)) { + if (client.storeObject(containerName, file, mimeType) != null) { System.out.println("Object " + file.getName() + " was created"); } return true; @@ -362,17 +360,85 @@ else if(components.length == 3) { } // We should never get here - System.out.println("Unrecognized command " + cmd); + System.out.println("Unrecognized command " + command); System.out.println(HELP_STRING); return true; } + public static class CommandLineOptions { + public final String userName; + public final String password; + public final String[] command; + + public CommandLineOptions(String[] args) { + String userName = null; + String password = null; + List command = new ArrayList(); + userName = System.getenv("CLOUDFILES_USERNAME"); + password = System.getenv("CLOUDFILES_PASSWORD"); + for (int i = 0; i < args.length; i ++) { + if ("username".equals(args[i])) { + if (i >= args.length - 1) { + throw new RuntimeException("No argument following option 'username'."); + } + userName = args[i + 1]; + i ++; + } else if ("password".equals(args[i])) { + if (i >= args.length - 1) { + throw new RuntimeException("No argument following option 'password'."); + } + password = args[i + 1]; + i ++; + } else { + command.add(args[i]); + } + } + if (userName == null) { + throw new RuntimeException("No username specified (use option 'username' or set CLOUDFILES_USERNAME environment variable)."); + } + if (password == null) { + throw new RuntimeException("No password specified (use option 'password' or set CLOUDFILES_PASSWORD environment variable)."); + } + this.userName = userName; + this.password = password; + this.command = new String[command.size()]; + command.toArray(this.command); + } + + } /** * @param args */ public static void main(String[] args) { + if (args.length < 1) { + interactiveMode(); + } else { + parseArgs(args); + } + } + + public static void parseArgs(String[] args) { + try { + final CommandLineOptions options = new CommandLineOptions(args); + final FilesCli cli = new FilesCli(); + if (!cli.doLogin(options.userName, options.password)) { + throw new RuntimeException("Failed to login."); + } + if (options.command.length == 0) { + System.out.println("Login was successful, but no other commands were specified."); + System.out.println(HELP_STRING); + } else { + cli.evaluateCommand(options.command); + } + } catch(Exception e) { + System.err.println("Error:" + e.getMessage()); + e.printStackTrace(); + } + } + + public static void interactiveMode() { FilesCli commandLine = new FilesCli(); if (commandLine.doLogin()) { diff --git a/src/main/java/com/mosso/client/cloudfiles/sample/FilesCopy.java b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesCopy.java similarity index 96% rename from src/main/java/com/mosso/client/cloudfiles/sample/FilesCopy.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesCopy.java index 38f40c5..23ff44b 100644 --- a/src/main/java/com/mosso/client/cloudfiles/sample/FilesCopy.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesCopy.java @@ -2,21 +2,21 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles.sample; +package com.rackspacecloud.client.cloudfiles.sample; import org.apache.commons.cli.*; import org.apache.commons.lang.SystemUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.io.FilenameUtils; -import org.apache.commons.httpclient.HttpException; +import org.apache.http.HttpException; import org.apache.log4j.Logger; -import com.mosso.client.cloudfiles.FilesAuthorizationException; -import com.mosso.client.cloudfiles.FilesClient; -import com.mosso.client.cloudfiles.FilesConstants; -import com.mosso.client.cloudfiles.FilesException; -import com.mosso.client.cloudfiles.FilesObject; +import com.rackspacecloud.client.cloudfiles.FilesAuthorizationException; +import com.rackspacecloud.client.cloudfiles.FilesClient; +import com.rackspacecloud.client.cloudfiles.FilesConstants; +import com.rackspacecloud.client.cloudfiles.FilesException; +import com.rackspacecloud.client.cloudfiles.FilesObject; import java.io.*; import java.util.zip.*; @@ -234,7 +234,7 @@ public static void main (String args[]) throws NoSuchAlgorithmException, FilesEx System.err.println( "Please see the logs for more details. Error Message: "+err.getMessage() ); }//catch (FilesAuthorizationException err) - catch ( IOException err) + catch ( Exception err) { logger.fatal("IOException : "+ err); System.err.println( "Please see the logs for more details. Error Message: "+err.getMessage() ); diff --git a/src/main/java/com/mosso/client/cloudfiles/sample/FilesList.java b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesList.java similarity index 96% rename from src/main/java/com/mosso/client/cloudfiles/sample/FilesList.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesList.java index a5e04e6..63b7dee 100644 --- a/src/main/java/com/mosso/client/cloudfiles/sample/FilesList.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesList.java @@ -2,7 +2,7 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles.sample; +package com.rackspacecloud.client.cloudfiles.sample; import java.io.IOException; @@ -17,9 +17,9 @@ import org.apache.commons.lang.StringUtils; // import org.apache.log4j.Logger; -import org.apache.commons.httpclient.HttpException; +import org.apache.http.HttpException; -import com.mosso.client.cloudfiles.*; +import com.rackspacecloud.client.cloudfiles.*; import java.util.*; @@ -85,10 +85,11 @@ else if (line.hasOption("H")) System.err.println( "Please see the logs for more details. Error Message: "+err.getMessage() ); err.printStackTrace(System.err); }//catch( ParseException err ) - catch (FilesException err) + catch( HttpException err ) { - System.err.println( "Please see the logs for more details. Error Message: "+err.getMessage() ); - }//catch (FilesAuthorizationException err) + System.err.println( "Please see the logs for more details. Error Message: "+err.getMessage() ); + err.printStackTrace(System.err); + }//catch( ParseException err ) catch ( IOException err) { diff --git a/src/main/java/com/mosso/client/cloudfiles/sample/FilesMakeContainer.java b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesMakeContainer.java similarity index 94% rename from src/main/java/com/mosso/client/cloudfiles/sample/FilesMakeContainer.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesMakeContainer.java index 9e6a0ce..3c6df66 100644 --- a/src/main/java/com/mosso/client/cloudfiles/sample/FilesMakeContainer.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesMakeContainer.java @@ -2,17 +2,17 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles.sample; +package com.rackspacecloud.client.cloudfiles.sample; //import org.apache.log4j.Logger; import org.apache.commons.lang.StringUtils; import org.apache.commons.cli.*; -import org.apache.commons.httpclient.HttpException; +import org.apache.http.HttpException; import java.io.IOException; import java.security.NoSuchAlgorithmException; -import com.mosso.client.cloudfiles.*; +import com.rackspacecloud.client.cloudfiles.*; public class FilesMakeContainer { @@ -60,7 +60,7 @@ else if (args.length > 0) err.printStackTrace(System.err); }//catch( ParseException err ) - catch ( IOException err) + catch ( Exception err) { System.err.println( "Please see the logs for more details. Error Message: "+err.getMessage() ); }//catch ( IOException err) diff --git a/src/main/java/com/mosso/client/cloudfiles/sample/FilesRemove.java b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesRemove.java similarity index 96% rename from src/main/java/com/mosso/client/cloudfiles/sample/FilesRemove.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesRemove.java index 443edd3..74e09a6 100644 --- a/src/main/java/com/mosso/client/cloudfiles/sample/FilesRemove.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/sample/FilesRemove.java @@ -2,18 +2,18 @@ * See COPYING for license information. */ -package com.mosso.client.cloudfiles.sample; +package com.rackspacecloud.client.cloudfiles.sample; import org.apache.log4j.Logger; import org.apache.commons.lang.StringUtils; import org.apache.commons.cli.*; -import org.apache.commons.httpclient.HttpException; +import org.apache.http.HttpException; import java.io.*; import java.security.NoSuchAlgorithmException; import java.util.*; -import com.mosso.client.cloudfiles.*; +import com.rackspacecloud.client.cloudfiles.*; public class FilesRemove { @@ -60,9 +60,9 @@ public static void main (String args[]) throws NoSuchAlgorithmException, FilesEx System.err.println( "Please see the logs for more details. Error Message: "+err.getMessage() ); err.printStackTrace(System.err); }//catch( ParseException err ) - catch ( IOException err) + catch ( Exception err) { - logger.fatal("IOException : "+ err); + logger.fatal("Exception : "+ err); System.err.println( "Please see the logs for more details. Error Message: "+err.getMessage() ); }//catch ( IOException err) }//end main diff --git a/src/main/java/com/mosso/client/cloudfiles/wrapper/OutputStreamWrapper.java b/src/main/java/com/rackspacecloud/client/cloudfiles/wrapper/OutputStreamWrapper.java similarity index 93% rename from src/main/java/com/mosso/client/cloudfiles/wrapper/OutputStreamWrapper.java rename to src/main/java/com/rackspacecloud/client/cloudfiles/wrapper/OutputStreamWrapper.java index b0e94b0..3961e0a 100644 --- a/src/main/java/com/mosso/client/cloudfiles/wrapper/OutputStreamWrapper.java +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/wrapper/OutputStreamWrapper.java @@ -1,12 +1,12 @@ /** * */ -package com.mosso.client.cloudfiles.wrapper; +package com.rackspacecloud.client.cloudfiles.wrapper; import java.io.IOException; import java.io.OutputStream; -import com.mosso.client.cloudfiles.IFilesTransferCallback; +import com.rackspacecloud.client.cloudfiles.IFilesTransferCallback; /** * @author lvaughn diff --git a/src/main/java/com/rackspacecloud/client/cloudfiles/wrapper/RequestEntityWrapper.java b/src/main/java/com/rackspacecloud/client/cloudfiles/wrapper/RequestEntityWrapper.java new file mode 100644 index 0000000..2c63f5f --- /dev/null +++ b/src/main/java/com/rackspacecloud/client/cloudfiles/wrapper/RequestEntityWrapper.java @@ -0,0 +1,102 @@ +/** + * + */ +package com.rackspacecloud.client.cloudfiles.wrapper; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; + +import com.rackspacecloud.client.cloudfiles.IFilesTransferCallback; + +/** + * @author lvaughn + * + */ +public class RequestEntityWrapper implements HttpEntity { + private HttpEntity entity; + private IFilesTransferCallback callback = null; + + public RequestEntityWrapper(HttpEntity entity, IFilesTransferCallback callback) { + this.entity = entity; + this.callback = callback; + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#getContentLength() + */ + public long getContentLength() { + return entity.getContentLength(); + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType() + */ + public Header getContentType() { + return entity.getContentType(); + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#isRepeatable() + */ + public boolean isRepeatable() { + return entity.isRepeatable(); + } + + /* (non-Javadoc) + * @see org.apache.commons.httpclient.methods.RequestEntity#writeRequest(java.io.OutputStream) + * + public void writeRequest(OutputStream stream) throws IOException { + ((RequestEntityWrapper) entity).writeRequest(new OutputStreamWrapper(stream, callback)); + + } */ + + /* (non-Javadoc) + * @see org.apache.http.HttpEntity#consumeContent() + */ + @SuppressWarnings("deprecation") + public void consumeContent() throws IOException { + entity.consumeContent(); + + } + + /* (non-Javadoc) + * @see org.apache.http.HttpEntity#getContent() + */ + public InputStream getContent() throws IOException, IllegalStateException { + return entity.getContent(); + } + + /* (non-Javadoc) + * @see org.apache.http.HttpEntity#getContentEncoding() + */ + public Header getContentEncoding() { + return entity.getContentEncoding(); + } + + /* (non-Javadoc) + * @see org.apache.http.HttpEntity#isChunked() + */ + public boolean isChunked() { + return entity.isChunked(); + } + + /* (non-Javadoc) + * @see org.apache.http.HttpEntity#isStreaming() + */ + public boolean isStreaming() { + return entity.isStreaming(); + } + + /* (non-Javadoc) + * @see org.apache.http.HttpEntity#writeTo(java.io.OutputStream) + */ + public void writeTo(OutputStream os) throws IOException { + entity.writeTo(new OutputStreamWrapper(os, callback)); + + } + +} diff --git a/src/test/java/com/rackspacecloud/client/cloudfiles/FilesClientTestCase.java b/src/test/java/com/rackspacecloud/client/cloudfiles/FilesClientTestCase.java new file mode 100644 index 0000000..aaf0cbb --- /dev/null +++ b/src/test/java/com/rackspacecloud/client/cloudfiles/FilesClientTestCase.java @@ -0,0 +1,2069 @@ +package com.rackspacecloud.client.cloudfiles; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.apache.http.HttpException; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang.SystemUtils; +import org.apache.log4j.Logger; + +import com.rackspacecloud.client.cloudfiles.FilesAccountInfo; +import com.rackspacecloud.client.cloudfiles.FilesCDNContainer; +import com.rackspacecloud.client.cloudfiles.FilesClient; +import com.rackspacecloud.client.cloudfiles.FilesConstants; +import com.rackspacecloud.client.cloudfiles.FilesContainer; +import com.rackspacecloud.client.cloudfiles.FilesContainerExistsException; +import com.rackspacecloud.client.cloudfiles.FilesContainerInfo; +import com.rackspacecloud.client.cloudfiles.FilesInvalidNameException; +import com.rackspacecloud.client.cloudfiles.FilesNotFoundException; +import com.rackspacecloud.client.cloudfiles.FilesObject; +import com.rackspacecloud.client.cloudfiles.FilesObjectMetaData; +import com.rackspacecloud.client.cloudfiles.FilesUtil; +import com.rackspacecloud.client.cloudfiles.IFilesTransferCallback; + + +import junit.framework.TestCase; + +public class FilesClientTestCase extends TestCase { + private static Logger logger = Logger.getLogger(FilesClientTestCase.class); + private static File SYSTEM_TMP = SystemUtils.getJavaIoTmpDir(); + private static int NUMBER_RANDOM_BYTES = 513; + + public void testConstructor() { + FilesClient client = new FilesClient("foo", "bar"); + + assertNotNull(client); + assertEquals("foo", client.getUserName()); + assertEquals("bar", client.getPassword()); + + } + + public void testNoArgConstructor() { + FilesClient client = new FilesClient(); + + assertNotNull(client); + assertEquals(FilesUtil.getProperty("username"), client.getUserName()); + assertEquals(FilesUtil.getProperty("password"), client.getPassword()); + assertEquals(FilesUtil.getProperty("account"), client.getAccount()); + } + + public void testLogin() { + FilesClient client = new FilesClient(); + + try { + assertTrue(client.login()); + } catch (Exception e) { + fail(e.getMessage()); + } + + // Now try a failed login + // Note: This causes a warning from DefaultHttpClient along these lines: + // 13 Dec 2010 15:46:26 WARN impl.client.DefaultHttpClient - Authentication error: Unable to respond to any of these challenges: {} + // It's just trying a little too hard to be helpful. + client = new FilesClient(FilesUtil.getProperty("username"), + FilesUtil.getProperty("password") + " this is a bogus password", + FilesUtil.getProperty("account")); + try { + assertFalse(client.login()); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + public void testAccountInfo() { + String containerName = createTempContainerName("acct-info"); + String filename = makeFileName("accountinfo"); + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + //logger.error(client.getStorageURL()); + client.createContainer(containerName); + + // See that it's there + assertTrue(client.containerExists(containerName)); + assertNotNull(client.getContainerInfo(containerName)); + + // Add some data + byte randomData[] = makeRandomBytes(); + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", filename, new HashMap())); + + // Do the test if we have an account + if (FilesUtil.getProperty("account") != null) { + FilesAccountInfo info = client.getAccountInfo(); + assertTrue(info.getContainerCount() > 0); + assertTrue(info.getBytesUsed() >= randomData.length); + } + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testMultipleFilesNotThere() { + // Tests to make sure we're releasing connections with 404's + FilesClient client = new FilesClient(); + String filename = makeFileName("random"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + try { + byte[] content = makeRandomFile(fullPath); + assertTrue(client.login()); + String containerName = createTempContainerName("file-not-there"); + client.createContainer(containerName); + + String[] names = new String[10]; + for(int i=0; i < 10; ++i) names[i] = "File" + (i + 1) + ".txt"; + for(int i=0; i < 5; ++i) + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", names[i])); + + for (int i = 0; i < 10; i++) { + String fileName = names[i]; + + byte[] retrievedContent = null; + try { + retrievedContent = client.getObject(containerName, fileName); + assertArrayEquals(content, retrievedContent); + } catch(FilesNotFoundException ex) { + assertTrue(i >= 5); + } + } + // Cleanup + for(int i=0; i < 5; ++i) + client.deleteObject(containerName, names[i]); + client.deleteContainer(containerName); + + } catch (Exception e) { + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + } + + public void testContainerCreation() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("container"); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + //logger.error("Creating the container"); + client.createContainer(containerName); + //logger.error("URL:\n" + client.getStorageURL() + "/" + containerName + "\n"); + //Thread.sleep(10000); + + // See that it's there + assertTrue(client.containerExists(containerName)); + assertNotNull(client.getContainerInfo(containerName)); + + // Try Adding it again + try { + client.createContainer(containerName); + fail("Allowed duplicate container creation"); + } + catch (FilesContainerExistsException fcee) { + // Hooray! + } + + // See that it's still there + assertTrue(client.containerExists(containerName)); + + // Delete it + assertTrue(client.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(client.containerExists(containerName)); + + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + public void testAlternateLoginMethod() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("container"); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + //logger.error("Creating the container"); + client.createContainer(containerName); + //logger.error("URL:\n" + client.getStorageURL() + "/" + containerName + "\n"); + Thread.sleep(1000); + + // See that it's there + assertTrue(client.containerExists(containerName)); + assertNotNull(client.getContainerInfo(containerName)); + + // Create a new Client + FilesClient newClient = new FilesClient(); + newClient.login(client.getAuthToken(), client.getStorageURL(), client.getCdnManagementURL()); + + // See that it's still there + assertTrue(newClient.containerExists(containerName)); + assertNotNull(newClient.getContainerInfo(containerName)); + + // Try Adding it again + try { + newClient.createContainer(containerName); + fail("Allowed duplicate container creation"); + } + catch (FilesContainerExistsException fcee) { + // Hooray! + } + + // See that it's still there + assertTrue(newClient.containerExists(containerName)); + + // Delete it + assertTrue(newClient.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(newClient.containerExists(containerName)); + + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + public void testContainerNotThereDeletion() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("I'mNotHere!"); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + boolean exceptionThrown = false; + try { + client.deleteContainer(containerName); + fail("Exception not thrown"); + } + catch (FilesNotFoundException fnfe) { + exceptionThrown = true; + } + assertTrue (exceptionThrown); + + // Make still not there + assertFalse(client.containerExists(containerName)); + + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + public void testContainerCreationWithSpaces() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("with space+and+plus"); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + client.createContainer(containerName); + + // See that it's there + assertTrue(client.containerExists(containerName)); + assertNotNull(client.getContainerInfo(containerName)); + + // Try Adding it again + try { + client.createContainer(containerName); + fail("Allowed duplicate container creation"); + } + catch (FilesContainerExistsException fcee) { + // Pass this case + } + + // See that it's still there + assertTrue(client.containerExists(containerName)); + + boolean found = false; + List containers = client.listContainers(); + for (FilesContainer cont : containers) { + // logger.warn(cont.getName()); + if(containerName.equals(cont.getName())) found = true; + } + assertTrue(found); + + + // Delete it + assertTrue(client.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(client.containerExists(containerName)); + + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testContainerInfoListing() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName(""); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + client.createContainer(containerName); + + // See that it's there + assertTrue(client.containerExists(containerName)); + assertNotNull(client.getContainerInfo(containerName)); + + // Try Adding it again + try { + client.createContainer(containerName); + fail("Allowed duplicate container creation"); + } + catch (FilesContainerExistsException fcee) { + // Hooray! + } + + // See that it's still there + assertTrue(client.containerExists(containerName)); + + boolean found = false; + List containers = client.listContainersInfo(); + for (FilesContainerInfo info : containers) { + if(containerName.equals(info.getName())) { + found = true; + assertEquals(0, info.getTotalSize()); + assertEquals(0, info.getObjectCount()); + } + } + assertTrue(found); + + + // Delete it + assertTrue(client.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(client.containerExists(containerName)); + + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testUserAgent() { + FilesClient client = new FilesClient(); + assertEquals(FilesConstants.USER_AGENT, client.getUserAgent()); + client.setUserAgent("Java-Test-User-Agent"); + assertEquals("Java-Test-User-Agent", client.getUserAgent()); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("user-agent"); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + client.createContainer(containerName); + + // See that it's there + assertTrue(client.containerExists(containerName)); + assertNotNull(client.getContainerInfo(containerName)); + + // Delete it + assertTrue(client.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(client.containerExists(containerName)); + + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + public void testContainerNameNoSlashes() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("/"); + + // Make sure they're not there + assertFalse(client.containerExists(containerName)); + + // Try to add it + boolean exceptionThrown = false; + try { + client.createContainer(containerName); + fail("Should not have been able to create container: " + containerName); + } + catch (FilesInvalidNameException fine) { + exceptionThrown = true; + } + assertTrue(exceptionThrown); + } catch (Exception e) { + fail(e.getMessage()); + } + } + public void testCustomHttpClient() { + String containerName = createTempContainerName("customHttp"); + String filename = makeFileName("customHttpFile"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + logger.debug("Test File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + + DefaultHttpClient httpClient = new DefaultHttpClient(); + + FilesClient client = new FilesClient(httpClient, + FilesUtil.getProperty("username"), + FilesUtil.getProperty("password"), + null, + FilesUtil.getProperty("account"), + FilesUtil.getIntProperty("connection_timeout")); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + logger.info("About to save: " + filename); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + + } + + public void testFileSaving() { + String containerName = createTempContainerName("file-test"); + String filename = makeFileName("random"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + logger.info("Test File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + logger.info("About to save: " + filename); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + + } + public void testSlashInName() { + String containerName = createTempContainerName("slashTest"); + String filename = makeFileName("slash/backslash\\slash"); + try { + byte randomData[] = makeRandomBytes(); + FilesClient client = new FilesClient(); + // client.setUseETag(false); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", filename, new HashMap())); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + public void testSaveAs() { + String containerName = createTempContainerName("file-test"); + String filename = makeFileName("random"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + String otherFileName = "Bob"; + logger.info("Test File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + logger.info("About to save: " + filename); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", otherFileName)); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals("Bob", obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, otherFileName)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, otherFileName); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, otherFileName); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + + } + public void testFileSavingWithCallback() { + String containerName = createTempContainerName("file-test"); + String filename = makeFileName("random"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + logger.info("Test File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + logger.info("About to save: " + filename); + TesterCallback callback = new TesterCallback(); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename, callback)); + + // Make sure the callback was called + assertEquals(randomData.length, callback.bytesSent); + assertEquals(1, callback.nCalls); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + if (e.getCause() != null) e.getCause().printStackTrace(); + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + } + public void testFileSavingWithMetadata() { + String containerName = createTempContainerName("meta-data-test"); + String filename = makeFileName("random-with-meta"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + logger.info("Test File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + HashMap meta = new HashMap(); + meta.put("Foo", "bar"); + meta.put("Uni", "\u0169\u00f1\u00efcode-test"); + meta.put("Width", "336"); + meta.put("Height", "183"); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename, meta)); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Make sure the metadata is correct + FilesObjectMetaData metadata = client.getObjectMetaData(containerName, filename); + assertNotNull(metadata); + Map serverMetadata = metadata.getMetaData(); + assertEquals(meta.size(), serverMetadata.size()); + for(String key : meta.keySet()) { + assertTrue(serverMetadata.containsKey(key)); + assertEquals(meta.get(key), serverMetadata.get(key)); + } + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (FilesException e) { + e.printStackTrace(); + fail(e.getHttpStatusMessage() + ":" + e.getMessage()); + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + + } + + public void testMetadataUpdate() { + String containerName = createTempContainerName("metadata-update"); + String filename = makeFileName("random-with-meta"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + logger.info("Test File Location: " + fullPath); + try { + makeRandomFile(fullPath); + + // DefaultHttpClient is single threaded, which will catch a big we've seen with not + // releasing the connection + DefaultHttpClient httpClient = new DefaultHttpClient(); + FilesClient client = new FilesClient(httpClient, + FilesUtil.getProperty("username"), + FilesUtil.getProperty("password"), + null, + FilesUtil.getProperty("account"), + FilesUtil.getIntProperty("connection_timeout")); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + HashMap meta = new HashMap(); + meta.put("Foo", "bar"); + meta.put("Uni", "\u0169\u00f1\u00efcode-test"); + meta.put("Width", "336"); + meta.put("Height", "183"); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename, meta)); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the metadata is correct + FilesObjectMetaData metadata = client.getObjectMetaData(containerName, filename); + assertNotNull(metadata); + Map serverMetadata = metadata.getMetaData(); + assertEquals(meta.size(), serverMetadata.size()); + for(String key : meta.keySet()) { + assertTrue(serverMetadata.containsKey(key)); + assertEquals(meta.get(key), serverMetadata.get(key)); + } + + // Make sure we can update + meta.put("Foo", "one"); + meta.put("Uni", "\u0169\u00f1\u00eftwo"); + meta.put("Width", "three"); + meta.put("Height", "four"); + assertTrue(client.updateObjectMetadata(containerName, filename, meta)); + + // Re-fect and make sure things are the same + objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + metadata = client.getObjectMetaData(containerName, filename); + assertNotNull(metadata); + serverMetadata = metadata.getMetaData(); + assertEquals(meta.size(), serverMetadata.size()); + for(String key : meta.keySet()) { + assertTrue(serverMetadata.containsKey(key)); + assertEquals(meta.get(key), serverMetadata.get(key)); + } + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (FilesException e) { + e.printStackTrace(); + fail(e.getHttpStatusMessage() + ":" + e.getMessage()); + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + } + + public void testFileSavingNoETag() { + String containerName = createTempContainerName("etagless"); + String filename = makeFileName("etagless"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + logger.info("Test File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + FilesClient client = new FilesClient(); + assertTrue(client.getUseETag()); + client.setUseETag(false); + assertFalse(client.getUseETag()); + + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + + } + + public void testCopyObject() throws Exception { + String containerSrc = createTempContainerName("copy-source"); + String containerDest = createTempContainerName("copy-dest"); + doTestCopyObject(containerSrc, containerDest); + } + + public void testCopyObjectSameContainer() throws Exception { + String containerSrc = createTempContainerName("copy-source1"); + doTestCopyObject(containerSrc, containerSrc); + } + + public void testCopyObjectNoDestContainer() throws Exception { + String containerSrc = createTempContainerName("copy-source2"); + String containerDest = null; + + try { + System.err.println("-- expected 404 exception below --"); + doTestCopyObject(containerSrc, containerDest); + fail("exception expected"); + + } catch (FilesException fe) { + assertEquals(404, fe.getHttpStatusCode()); + } + } + + public void doTestCopyObject(String containerSrc, String containerDest) + throws Exception { + String filename = makeFileName("copy"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), + filename); + logger.info("Test Copy File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerSrc); + if (null != containerDest && !containerSrc.equals(containerDest)) { + client.createContainer(containerDest); + } + + // Store it + logger.info("About to save: " + filename); + String mime = "application/octet-stream"; + assertNotNull(client.storeObjectAs(containerSrc, + new File(fullPath), + mime, + filename)); + + verifyStoredObject(containerSrc, + filename, + mime, + randomData, + client); + + // Do the copy + logger.info("About to copy: " + filename); + String dest = null == containerDest ? "not-exist" : containerDest; + String etag = client.copyObject(containerSrc, + filename, + dest, + filename); + + String md5 = FilesClient.md5Sum(randomData); + assertEquals(md5, etag); + + verifyStoredObject(containerDest, + filename, + mime, + randomData, + client); + + // Clean up + client.deleteObject(containerSrc, filename); + assertTrue(client.deleteContainer(containerSrc)); + if (null != containerDest && !containerSrc.equals(containerDest)) { + client.deleteObject(containerDest, filename); + assertTrue(client.deleteContainer(containerDest)); + } + + } catch (FilesException fe) { + System.err.println(fe.getHttpHeadersAsString()); + System.err.println(fe.getHttpStatusMessage()); + System.err.println(fe.getHttpStatusCode()); + System.err.println(fe.getMessage()); + fe.printStackTrace(); + throw fe; + + } catch (Exception e) { + e.printStackTrace(); + System.err.println(e.getMessage()); + throw e; + + } finally { + File f = new File(fullPath); + f.delete(); + } + } + + private void verifyStoredObject(String container, + String objName, + String mime, + byte[] data, + FilesClient client) + throws IOException, HttpException { + + // Make sure it's there + List objects = client.listObjects(container); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(objName, obj.getName()); + assertEquals(mime, obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(data, client.getObject(container, objName)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(container, objName); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(data, otherData); + + // Could hang if there's a bug on the other end + assertEquals(-1, is.read()); + } + + public void testContainerListing() { + String containerName = createTempContainerName(""); + String filename = makeFileName(""); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + logger.info("Test File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + logger.info("About to save: " + filename); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + assertEquals(NUMBER_RANDOM_BYTES, obj.getSize()); + assertEquals(md5Sum(randomData), obj.getMd5sum()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + + } + + public void testContainerListingWithXML() { + String containerName = createTempContainerName(""); + String filename = makeFileName(""); + try { + byte randomData[] = makeRandomBytes(); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + logger.info("About to save: " + filename); + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", filename, new HashMap())); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + assertEquals(NUMBER_RANDOM_BYTES, obj.getSize()); + assertEquals(md5Sum(randomData), obj.getMd5sum()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + } + + public void testByteArraySaving() { + String containerName = createTempContainerName("byte-array"); + String filename = makeFileName("bytearray"); + try { + byte randomData[] = makeRandomBytes(); + FilesClient client = new FilesClient(); + // client.setUseETag(false); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", filename, new HashMap())); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testLineNoiseSaving() { + String containerName = createTempContainerName("[]<>{}!@#$%^&*()_-+=|,.?"); + String filename = makeFileName("/[]<>{}!@#$%^&*()_-+=|,.?/"); + try { + byte randomData[] = makeRandomBytes(); + FilesClient client = new FilesClient(); + // client.setUseETag(false); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", filename, new HashMap())); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + logger.error("LGV: LINE NOISE", e); + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testRequestEntitySaving() { + String containerName = createTempContainerName("requst-entity"); + String filename = makeFileName("req-entity"); + try { + byte randomData[] = makeRandomBytes(); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + ByteArrayEntity entity = new ByteArrayEntity(randomData); + entity.setContentType("test/content_type"); + + assertNotNull(client.storeObjectAs(containerName, filename, entity, new HashMap(), FilesClient.md5Sum(randomData))); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("test/content_type", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testObjectListing() { + String containerName = createTempContainerName("object-listing-marker"); + try { + byte randomData[] = makeRandomBytes(); + FilesClient client = new FilesClient(); + // client.setUseETag(false); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + for (int i=0; i < 10; i++) { + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", "testfile" + i + ".bogus", new HashMap())); + } + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(10, objects.size()); + for (int i=0; i < 10; i++) { + FilesObject obj = objects.get(i); + assertEquals("testfile" + i + ".bogus", obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + } + + // Now do a limit + objects = client.listObjects(containerName, 3); + assertEquals(3, objects.size()); + for (int i=0; i < 3; i++) { + FilesObject obj = objects.get(i); + assertEquals("testfile" + i + ".bogus", obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + } + + // Now check out a marker + objects = client.listObjects(containerName, 4, "testfile3.bogus"); + assertEquals(4, objects.size()); + for (int i=0; i < 4; i++) { + FilesObject obj = objects.get(i); + assertEquals("testfile" + (i + 4) + ".bogus", obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + } + + // Clean up + for (int i=0; i < 10; i++) { + client.deleteObject(containerName, "testfile" + i + ".bogus"); + } + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testObjectListingWithDelimiter() { + String containerName = createTempContainerName("delimiter"); + try { + byte randomData[] = makeRandomBytes(); + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + for (int i=0; i < 10; i++) { + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", "foo/testfile" + i + ".bogus", new HashMap())); + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", "bar/testfile" + i + ".bogus", new HashMap())); + } + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(20, objects.size()); + + // Now check with delimiter + objects = client.listObjects(containerName, new Character('/')); + assertEquals(2, objects.size()); + for(FilesObject obj : objects) { + assertTrue(obj.isDirectory()); + } + + objects = client.listObjects(containerName, "foo", new Character('/')); + assertEquals(10, objects.size()); + for (FilesObject obj : objects) { + assertTrue(obj.getName().startsWith("foo/")); + } + + // Clean up + for (int i=0; i < 10; i++) { + client.deleteObject(containerName, "foo/testfile" + i + ".bogus"); + client.deleteObject(containerName, "bar/testfile" + i + ".bogus"); + } + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testContainerListingWithLimitMarker() { + try { + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Populate our account + for (int i=0; i < 20; i++) { + client.createContainer("test_container_" + i); + } + + // Make sure it's there + List originalContainers = client.listContainers(); + assertTrue(20 <=originalContainers.size()); + + // Now do a limit + List containers = client.listContainers(5); + assertEquals(5, containers.size()); + for (int i=0; i < 5; i++) { + FilesContainer container = containers.get(i); + assertEquals(originalContainers.get(i).getName(), container.getName()); + } + + // Now check out a marker + containers = client.listContainers(10, originalContainers.get(originalContainers.size() - 5).getName()); + assertEquals(4, containers.size()); + for (int i=0; i < 2; i++) { + FilesContainer container = containers.get(i); + assertEquals(originalContainers.get(originalContainers.size() - 4 + i).getName(), container.getName()); + } + + // Clean up + for (int i=0; i < 20; i++) { + assertTrue(client.deleteContainer("test_container_" + i)); + } + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testByteArraySavingWithCallback() { + String containerName = createTempContainerName("byte-array"); + String filename = makeFileName("bytearray"); + try { + byte randomData[] = makeRandomBytes(1024 * 100); // 100 K to make sure we do more with the callback + FilesClient client = new FilesClient(); + // client.setUseETag(false); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + TesterCallback callback = new TesterCallback(); + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", filename, new HashMap(), callback)); + + // Make sure it all got written + assertEquals(randomData.length, callback.bytesSent); + assertEquals(randomData.length/8192 + 1, callback.nCalls); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[randomData.length]; + int loc = 0; + int bytesRead = 0; + while ((bytesRead = is.read(otherData, loc, otherData.length - loc)) > 0) { + loc += bytesRead; + } + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testStreamedSaving() { + String containerName = createTempContainerName("streamed"); + String filename = makeFileName("streamed"); + try { + byte randomData[] = makeRandomBytes(1024 * 100); // 100 K to make sure it's interesting + FilesClient client = new FilesClient(); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + assertNotNull(client.storeStreamedObject(containerName, new ByteArrayInputStream(randomData), "application/octet-stream", filename, new HashMap())); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[randomData.length]; + int loc = 0; + int bytesRead = 0; + while ((bytesRead = is.read(otherData, loc, otherData.length - loc)) > 0) { + loc += bytesRead; + } + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testMD5IssueSaving() { + String containerName = createTempContainerName("byte-array"); + String filename = makeFileName("bytearray"); + try { + byte randomData[] = makeRandomBytes(); + + while(zeroStripMd5Sum(randomData).length() ==32) { + randomData = makeRandomBytes(); + } + FilesClient client = new FilesClient(); + // client.setUseETag(false); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", filename, new HashMap())); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + private static String zeroStripMd5Sum (byte[] data) throws IOException, NoSuchAlgorithmException + { + MessageDigest digest = MessageDigest.getInstance("MD5"); + + byte[] md5sum = digest.digest(data); + BigInteger bigInt = new BigInteger(1, md5sum); + + return bigInt.toString(16); + } + + private static String md5Sum (byte[] data) throws IOException, NoSuchAlgorithmException + { + MessageDigest digest = MessageDigest.getInstance("MD5"); + + byte[] md5sum = digest.digest(data); + BigInteger bigInt = new BigInteger(1, md5sum); + + String result = bigInt.toString(16); + + while(result.length() < 32) { + result = "0" + result; + } + + return result; + } + + public void testUnicodeContainer() { + String containerName = createTempContainerName("\u0169\u00f1\u00efcode-test-\u03de"); + try { + FilesClient client = new FilesClient(FilesUtil.getProperty("username"), FilesUtil.getProperty("password"), FilesUtil.getProperty("account")); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + + // Make sure it's there + assertTrue(client.containerExists(containerName)); + + // Make sure we can get the container info + assertNotNull(client.getContainerInfo(containerName)); + + // Clean up + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testUnicode() { + String containerName = createTempContainerName("\u0169\u00f1\u00efcode-test-\u03de"); + String filename = makeFileName("unicode_\u03DA_\u2042"); + filename = makeFileName("\u00f1\u00efcode-test-\u03de"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + logger.info("Test File Location: " + fullPath); + try { + byte randomData[] = makeRandomFile(fullPath); + FilesClient client = new FilesClient(FilesUtil.getProperty("username"), FilesUtil.getProperty("password"), FilesUtil.getProperty("account")); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + + // Store it + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + + // Make sure it's there + List objects = client.listObjects(containerName); + assertEquals(1, objects.size()); + FilesObject obj = objects.get(0); + assertEquals(filename, obj.getName()); + assertEquals("application/octet-stream", obj.getMimeType()); + + assertNotNull(obj.getMetaData()); + + // Make sure the data is correct + assertArrayEquals(randomData, client.getObject(containerName, filename)); + + // Make sure the data is correct as a stream + InputStream is = client.getObjectAsStream(containerName, filename); + byte otherData[] = new byte[NUMBER_RANDOM_BYTES]; + is.read(otherData); + assertArrayEquals(randomData, otherData); + assertEquals(-1, is.read()); // Could hang if there's a bug on the other end + + // Make sure we can get the container info + assertNotNull(client.getContainerInfo(containerName)); + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } + catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + + } + + public void testCDNContainerList() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + + List containers = client.listCdnContainers(); + assertTrue(containers.size() > 0); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testCDNContainerListLimitMarker() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + + List originalContainers = client.listCdnContainers(); + assertTrue(originalContainers.size() > 0); + + // Now do a limit + List containers = client.listCdnContainers(5); + assertEquals(5, containers.size()); + for (int i=0; i < 5; i++) { + assertEquals(originalContainers.get(i), containers.get(i)); + } + + // Now check out a marker + containers = client.listCdnContainers(10, originalContainers.get(originalContainers.size() - 5)); + assertEquals(4, containers.size()); + for (int i=0; i < 2; i++) { + assertEquals(originalContainers.get(originalContainers.size() - 4 + i), containers.get(i)); + } + } catch (Exception e) { + fail(e.getMessage()); + } + } + public void testCDNContainerFullListing() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + + List originalContainers = client.listCdnContainers(); + assertTrue(originalContainers.size() > 0); + + // Now do a limit + List containers = client.listCdnContainerInfo(5); + assertEquals(5, containers.size()); + for (int i=0; i < 5; i++) { + assertEquals(originalContainers.get(i), containers.get(i).getName()); + assertNotNull(containers.get(i).getSSLURL()); + assertNotNull(containers.get(i).getStreamingURL()); + } + + // Now check out a marker + containers = client.listCdnContainerInfo(10, originalContainers.get(originalContainers.size() - 5)); + assertEquals(4, containers.size()); + for (int i=0; i < 2; i++) { + assertEquals(originalContainers.get(originalContainers.size() - 4 + i), containers.get(i).getName()); + } + } catch (Exception e) { + fail(e.getMessage()); + } + } + + public void testCDNUrlOnObject() { + String containerName = createTempContainerName("cdnURLtest"); + String filename = makeFileName("cdnURLtest"); + try { + byte randomData[] = makeRandomBytes(); + FilesClient client = new FilesClient(); + // client.setUseETag(false); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + String cdnUrl = client.cdnEnableContainer(containerName); + + // Store it + assertTrue(client.storeObject(containerName, randomData, "application/octet-stream", filename, new HashMap())); + + // Make sure it's there + List objects = client.listObjects(containerName); + + // See that the CDN URL works + FilesObject obj = objects.get(0); + assertEquals(cdnUrl + "/" + filename, obj.getCDNURL()); + + // Clean up + client.deleteObject(containerName, filename); + assertTrue(client.deleteContainer(containerName)); + + } catch (Exception e) { + fail(e.getMessage()); + } + + } + + public void testCDNPurge() { + String containerName = createTempContainerName("cdnPurgeTest"); + try { + FilesClient client = new FilesClient(); + // client.setUseETag(false); + assertTrue(client.login()); + + // Set up + client.createContainer(containerName); + String cdnUrl = client.cdnEnableContainer(containerName); + assertNotNull(cdnUrl); + + //client.purgeCDNContainer(containerName, "lowell.vaughn@rackspace.com"); + //client.purgeCDNContainer(containerName, null); + //client.purgeCDNObject(containerName, "object.txt", "lowell.vaughn@rackspace.com"); + client.purgeCDNObject(containerName, "object.txt", null); + client.purgeCDNObject(containerName, "path/object.txt", null); + + assertTrue(client.deleteContainer(containerName)); + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + } + + public void testCDNContainerFullListingAll() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String container = createTempContainerName("aaa_\u1422_aaa"); + client.cdnEnableContainer(container); + // Now do a limit + client.listCdnContainerInfo(); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + + public void testCDNApi() { + String containerName = createTempContainerName("java api Test\u03DA_\u2042\u03de#<>\u2043\u2042\u2044\u2045"); + //containerName = createTempContainerName("java Api Test no uniocde"); + //logger.warn("Container:" + containerName.length() + ":" + containerName); + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + + List containers = client.listCdnContainers(); + int originalContainerListSize = containers.size(); + + assertFalse(client.isCDNEnabled(containerName)); + + String url = client.cdnEnableContainer(containerName); + assertNotNull(url); + assertTrue(client.isCDNEnabled(containerName)); + containers = client.listCdnContainers(); + assertEquals(originalContainerListSize + 1, containers.size()); + + boolean found = false; + for(String container : containers) { + // logger.warn(container); + if (containerName.equals(container)) found = true; + } + assertTrue(found); + + FilesCDNContainer info = client.getCDNContainerInfo(containerName); + assertTrue(info.isEnabled()); +// assertEquals("", info.getUserAgentACL()); +// assertEquals("", info.getReferrerACL()); + String cdnUrl = info.getCdnURL(); + assertNotNull(cdnUrl); + assertNotNull(info.getSSLURL()); + assertNotNull(info.getStreamingURL()); + + client.cdnUpdateContainer(containerName, 31415, false, true); + assertFalse(client.isCDNEnabled(containerName)); + info = client.getCDNContainerInfo(containerName); + assertFalse(info.isEnabled()); + assertTrue(info.getRetainLogs()); + assertEquals(31415, info.getTtl()); + assertEquals(cdnUrl, info.getCdnURL()); + + //client.cdnUpdateContainer(containerName, 54321, true, "Referrer Test", "User Agent Acl Test"); + client.cdnUpdateContainer(containerName, 54321, true, false); + assertTrue(client.isCDNEnabled(containerName)); + info = client.getCDNContainerInfo(containerName); + assertTrue(info.isEnabled()); + assertFalse(info.getRetainLogs()); + assertEquals(54321, info.getTtl()); + assertEquals(cdnUrl, info.getCdnURL()); +// assertEquals("Referrer Test", info.getReferrerACL()); +// assertEquals("User Agent Acl Test", info.getUserAgentACL()); + + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + // Test container name limits + public void testContainerNameLimits() { + FilesClient fc = new FilesClient(); + try { + assertTrue(fc.login()); + StringBuilder nameBuilder = new StringBuilder(createTempContainerName("long")); + while(nameBuilder.length() <= FilesConstants.CONTAINER_NAME_LENGTH) { + nameBuilder.append("a"); + } + try { + fc.createContainer(nameBuilder.toString()); + // Note, we shouldn't get here, but want to clean up if we do + fc.deleteContainer(nameBuilder.toString()); + fail("No exception thrown"); + } + catch (FilesInvalidNameException fine) { + // Hooray! + } + } + catch (Exception ex) { + fail(ex.getMessage()); + } + } + + public void testPathCreationAndListing() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("pathTest"); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + client.createContainer(containerName); + + // See that it's there + assertTrue(client.containerExists(containerName)); + + // Add a path and two files + byte randomData[] = makeRandomBytes(); + client.createPath(containerName, "foo"); + client.storeObject(containerName, randomData, "application/octet-stream", "notInContainer.dat", new HashMap()); + client.storeObject(containerName, randomData, "application/octet-stream", "foo/inContainer.dat", new HashMap()); + + List allObjects = client.listObjects(containerName); + List pathObjects = client.listObjects(containerName, "foo"); + + assertEquals(3, allObjects.size()); + assertEquals(1, pathObjects.size()); + assertEquals("foo/inContainer.dat", pathObjects.get(0).getName()); + + // Delete it + client.deleteObject(containerName, "notInContainer.dat"); + client.deleteObject(containerName, "foo/inContainer.dat"); + client.deleteObject(containerName, "foo"); + assertTrue(client.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(client.containerExists(containerName)); + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + public void testPathCreation() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("pathTest"); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + client.createContainer(containerName); + + // See that it's there + assertTrue(client.containerExists(containerName)); + + // Add a path and two files + client.createFullPath(containerName, "foo/bar/baz"); + + List allObjects = client.listObjects(containerName); + + assertEquals(3, allObjects.size()); + + // If we don't throw an exception, we should be OK + client.getObject(containerName, "foo"); + client.getObject(containerName, "foo/bar"); + client.getObject(containerName, "foo/bar/baz"); + + // Delete it + client.deleteObject(containerName, "foo/bar/baz"); + client.deleteObject(containerName, "foo/bar"); + client.deleteObject(containerName, "foo"); + assertTrue(client.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(client.containerExists(containerName)); + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testFilesObjectPath() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + String containerName = createTempContainerName("FOpathTest"); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + client.createContainer(containerName); + + // See that it's there + assertTrue(client.containerExists(containerName)); + + // Add a path and two files + client.createPath(containerName, "test"); + + List allObjects = client.listObjects(containerName); + + assertEquals(1, allObjects.size()); + + FilesObject obj = allObjects.get(0); + assertEquals(0, obj.getSize()); + assertEquals("application/directory", obj.getMimeType()); + + // If we don't throw an exception, we should be OK + client.getObject(containerName, "test"); + + // Delete it + client.deleteObject(containerName, "test"); + assertTrue(client.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(client.containerExists(containerName)); + + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testURLs() { + // Test to make sure these are getting set and are visible to the outside world (needed for Cyberduck's SSL). + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + assertNotNull(client.getCdnManagementURL()); + assertNotNull(client.getStorageURL()); + + } catch (Exception e) { + fail(e.getMessage()); + } + } + + // Fun utilities + private String createTempContainerName(String addition) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSSS"); + return "test-container-" + addition + "-" + sdf.format(new Date(System.currentTimeMillis())); + } + + private String makeFileName(String addition) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSSS"); + return "test-file-" + addition + "-" + sdf.format(new Date(System.currentTimeMillis())); + } + + private byte[] makeRandomFile(String name) throws IOException { + + File file = new File(name); + FileOutputStream fos = new FileOutputStream(file); + byte randomData[] = makeRandomBytes(); + fos.write(randomData); + fos.close(); + + return randomData; + } + + private byte[] makeRandomBytes() { + return makeRandomBytes(NUMBER_RANDOM_BYTES); + } + private byte[] makeRandomBytes(int nBytes) { + byte results[] = new byte[nBytes]; + Random gen = new Random(); + gen.nextBytes(results); + + // Uncomment to get some not so random data + // for(int i=0; i < results.length; ++i) results[i] = (byte) (i % Byte.MAX_VALUE); + + return results; + } + + private void assertArrayEquals(byte a[], byte b[]) { + assertEquals(a.length, b.length); + for(int i=0; i < a.length; ++i) assertEquals(a[i], b[i]); + } + + private class TesterCallback implements IFilesTransferCallback { + public long bytesSent = 0; + public int nCalls = 0; + public void progress(long n) { + bytesSent = n; + ++nCalls; + } + } +} \ No newline at end of file diff --git a/src/test/java/com/mosso/client/cloudfiles/LongRunningTest.java b/src/test/java/com/rackspacecloud/client/cloudfiles/LongRunningTest.java similarity index 84% rename from src/test/java/com/mosso/client/cloudfiles/LongRunningTest.java rename to src/test/java/com/rackspacecloud/client/cloudfiles/LongRunningTest.java index 20ec59c..845c70a 100644 --- a/src/test/java/com/mosso/client/cloudfiles/LongRunningTest.java +++ b/src/test/java/com/rackspacecloud/client/cloudfiles/LongRunningTest.java @@ -1,7 +1,9 @@ /** * */ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; + +import com.rackspacecloud.client.cloudfiles.FilesClient; /** * @author lvaughn diff --git a/src/test/java/com/mosso/client/cloudfiles/FilesClientTestCase.java b/src/test/java/com/rackspacecloud/client/cloudfiles/SnetFilesClientTestCase.java similarity index 85% rename from src/test/java/com/mosso/client/cloudfiles/FilesClientTestCase.java rename to src/test/java/com/rackspacecloud/client/cloudfiles/SnetFilesClientTestCase.java index 7ef6184..09a5cb4 100644 --- a/src/test/java/com/mosso/client/cloudfiles/FilesClientTestCase.java +++ b/src/test/java/com/rackspacecloud/client/cloudfiles/SnetFilesClientTestCase.java @@ -1,4 +1,4 @@ -package com.mosso.client.cloudfiles; +package com.rackspacecloud.client.cloudfiles; import java.io.ByteArrayInputStream; import java.io.File; @@ -15,22 +15,28 @@ import java.util.Map; import java.util.Random; -import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.SystemUtils; import org.apache.log4j.Logger; -import com.mosso.client.cloudfiles.FilesAccountInfo; -import com.mosso.client.cloudfiles.FilesClient; -import com.mosso.client.cloudfiles.FilesConstants; -import com.mosso.client.cloudfiles.FilesObject; -import com.mosso.client.cloudfiles.FilesObjectMetaData; -import com.mosso.client.cloudfiles.FilesUtil; +import com.rackspacecloud.client.cloudfiles.FilesAccountInfo; +import com.rackspacecloud.client.cloudfiles.FilesCDNContainer; +import com.rackspacecloud.client.cloudfiles.FilesClient; +import com.rackspacecloud.client.cloudfiles.FilesConstants; +import com.rackspacecloud.client.cloudfiles.FilesContainer; +import com.rackspacecloud.client.cloudfiles.FilesContainerExistsException; +import com.rackspacecloud.client.cloudfiles.FilesContainerInfo; +import com.rackspacecloud.client.cloudfiles.FilesInvalidNameException; +import com.rackspacecloud.client.cloudfiles.FilesNotFoundException; +import com.rackspacecloud.client.cloudfiles.FilesObject; +import com.rackspacecloud.client.cloudfiles.FilesObjectMetaData; +import com.rackspacecloud.client.cloudfiles.FilesUtil; +import com.rackspacecloud.client.cloudfiles.IFilesTransferCallback; import junit.framework.TestCase; -public class FilesClientTestCase extends TestCase { +public class SnetFilesClientTestCase extends TestCase { private static Logger logger = Logger.getLogger(FilesClientTestCase.class); private static File SYSTEM_TMP = SystemUtils.getJavaIoTmpDir(); private static int NUMBER_RANDOM_BYTES = 513; @@ -58,6 +64,8 @@ public void testLogin() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); } catch (Exception e) { fail(e.getMessage()); @@ -68,6 +76,7 @@ public void testLogin() { FilesUtil.getProperty("password") + " this is a bogus password", FilesUtil.getProperty("account")); try { + assertFalse(client.login()); } catch (Exception e) { fail(e.getMessage()); @@ -79,6 +88,8 @@ public void testAccountInfo() { String filename = makeFileName("accountinfo"); FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Make sure it's not there @@ -110,10 +121,55 @@ public void testAccountInfo() { fail(e.getMessage()); } } + + public void testMultipleFilesNotThere() { + // Tests to make sure we're releasing connections with 404's + FilesClient client = new FilesClient(); + String filename = makeFileName("random"); + String fullPath = FilenameUtils.concat(SYSTEM_TMP.getAbsolutePath(), filename); + try { + byte[] content = makeRandomFile(fullPath); + client.useSnet(); + assertTrue(client.usingSnet()); + assertTrue(client.login()); + String containerName = createTempContainerName("file-not-there"); + client.createContainer(containerName); + + String[] names = new String[10]; + for(int i=0; i < 10; ++i) names[i] = "File" + (i + 1) + ".txt"; + for(int i=0; i < 5; ++i) + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", names[i])); + + for (int i = 0; i < 10; i++) { + String fileName = names[i]; + + byte[] retrievedContent = null; + try { + retrievedContent = client.getObject(containerName, fileName); + assertArrayEquals(content, retrievedContent); + } catch(FilesNotFoundException ex) { + assertTrue(i >= 5); + } + } + // Cleanup + for(int i=0; i < 5; ++i) + client.deleteObject(containerName, names[i]); + client.deleteContainer(containerName); + + } catch (Exception e) { + fail(e.getMessage()); + } + finally { + File f = new File(fullPath); + f.delete(); + } + } public void testContainerCreation() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); String containerName = createTempContainerName(""); @@ -150,10 +206,53 @@ public void testContainerCreation() { fail(e.getMessage()); } } - + public void testSnetToggle() { + FilesClient client = new FilesClient(); + try { + assertTrue(client.login()); + client.useSnet(); + assertTrue(client.usingSnet()); + String containerName = createTempContainerName(""); + + // Make sure it's not there + assertFalse(client.containerExists(containerName)); + + // Add it + client.createContainer(containerName); + client.usePublic(); + assertFalse(client.usingSnet()); + // See that it's there + assertTrue(client.containerExists(containerName)); + assertNotNull(client.getContainerInfo(containerName)); + + // Try Adding it again + try { + client.createContainer(containerName); + fail("Allowed duplicate container creation"); + } + catch (FilesContainerExistsException fcee) { + // Hooray! + } + + // See that it's still there + assertTrue(client.containerExists(containerName)); + + // Delete it + assertTrue(client.deleteContainer(containerName)); + + // Make sure it's gone + assertFalse(client.containerExists(containerName)); + + + } catch (Exception e) { + fail(e.getMessage()); + } + } public void testContainerNotThereDeletion() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); String containerName = createTempContainerName("I'mNotHere!"); @@ -182,6 +281,8 @@ public void testContainerNotThereDeletion() { public void testContainerCreationWithSpaces() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); String containerName = createTempContainerName("with space+and+plus"); @@ -231,8 +332,10 @@ public void testContainerCreationWithSpaces() { public void testContainerInfoListing() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); - String containerName = createTempContainerName(""); + String containerName = createTempContainerName(""); // Make sure it's not there assertFalse(client.containerExists(containerName)); @@ -287,6 +390,8 @@ public void testUserAgent() { client.setUserAgent("Java-Test-User-Agent"); assertEquals("Java-Test-User-Agent", client.getUserAgent()); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); String containerName = createTempContainerName("user-agent"); @@ -315,6 +420,8 @@ public void testUserAgent() { public void testContainerNameNoSlashes() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); String containerName = createTempContainerName("/"); @@ -344,6 +451,8 @@ public void testFileSaving() { try { byte randomData[] = makeRandomFile(fullPath); FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -351,7 +460,7 @@ public void testFileSaving() { // Store it logger.info("About to save: " + filename); - assertTrue(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); // Make sure it's there List objects = client.listObjects(containerName); @@ -376,6 +485,7 @@ public void testFileSaving() { } catch (Exception e) { + e.printStackTrace(); fail(e.getMessage()); } finally { @@ -393,6 +503,8 @@ public void testSaveAs() { try { byte randomData[] = makeRandomFile(fullPath); FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -400,7 +512,7 @@ public void testSaveAs() { // Store it logger.info("About to save: " + filename); - assertTrue(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", otherFileName)); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", otherFileName)); // Make sure it's there List objects = client.listObjects(containerName); @@ -441,6 +553,8 @@ public void testFileSavingWithCallback() { try { byte randomData[] = makeRandomFile(fullPath); FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -449,7 +563,7 @@ public void testFileSavingWithCallback() { // Store it logger.info("About to save: " + filename); TesterCallback callback = new TesterCallback(); - assertTrue(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename, callback)); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename, callback)); // Make sure the callback was called assertEquals(randomData.length, callback.bytesSent); @@ -496,6 +610,8 @@ public void testFileSavingWithMetadata() { try { byte randomData[] = makeRandomFile(fullPath); FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -507,7 +623,7 @@ public void testFileSavingWithMetadata() { meta.put("Uni", "\u0169\u00f1\u00efcode-test"); meta.put("Width", "336"); meta.put("Height", "183"); - assertTrue(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename, meta)); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename, meta)); // Make sure it's there List objects = client.listObjects(containerName); @@ -528,6 +644,7 @@ public void testFileSavingWithMetadata() { // Make sure the metadata is correct FilesObjectMetaData metadata = client.getObjectMetaData(containerName, filename); + assertNotNull(metadata); Map serverMetadata = metadata.getMetaData(); assertEquals(meta.size(), serverMetadata.size()); for(String key : meta.keySet()) { @@ -540,7 +657,12 @@ public void testFileSavingWithMetadata() { assertTrue(client.deleteContainer(containerName)); } + catch (FilesException e) { + e.printStackTrace(); + fail(e.getHttpStatusMessage() + ":" + e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); fail(e.getMessage()); } finally { @@ -561,14 +683,15 @@ public void testFileSavingNoETag() { assertTrue(client.getUseETag()); client.setUseETag(false); assertFalse(client.getUseETag()); - + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up client.createContainer(containerName); // Store it - assertTrue(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); // Make sure it's there List objects = client.listObjects(containerName); @@ -610,6 +733,8 @@ public void testContainerListing() { try { byte randomData[] = makeRandomFile(fullPath); FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -617,7 +742,7 @@ public void testContainerListing() { // Store it logger.info("About to save: " + filename); - assertTrue(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); // Make sure it's there List objects = client.listObjects(containerName); @@ -659,6 +784,8 @@ public void testContainerListingWithXML() { try { byte randomData[] = makeRandomBytes(); FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -705,6 +832,8 @@ public void testByteArraySaving() { byte randomData[] = makeRandomBytes(); FilesClient client = new FilesClient(); // client.setUseETag(false); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -748,6 +877,8 @@ public void testLineNoiseSaving() { byte randomData[] = makeRandomBytes(); FilesClient client = new FilesClient(); // client.setUseETag(false); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -790,14 +921,15 @@ public void testRequestEntitySaving() { try { byte randomData[] = makeRandomBytes(); FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up client.createContainer(containerName); // Store it - ByteArrayRequestEntity entity = new ByteArrayRequestEntity(randomData, "test/content_type"); - assertTrue(client.storeObjectAs(containerName, filename, entity, new HashMap(), FilesClient.md5Sum(randomData))); + assertTrue(client.storeObject(containerName, randomData, "test/content_type", filename, new HashMap())); // Make sure it's there List objects = client.listObjects(containerName); @@ -833,6 +965,8 @@ public void testObjectListing() { byte randomData[] = makeRandomBytes(); FilesClient client = new FilesClient(); // client.setUseETag(false); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -886,6 +1020,8 @@ public void testObjectListing() { public void testContainerListingWithLimitMarker() { try { FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Populate our account @@ -931,6 +1067,8 @@ public void testByteArraySavingWithCallback() { byte randomData[] = makeRandomBytes(1024 * 100); // 100 K to make sure we do more with the callback FilesClient client = new FilesClient(); // client.setUseETag(false); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -982,13 +1120,15 @@ public void testStreamedSaving() { try { byte randomData[] = makeRandomBytes(1024 * 100); // 100 K to make sure it's interesting FilesClient client = new FilesClient(); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up client.createContainer(containerName); // Store it - assertTrue(client.storeStreamedObject(containerName, new ByteArrayInputStream(randomData), "application/octet-stream", filename, new HashMap())); + assertNotNull(client.storeStreamedObject(containerName, new ByteArrayInputStream(randomData), "application/octet-stream", filename, new HashMap())); // Make sure it's there List objects = client.listObjects(containerName); @@ -1033,6 +1173,8 @@ public void testMD5IssueSaving() { } FilesClient client = new FilesClient(); // client.setUseETag(false); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -1099,6 +1241,8 @@ public void testUnicodeContainer() { String containerName = createTempContainerName("\u0169\u00f1\u00efcode-test-\u03de"); try { FilesClient client = new FilesClient(FilesUtil.getProperty("username"), FilesUtil.getProperty("password"), FilesUtil.getProperty("account")); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up @@ -1130,13 +1274,15 @@ public void testUnicode() { try { byte randomData[] = makeRandomFile(fullPath); FilesClient client = new FilesClient(FilesUtil.getProperty("username"), FilesUtil.getProperty("password"), FilesUtil.getProperty("account")); + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); // Set up client.createContainer(containerName); // Store it - assertTrue(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); + assertNotNull(client.storeObjectAs(containerName, new File(fullPath), "application/octet-stream", filename)); // Make sure it's there List objects = client.listObjects(containerName); @@ -1179,6 +1325,8 @@ public void testUnicode() { public void testCDNContainerList() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); List containers = client.listCdnContainers(); @@ -1191,8 +1339,10 @@ public void testCDNContainerList() { public void testCDNContainerListLimitMarker() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); - + List originalContainers = client.listCdnContainers(); assertTrue(originalContainers.size() > 0); @@ -1216,6 +1366,8 @@ public void testCDNContainerListLimitMarker() { public void testCDNContainerFullListing() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); List originalContainers = client.listCdnContainers(); @@ -1239,19 +1391,41 @@ public void testCDNContainerFullListing() { } } + + public void testCDNContainerFullListingAll() { + FilesClient client = new FilesClient(); + try { + client.useSnet(); + assertTrue(client.usingSnet()); + assertTrue(client.login()); + String container = createTempContainerName("aaa_\u1422_aaa"); + client.cdnEnableContainer(container); + // Now do a limit + client.listCdnContainerInfo(); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + public void testCDNApi() { String containerName = createTempContainerName("java api Test\u03DA_\u2042\u03de#<>\u2043\u2042\u2044\u2045"); //containerName = createTempContainerName("java Api Test no uniocde"); //logger.warn("Container:" + containerName.length() + ":" + containerName); FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); List containers = client.listCdnContainers(); int originalContainerListSize = containers.size(); + + assertFalse(client.isCDNEnabled(containerName)); String url = client.cdnEnableContainer(containerName); assertNotNull(url); + assertTrue(client.isCDNEnabled(containerName)); containers = client.listCdnContainers(); assertEquals(originalContainerListSize + 1, containers.size()); @@ -1269,16 +1443,20 @@ public void testCDNApi() { String cdnUrl = info.getCdnURL(); assertNotNull(cdnUrl); - client.cdnUpdateContainer(containerName, 31415, false); + client.cdnUpdateContainer(containerName, 31415, false, true); + assertFalse(client.isCDNEnabled(containerName)); info = client.getCDNContainerInfo(containerName); assertFalse(info.isEnabled()); + assertTrue(info.getRetainLogs()); assertEquals(31415, info.getTtl()); assertEquals(cdnUrl, info.getCdnURL()); //client.cdnUpdateContainer(containerName, 54321, true, "Referrer Test", "User Agent Acl Test"); - client.cdnUpdateContainer(containerName, 54321, true); + client.cdnUpdateContainer(containerName, 54321, true, false); + assertTrue(client.isCDNEnabled(containerName)); info = client.getCDNContainerInfo(containerName); assertTrue(info.isEnabled()); + assertFalse(info.getRetainLogs()); assertEquals(54321, info.getTtl()); assertEquals(cdnUrl, info.getCdnURL()); // assertEquals("Referrer Test", info.getReferrerACL()); @@ -1292,17 +1470,19 @@ public void testCDNApi() { // Test container name limits public void testContainerNameLimits() { - FilesClient fc = new FilesClient(); + FilesClient client = new FilesClient(); try { - assertTrue(fc.login()); + client.useSnet(); + assertTrue(client.usingSnet()); + assertTrue(client.login()); StringBuilder nameBuilder = new StringBuilder(createTempContainerName("long")); while(nameBuilder.length() <= FilesConstants.CONTAINER_NAME_LENGTH) { nameBuilder.append("a"); } try { - fc.createContainer(nameBuilder.toString()); + client.createContainer(nameBuilder.toString()); // Note, we shouldn't get here, but want to clean up if we do - fc.deleteContainer(nameBuilder.toString()); + client.deleteContainer(nameBuilder.toString()); fail("No exception thrown"); } catch (FilesInvalidNameException fine) { @@ -1317,6 +1497,8 @@ public void testContainerNameLimits() { public void testPathCreationAndListing() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); String containerName = createTempContainerName("pathTest"); @@ -1360,6 +1542,8 @@ public void testPathCreationAndListing() { public void testPathCreation() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); String containerName = createTempContainerName("pathTest"); @@ -1402,6 +1586,8 @@ public void testPathCreation() { public void testFilesObjectPath() { FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); String containerName = createTempContainerName("FOpathTest"); @@ -1445,6 +1631,8 @@ public void testURLs() { // Test to make sure these are getting set and are visible to the outside world (needed for Cyberduck's SSL). FilesClient client = new FilesClient(); try { + client.useSnet(); + assertTrue(client.usingSnet()); assertTrue(client.login()); assertNotNull(client.getCdnManagementURL()); assertNotNull(client.getStorageURL()); diff --git a/src/test/resources/cloudfiles.properties b/src/test/resources/cloudfiles.properties index 07234ca..3b689af 100644 --- a/src/test/resources/cloudfiles.properties +++ b/src/test/resources/cloudfiles.properties @@ -1,9 +1,14 @@ # user properties -username=your-username-here -password=your-password-here -auth_url=https://api.mosso.com/auth +username=username-here +password=api-key-here + +# Auth Info, including two headers that can change for different auth services +auth_url=https://auth.api.rackspacecloud.com/v1.0 +#auth_user_header=X-Storage-User +#auth_pass_header=X-Storage-Pass # cloudfs properties version=v1 connection_timeout=15000 +