Java tutorial
/* * See COPYING for license information. */ package com.rackspacecloud.client.cloudfiles; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; 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.net.SocketException; import java.net.UnknownHostException; 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.io.IOUtils; 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.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.rackspacecloud.client.cloudfiles.expections.*; 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.rackspacecloud.client.cloudfiles.sample, which contains a series of * examples. * * <pre> * * // Create the client object for username "jdoe", password "johnsdogsname". * FilesClient myClient = FilesClient("jdoe", "johnsdogsname"); * * // Log in ( * <code>login()</code> will return false if the login was unsuccessful. * assert(myClient.login()); * * // Make sure there are no containers in the account * assert(myClient.listContainers.length() == 0); * * // Create the container assert(myClient.createContainer("myContainer")); * * // Now we should have one assert(myClient.listContainers.length() == 1); * * // Upload the file "alpaca.jpg" assert(myClient.storeObject("myContainer", * new File("alapca.jpg"), "image/jpeg")); * * // Download "alpaca.jpg" FilesObject obj = myClient.getObject("myContainer", * "alpaca.jpg"); byte data[] = obj.getObject(); * * // Clean up after ourselves. // Note: Order here is important, you can't * delete non-empty containers. assert(myClient.deleteObject("myContainer", * "alpaca.jpg")); assert(myClient.deleteContainer("myContainer"); * </pre> * * @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 */ public class FilesClient { public static final String VERSION = "v1"; private String username = null; private String password = null; private String account = null; private String authenticationURL; private int connectionTimeOut; private String storageURL = null; private String cdnManagementURL = null; private String authToken = null; private boolean isLoggedin = false; private boolean useETag = true; 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(HttpClient client, String username, String password, String authUrl, String account, int connectionTimeOut) { this.client = WebClientDevWrapper.wrapClient(client); this.username = username; this.password = password; this.account = account; 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 = authUrl; } this.connectionTimeOut = connectionTimeOut; setUserAgent(FilesConstants.USER_AGENT); if (logger.isDebugEnabled()) { logger.debug("UserName: " + this.username); logger.debug("AuthenticationURL: " + this.authenticationURL); logger.debug("ConnectionTimeOut: " + this.connectionTimeOut); } } /** * @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() { @Override protected HttpParams createHttpParams() { BasicHttpParams params = new BasicHttpParams(); org.apache.http.params.HttpConnectionParams.setSoTimeout(params, connectionTimeOut); params.setParameter("http.socket.timeout", connectionTimeOut); return params; } @SuppressWarnings("deprecation") @Override protected ClientConnectionManager createClientConnectionManager() { SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); return new ThreadSafeClientConnManager(createHttpParams(), schemeRegistry); } }, username, password, authUrl, account, connectionTimeOut); } /** * This method uses the default connection time out of CONNECTON_TIMEOUT. If * <code>account</code> is null, "Mosso Style" authentication is assumed, * otherwise standard Cloud Files authentication is used. * * @param username * @param password * @param authUrl */ public FilesClient(String username, String password, String authUrl) { this(username, password, authUrl, null, FilesUtil.getIntProperty("connection_timeout")); } /** * Mosso-style authentication (No accounts). https://10.30.230.191:8080 * * @param username Your CloudFiles username * @param apiAccessKey Your CloudFiles API Access Key */ public FilesClient(String username, String apiAccessKey) { this(username, apiAccessKey, null, null, FilesUtil.getIntProperty("connection_timeout")); // lConnectionManagerogger.warn("LGV"); // logger.debug("LGV:" + client.getHttpConnectionManager()); } /** * This method uses the default connection time out of CONNECTON_TIMEOUT and * username, password, and account from FilesUtil */ public FilesClient() { this(FilesUtil.getProperty("username"), FilesUtil.getProperty("password"), null, FilesUtil.getProperty("account"), FilesUtil.getIntProperty("connection_timeout")); } /** * Returns the Account associated with the URL * * @return The account name */ public String getAccount() { return account; } /** * Set the Account value and reassemble the Authentication URL. * * @param account */ public void setAccount(String account) { this.account = account; if (account != null && account.length() > 0) { this.authenticationURL = FilesUtil.getProperty("auth_url") + VERSION + "/" + account + FilesUtil.getProperty("auth_url_post"); } else { this.authenticationURL = FilesUtil.getProperty("auth_url"); } } /** * Log in to CloudFiles. This method performs the authentication and sets up * the client's internal state. * * @return true if the login was successful, false otherwise. * * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol */ public boolean login() throws IOException, HttpException { isLoggedin = false; HttpGet method = new HttpGet(authenticationURL); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); 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; 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.getConnectionManager()); } method.abort(); return this.isLoggedin; } public boolean loginKeystone() throws UnknownHostException, SocketException, IOException, UnauthorizeException { isLoggedin = false; String tenantNameKeystone = ""; String userNameKeystone = username; if (username.split(":").length >= 2) { tenantNameKeystone = username.split(":")[0]; userNameKeystone = username.split(":")[1]; } String content = "{\"auth\": {\"passwordCredentials\": {\"username\": \"" + userNameKeystone + "\", \"password\": \"" + password + "\"}, \"tenantName\":\"" + tenantNameKeystone + "\"}}"; HttpPost method = new HttpPost(authenticationURL); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader("Content-type", "application/json"); InputStream stream = new ByteArrayInputStream(content.getBytes("UTF-8")); InputStreamEntity entity = new InputStreamEntity(stream, content.getBytes("UTF-8").length); method.setEntity(entity); stream.close(); FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == 401) { throw new UnauthorizeException("Incorrect user/password.", response.getResponseHeaders(), response.getStatusLine()); } InputStream in = response.getResponseBodyAsStream(); String outString = IOUtils.toString(in, "UTF-8"); in.close(); JsonElement jelement = new JsonParser().parse(outString); JsonObject jobject = jelement.getAsJsonObject(); jobject = jobject.getAsJsonObject("access"); jobject = jobject.getAsJsonObject("token"); authToken = jobject.get("id").getAsString(); jobject = jelement.getAsJsonObject(); jobject = jobject.getAsJsonObject("access"); JsonArray jarray = jobject.getAsJsonArray("serviceCatalog"); for (JsonElement serviceCatalog : jarray) { JsonObject jsonLineItem = serviceCatalog.getAsJsonObject(); String value = jsonLineItem.get("type").getAsString(); if (value.compareTo("object-store") == 0) { JsonArray jarray2 = jsonLineItem.getAsJsonArray("endpoints"); JsonElement endpoint = jarray2.get(0); storageURL = endpoint.getAsJsonObject().get("publicURL").getAsString(); isLoggedin = true; cdnManagementURL = ""; break; } } logger.debug("storageURL: " + storageURL); logger.debug("authToken: " + authToken); logger.debug("cdnManagementURL:" + cdnManagementURL); logger.debug("ConnectionManager:" + client.getConnectionManager()); return isLoggedin; } public boolean loginKeystoneV3() throws UnknownHostException, SocketException, IOException, UnauthorizeException { isLoggedin = false; String tenantNameKeystone = ""; String userNameKeystone = username; if (username.split(":").length >= 2) { tenantNameKeystone = username.split(":")[0]; userNameKeystone = username.split(":")[1]; } String content = "{\"auth\": {\"identity\": {\"methods\": [\"password\"],\"password\": {\"user\":{\"domain\": {\"name\": \"d_Stacksync\"},\"name\": \"" + userNameKeystone + "\",\"password\": \"" + password + "\"}}},\"scope\": {\"project\": {\"domain\": {\"name\": \"d_Stacksync\"},\"name\": \"" + tenantNameKeystone + "\"}}}}"; //String content = "{\"auth\": {\"passwordCredentials\": {\"username\": \"" + userNameKeystone + "\", \"password\": \"" + password + "\"}, \"tenantName\":\"" + tenantNameKeystone + "\"}}"; HttpPost method = new HttpPost(authenticationURL); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader("Content-type", "application/json"); InputStream stream = new ByteArrayInputStream(content.getBytes("UTF-8")); InputStreamEntity entity = new InputStreamEntity(stream, content.getBytes("UTF-8").length); method.setEntity(entity); stream.close(); FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == 401) { throw new UnauthorizeException("Incorrect user/password.", response.getResponseHeaders(), response.getStatusLine()); } InputStream in = response.getResponseBodyAsStream(); String outString = IOUtils.toString(in, "UTF-8"); in.close(); Header header = response.getResponseHeaders("X-Subject-Token")[0]; authToken = header.getValue(); JsonElement jelement = new JsonParser().parse(outString); JsonObject jobject = jelement.getAsJsonObject(); //jobject = jelement.getAsJsonObject(); jobject = jobject.getAsJsonObject("token"); JsonArray jarray = jobject.getAsJsonArray("catalog"); for (JsonElement serviceCatalog : jarray) { JsonObject jsonLineItem = serviceCatalog.getAsJsonObject(); String value = jsonLineItem.get("type").getAsString(); if (value.compareTo("object-store") == 0) { JsonArray jarray2 = jsonLineItem.getAsJsonArray("endpoints"); for (JsonElement endpoint : jarray2) { JsonObject endpointObject = endpoint.getAsJsonObject(); String publicURL = endpointObject.get("interface").getAsString(); if (publicURL.compareTo("public") == 0) { storageURL = endpointObject.get("url").getAsString(); isLoggedin = true; cdnManagementURL = ""; break; } } } } logger.debug("storageURL: " + storageURL); logger.debug("authToken: " + authToken); logger.debug("cdnManagementURL:" + cdnManagementURL); logger.debug("ConnectionManager:" + client.getConnectionManager()); return 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. * * @return null if the user is not logged in or the Account is not found. A * List of FSContainers with all of the containers in the account. if there * are no containers in the account, the list will be zero length. * @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<FilesContainerInfo> listContainersInfo() throws IOException, HttpException, FilesAuthorizationException, FilesException { return listContainersInfo(-1, null); } /** * List the containers available in an account, ordered by container name. * * @param limit The maximum number of containers to return. -1 returns an * unlimited number. * * @return null if the user is not logged in or the Account is not found. A * List of FSContainers with all of the containers in the account. if there * are no containers in the account, the list will be zero length. * @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<FilesContainerInfo> listContainersInfo(int limit) throws IOException, HttpException, FilesAuthorizationException, FilesException { return listContainersInfo(limit, null); } /** * List the containers available in an account, ordered by container name. * * @param limit The maximum number of containers to return. -1 returns an * unlimited number. * @param marker Return containers that occur after this lexicographically. * * @return null if the user is not logged in or the Account is not found. A * List of FSContainers with all of the containers in the account. if there * are no containers in the account, the list will be zero length. * @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<FilesContainerInfo> listContainersInfo(int limit, String marker) throws IOException, HttpException, FilesAuthorizationException, FilesException { if (!this.isLoggedin()) { throw new FilesAuthorizationException("You must be logged in", null, null); } HttpGet method = null; try { LinkedList<NameValuePair> parameters = new LinkedList<NameValuePair>(); if (limit > 0) { parameters.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if (marker != null) { parameters.add(new BasicNameValuePair("marker", marker)); } 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.removeHeaders(FilesConstants.X_AUTH_TOKEN); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_OK) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(response.getResponseBodyAsStream()); NodeList nodes = document.getChildNodes(); Node accountNode = nodes.item(0); if (!"account".equals(accountNode.getNodeName())) { logger.error("Got unexpected type of XML"); return null; } ArrayList<FilesContainerInfo> containerList = new ArrayList<FilesContainerInfo>(); NodeList containerNodes = accountNode.getChildNodes(); for (int i = 0; i < containerNodes.getLength(); ++i) { Node containerNode = containerNodes.item(i); if (!"container".equals(containerNode.getNodeName())) { continue; } String name = null; int count = -1; long size = -1; NodeList objectData = containerNode.getChildNodes(); for (int j = 0; j < objectData.getLength(); ++j) { Node data = objectData.item(j); if ("name".equals(data.getNodeName())) { name = data.getTextContent(); } else if ("bytes".equals(data.getNodeName())) { size = Long.parseLong(data.getTextContent()); } else if ("count".equals(data.getNodeName())) { count = Integer.parseInt(data.getTextContent()); } else { logger.debug("Unexpected container-info tag:" + data.getNodeName()); } } if (name != null) { FilesContainerInfo obj = new FilesContainerInfo(name, count, size); containerList.add(obj); } } return containerList; } else if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) { return new ArrayList<FilesContainerInfo>(); } else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { throw new FilesNotFoundException("Account not Found", response.getResponseHeaders(), response.getStatusLine()); } else { throw new FilesException("Unexpected Return Code", response.getResponseHeaders(), response.getStatusLine()); } } catch (Exception ex) { throw new FilesException("Unexpected problem, probably in parsing Server XML", ex); } finally { if (method != null) { method.abort(); } } } /** * List the containers available in an account. * * @return null if the user is not logged in or the Account is not found. A * List of FilesContainer with all of the containers in the account. if * there are no containers in the account, the list will be zero length. * @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<FilesContainer> listContainers() throws IOException, HttpException, FilesAuthorizationException, FilesException { return listContainers(-1, null); } /** * List the containers available in an account. * * @param limit The maximum number of containers to return. -1 denotes no * limit. * * @return null if the user is not logged in or the Account is not found. A * List of FilesContainer with all of the containers in the account. if * there are no containers in the account, the list will be zero length. * @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<FilesContainer> listContainers(int limit) throws IOException, HttpException, FilesAuthorizationException, FilesException { return listContainers(limit, null); } /** * List the containers available in an account. * * @param limit The maximum number of containers to return. -1 denotes no * limit. * @param marker Only return containers after this container. Null denotes * starting at the beginning (lexicographically). * * @return A List of FilesContainer with all of the containers in the * account. if there are no containers in the account, the list will be zero * length. * @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<FilesContainer> listContainers(int limit, String marker) throws IOException, HttpException, FilesException { if (!this.isLoggedin()) { throw new FilesAuthorizationException("You must be logged in", null, null); } HttpGet method = null; try { LinkedList<NameValuePair> parameters = new LinkedList<NameValuePair>(); if (limit > 0) { parameters.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if (marker != null) { parameters.add(new BasicNameValuePair("marker", marker)); } 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.abort(); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_OK) { // logger.warn(method.getResponseCharSet()); StrTokenizer tokenize = new StrTokenizer(response.getResponseBodyAsString()); tokenize.setDelimiterString("\n"); String[] containers = tokenize.getTokenArray(); ArrayList<FilesContainer> containerList = new ArrayList<FilesContainer>(); for (String container : containers) { containerList.add(new FilesContainer(container, this)); } return containerList; } else if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) { return new ArrayList<FilesContainer>(); } else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { throw new FilesNotFoundException("Account was not found", response.getResponseHeaders(), response.getStatusLine()); } else { throw new FilesException("Unexpected resposne from server", response.getResponseHeaders(), response.getStatusLine()); } } catch (Exception ex) { ex.toString(); throw new FilesException("Unexpected error, probably parsing Server XML", ex); } finally { if (method != null) { method.abort(); } } } /** * 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 <code>limit</code> objects * @param marker Returns objects lexicographically greater than * <code>marker</code>. Used in conjunction with <code>limit</code> to * paginate the list. * * @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<FilesObject> 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 <code>limit</code> objects * @param marker Returns objects lexicographically greater than * <code>marker</code>. Used in conjunction with <code>limit</code> 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<FilesObject> 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 (!isValidContainerName(container)) { throw new FilesInvalidNameException(container); } HttpGet method = null; try { LinkedList<NameValuePair> parameters = new LinkedList<NameValuePair>(); parameters.add(new BasicNameValuePair("format", "xml")); if (startsWith != null) { parameters.add(new BasicNameValuePair(FilesConstants.LIST_CONTAINER_NAME_QUERY, startsWith)); } if (path != null) { parameters.add(new BasicNameValuePair("path", path)); } if (limit > 0) { parameters.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if (marker != null) { parameters.add(new BasicNameValuePair("marker", marker)); } if (delimiter != null) { parameters.add(new BasicNameValuePair("delimiter", delimiter.toString())); } 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.removeHeaders(FilesConstants.X_AUTH_TOKEN); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_OK) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(response.getResponseBodyAsStream()); NodeList nodes = document.getChildNodes(); Node containerList = nodes.item(0); if (!"container".equals(containerList.getNodeName())) { logger.error("Got unexpected type of XML"); return null; } ArrayList<FilesObject> objectList = new ArrayList<FilesObject>(); NodeList objectNodes = containerList.getChildNodes(); for (int i = 0; i < objectNodes.getLength(); ++i) { Node objectNode = objectNodes.item(i); 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())) { name = data.getTextContent(); } else if ("content_type".equals(data.getNodeName())) { mimeType = data.getTextContent(); } else if ("hash".equals(data.getNodeName())) { eTag = data.getTextContent(); } else if ("bytes".equals(data.getNodeName())) { size = Long.parseLong(data.getTextContent()); } else if ("last_modified".equals(data.getNodeName())) { lastModified = data.getTextContent(); } else { logger.warn("Unexpected tag:" + data.getNodeName()); } } if (name != null) { 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 (lastModified != null) { obj.setLastModified(lastModified); } objectList.add(obj); } } return objectList; } else if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) { logger.debug("Container " + container + " has no Objects"); return new ArrayList<FilesObject>(); } else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { throw new FilesNotFoundException("Container was not found", response.getResponseHeaders(), response.getStatusLine()); } else { throw new FilesException("Unexpected Server Result", response.getResponseHeaders(), response.getStatusLine()); } } catch (FilesNotFoundException fnfe) { throw fnfe; } catch (Exception ex) { String errorMessage = "Error parsing server resposne " + ex.getMessage(); logger.error(errorMessage); throw new FilesException(errorMessage, ex); } finally { 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<FilesObject> 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<FilesObject> 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 <code>limit</code> objects * * @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<FilesObject> 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 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. */ public List<FilesObject> listObjects(String container, String path) throws IOException, HttpException, FilesAuthorizationException, FilesException { return listObjectsStartingWith(container, null, path, -1, null, null); } /** * List the objects in a container in lexicographic order. * * @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<FilesObject> listObjects(String container, String path, Character delimiter) throws IOException, HttpException, FilesAuthorizationException, FilesException { return listObjectsStartingWith(container, null, path, -1, null, delimiter); } /** * List the objects in a container in lexicographic order. * * @param container The container name * @param path Only look for objects in this path * @param limit Return at most <code>limit</code> objects * @param marker Returns objects lexicographically greater than * <code>marker</code>. Used in conjunction with <code>limit</code> to * paginate the list. * * @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<FilesObject> listObjects(String container, String path, int limit) throws IOException, HttpException, FilesAuthorizationException, FilesException { return listObjectsStartingWith(container, null, path, limit, null); } /** * List the objects in a container in lexicographic order. * * @param container The container name * @param path Only look for objects in this path * @param limit Return at most <code>limit</code> objects * @param marker Returns objects lexicographically greater than * <code>marker</code>. Used in conjunction with <code>limit</code> to * paginate the list. * * @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<FilesObject> listObjects(String container, String path, int limit, String marker) throws IOException, HttpException, FilesAuthorizationException, FilesException { return listObjectsStartingWith(container, null, path, limit, marker); } /** * List the objects in a container in lexicographic order. * * @param container The container name * @param limit Return at most <code>limit</code> objects * @param marker Returns objects lexicographically greater than * <code>marker</code>. Used in conjunction with <code>limit</code> to * paginate the list. * * @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<FilesObject> listObjects(String container, int limit, String marker) throws IOException, HttpException, FilesAuthorizationException, FilesException { return listObjectsStartingWith(container, null, null, limit, marker); } /** * Convenience method to test for the existence of a container in Cloud * Files. * * @param container * @return true if the container exists. false otherwise. * @throws IOException * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol */ public boolean containerExists(String container) throws IOException, HttpException { try { this.getContainerInfo(container); return true; } catch (FilesException fnfe) { return false; } } /** * Gets information for the given account. * * @return The FilesAccountInfo with information about the number of * containers and number of bytes used by the given account. * @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 FilesAccountInfo getAccountInfo() throws IOException, HttpException, FilesAuthorizationException, FilesException { if (this.isLoggedin()) { HttpHead method = null; 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 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); } } /** * Get basic information on a container (number of items and the total * size). * * @param container The container to get information for * @return ContainerInfo object of the container is present or null if its * not present * @throws IOException There was a socket level exception while talking to * CloudFiles * @throws HttpException There was an protocol level exception while talking * to Cloudfiles * @throws FilesNotFoundException The container was not found * @throws FilesAuthorizationException The client was not logged in or the * log in expired. */ public FilesContainerInfo getContainerInfo(String container) throws IOException, HttpException, FilesException { if (this.isLoggedin()) { if (isValidContainerName(container)) { HttpHead method = null; try { 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.removeHeaders(FilesConstants.X_AUTH_TOKEN); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) { int objCount = response.getContainerObjectCount(); long objSize = response.getContainerBytesUsed(); return new FilesContainerInfo(container, objCount, objSize); } else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { throw new FilesNotFoundException("Container not found: " + container, response.getResponseHeaders(), response.getStatusLine()); } 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 container * * @param name The name of the container to be created * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesAuthorizationException The client was not property logged in * @throws FilesInvalidNameException The container name was invalid */ public void createContainer(String name) throws IOException, HttpException, FilesAuthorizationException, FilesException { if (this.isLoggedin()) { if (isValidContainerName(name)) { HttpPut method = new HttpPut(storageURL + "/" + sanitizeForURI(name)); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); try { FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { method.abort(); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_CREATED) { // Fressen } else if (response.getStatusCode() == HttpStatus.SC_ACCEPTED) { throw new FilesContainerExistsException(name, response.getResponseHeaders(), response.getStatusLine()); } else { throw new FilesException("Unexpected Response", response.getResponseHeaders(), response.getStatusLine()); } } finally { method.abort(); } } else { throw new FilesInvalidNameException(name); } } else { throw new FilesAuthorizationException("You must be logged in", null, null); } } /** * Deletes a container * * @param name The name 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 The user is not Logged in * @throws FilesInvalidNameException The container name is invalid * @throws FilesNotFoundException The container doesn't exist * @throws FilesContainerNotEmptyException The container was not empty */ public boolean deleteContainer(String name) throws IOException, HttpException, FilesAuthorizationException, FilesInvalidNameException, FilesNotFoundException, FilesContainerNotEmptyException { if (this.isLoggedin()) { if (isValidContainerName(name)) { HttpDelete method = new HttpDelete(storageURL + "/" + sanitizeForURI(name)); 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(); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT) { logger.debug("Container Deleted : " + name); return true; } else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { logger.debug("Container does not exist !"); throw new FilesNotFoundException("You can't delete an non-empty container", response.getResponseHeaders(), response.getStatusLine()); } else if (response.getStatusCode() == HttpStatus.SC_CONFLICT) { logger.debug("Container is not empty, can not delete a none empty container !"); throw new FilesContainerNotEmptyException("You can't delete an non-empty container", response.getResponseHeaders(), response.getStatusLine()); } } finally { method.abort(); } } else { throw new FilesInvalidNameException(name); } } else { throw new FilesAuthorizationException("You must be logged in", null, null); } return false; } /** * Enables access of files in this container via the Content Delivery * Network. * * @param name The name of the container to enable * @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 Server. */ public String cdnEnableContainer(String name) throws IOException, HttpException, FilesException { String returnValue = null; if (this.isLoggedin()) { if (isValidContainerName(name)) { HttpPut method = null; try { 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.abort(); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_CREATED || response.getStatusCode() == HttpStatus.SC_ACCEPTED) { returnValue = response.getCdnUrl(); } else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { logger.warn("Unauthorized access"); 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(); } } } else { throw new FilesInvalidNameException(name); } } else { throw new FilesAuthorizationException("You must be logged in", null, null); } 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 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 */ /* * @param referrerAcl Unused for now * * @param userAgentACL Unused for now */ 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 (isValidContainerName(name)) { HttpPost method = null; try { method = new HttpPost(cdnManagementURL + "/" + sanitizeForURI(name)); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); // TTL if (ttl > 0) { method.setHeader(FilesConstants.X_CDN_TTL, Integer.toString(ttl)); } // Enabled method.setHeader(FilesConstants.X_CDN_ENABLED, Boolean.toString(enabled)); // Log Retention method.setHeader(FilesConstants.X_CDN_RETAIN_LOGS, Boolean.toString(retainLogs)); // Referrer ACL if (referrerAcl != null) { method.setHeader(FilesConstants.X_CDN_REFERRER_ACL, referrerAcl); } // 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.abort(); if (login()) { new HttpPost(cdnManagementURL + "/" + sanitizeForURI(name)); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); // TTL if (ttl > 0) { method.setHeader(FilesConstants.X_CDN_TTL, Integer.toString(ttl)); } // Enabled 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()); } } if (response.getStatusCode() == HttpStatus.SC_ACCEPTED) { returnValue = response.getCdnUrl(); } else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { logger.warn("Unauthorized access"); 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(); } } } else { throw new FilesInvalidNameException(name); } } else { throw new FilesAuthorizationException("You must be logged in", null, null); } return returnValue; } /** * 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 FilesCDNContainer getCDNContainerInfo(String container) throws IOException, FilesNotFoundException, 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) { 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; } 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.abort(); } } } else { throw new FilesInvalidNameException(container); } } else { throw new FilesAuthorizationException("You must be logged in", null, null); } } /** * 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 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) * * @param container The name of the container. * @param path The name of the Path * @throws HttpException There was an error at the protocol layer while * talking to CloudFiles * @throws IOException There was an error at the socket layer while talking * to CloudFiles * @throws FilesException There was another error while taking to the * CloudFiles server */ public void createPath(String container, String path) throws HttpException, IOException, FilesException { if (!isValidContainerName(container)) { throw new FilesInvalidNameException(container); } if (!isValidObjectName(path)) { throw new FilesInvalidNameException(path); } storeObject(container, new byte[0], "application/directory", path, new HashMap<String, String>()); } /** * Create all of the path elements for the entire tree for a given path. * Thus, * <code>createFullPath("myContainer", "foo/bar/baz")</code> creates the * paths "foo", "foo/bar" and "foo/bar/baz". * * @param container The name of the container * @param path The full name of the path * @throws HttpException There was an error at the protocol layer while * talking to CloudFiles * @throws IOException There was an error at the socket layer while talking * to CloudFiles * @throws FilesException There was another error while taking to the * CloudFiles server */ public void createFullPath(String container, String path) throws HttpException, IOException, FilesException { String parts[] = path.split("/"); for (int i = 0; i < parts.length; ++i) { StringBuilder sb = new StringBuilder(); for (int j = 0; j <= i; ++j) { if (sb.length() != 0) { sb.append("/"); } sb.append(parts[j]); } createPath(container, sb.toString()); } } /** * Gets the names of all of the containers associated with this account. * * @param limit The maximum number of container names to return * @return A list of container names * * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public List<String> listCdnContainers(int limit) throws IOException, HttpException, FilesException { return listCdnContainers(limit, null); } /** * Gets the names of all of the containers associated with this account. * * @return A list of container names * * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public List<String> listCdnContainers() throws IOException, HttpException, FilesException { return listCdnContainers(-1, null); } /** * Gets the names of all of the containers associated with this account. * * @param limit The maximum number of container names to return * @param marker All of the results will come after <code>marker</code> * lexicographically. * @return A list of container names * * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public List<String> listCdnContainers(int limit, String marker) throws IOException, HttpException, FilesException { if (this.isLoggedin()) { HttpGet method = null; try { LinkedList<NameValuePair> params = new LinkedList<NameValuePair>(); if (limit > 0) { params.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if (marker != null) { params.add(new BasicNameValuePair("marker", marker)); } 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.abort(); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_OK) { StrTokenizer tokenize = new StrTokenizer(response.getResponseBodyAsString()); tokenize.setDelimiterString("\n"); String[] containers = tokenize.getTokenArray(); List<String> returnValue = new ArrayList<String>(); for (String containerName : containers) { returnValue.add(containerName); } return returnValue; } else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { logger.warn("Unauthorized access"); 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(); } } } 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. <code>null</code> 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) { // fressen } 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. <code>null</code> 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) { // fressen } 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. * * @return A list of containers * * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public List<FilesCDNContainer> listCdnContainerInfo() throws IOException, HttpException, FilesException { return listCdnContainerInfo(-1, null); } /** * Gets list of all of the containers associated with this account. * * @param limit The maximum number of container names to return * @return A list of containers * * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public List<FilesCDNContainer> listCdnContainerInfo(int limit) throws IOException, HttpException, FilesException { return listCdnContainerInfo(limit, null); } /** * Gets list of all of the containers associated with this account. * * @param limit The maximum number of container names to return * @param marker All of the names will come after <code>marker</code> * lexicographically. * @return A list of containers * * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public List<FilesCDNContainer> listCdnContainerInfo(int limit, String marker) throws IOException, HttpException, FilesException { if (this.isLoggedin()) { HttpGet method = null; try { LinkedList<NameValuePair> params = new LinkedList<NameValuePair>(); params.add(new BasicNameValuePair("format", "xml")); if (limit > 0) { params.add(new BasicNameValuePair("limit", String.valueOf(limit))); } if (marker != null) { params.add(new BasicNameValuePair("marker", marker)); } 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.abort(); if (login()) { 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()); } } if (response.getStatusCode() == HttpStatus.SC_OK) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(response.getResponseBodyAsStream()); NodeList nodes = document.getChildNodes(); Node accountNode = nodes.item(0); if (!"account".equals(accountNode.getNodeName())) { logger.error("Got unexpected type of XML"); return null; } ArrayList<FilesCDNContainer> containerList = new ArrayList<FilesCDNContainer>(); NodeList containerNodes = accountNode.getChildNodes(); for (int i = 0; i < containerNodes.getLength(); ++i) { Node containerNode = containerNodes.item(i); if (!"container".equals(containerNode.getNodeName())) { continue; } FilesCDNContainer container = new FilesCDNContainer(); NodeList objectData = containerNode.getChildNodes(); for (int j = 0; j < objectData.getLength(); ++j) { Node data = objectData.item(j); if ("name".equals(data.getNodeName())) { container.setName(data.getTextContent()); } 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()); } } if (container.getName() != null) { containerList.add(container); } } return containerList; } else if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { logger.warn("Unauthorized access"); throw new FilesAuthorizationException("User not Authorized!", response.getResponseHeaders(), response.getStatusLine()); } else { throw new FilesException("Unexpected server response", response.getResponseHeaders(), response.getStatusLine()); } } catch (SAXException ex) { // probably a problem parsing the XML throw new FilesException("Problem parsing XML", ex); } catch (ParserConfigurationException ex) { // probably a problem parsing the XML throw new FilesException("Problem parsing XML", ex); } finally { 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<String, String>(), 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<String, String> 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<String, String> 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 * * @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 * @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 String storeObjectAs(String container, File obj, String contentType, String name) throws OverQuotaException, FilesException, IOException, HttpException { return storeObjectAs(container, obj, contentType, name, new HashMap<String, String>(), null); } /** * Store a file on the server * * @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 * @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 String storeObjectAs(String container, File obj, String contentType, String name, IFilesTransferCallback callback) throws OverQuotaException, FilesException, IOException, HttpException { return storeObjectAs(container, obj, contentType, name, new HashMap<String, String>(), callback); } /** * Store a file 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 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 String storeObjectAs(String container, File obj, String contentType, String name, Map<String, String> metadata) throws OverQuotaException, FilesException, IOException, HttpException { return storeObjectAs(container, obj, contentType, name, metadata, null); } /** * Store a file 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 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 OverQuotaException * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public String storeObjectAs(String container, File obj, String contentType, String name, Map<String, String> metadata, IFilesTransferCallback callback) throws OverQuotaException, FilesException, IOException, HttpException { if (!this.isLoggedin()) { throw new FilesAuthorizationException("You must be logged in", null, null); } if (!isValidContainerName(container)) { throw new FilesInvalidNameException(name); } if (!isValidObjectName(name)) { throw new FilesInvalidNameException(container); } if (!obj.exists()) { throw new FileNotFoundException(name + " does not exist"); } if (obj.isDirectory()) { throw new IOException("The alleged file was a directory"); } HttpPut method = null; try { 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.setHeader(FilesConstants.E_TAG, md5Sum(obj)); } method.setEntity(new RequestEntityWrapper(new FileEntity(obj, contentType), callback)); for (String key : metadata.keySet()) { 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(name)); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); if (useETag) { method.setHeader(FilesConstants.E_TAG, md5Sum(obj)); } method.setEntity(new RequestEntityWrapper(new FileEntity(obj, contentType), 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()); } } int statusCode = response.getStatusCode(); switch (statusCode) { case HttpStatus.SC_CREATED: return response.getResponseHeader(FilesConstants.E_TAG).getValue(); case HttpStatus.SC_PRECONDITION_FAILED: throw new FilesException("Etag missmatch", response.getResponseHeaders(), response.getStatusLine()); case HttpStatus.SC_LENGTH_REQUIRED: throw new FilesException("Length miss-match", response.getResponseHeaders(), response.getStatusLine()); case HttpStatus.SC_REQUEST_TOO_LONG: throw new OverQuotaException("Quota excedeed", response.getResponseHeaders(), response.getStatusLine()); default: throw new FilesException("Unexpected Server Response", response.getResponseHeaders(), response.getStatusLine()); } } finally { if (method != null) { method.abort(); } } } /** * Store a file on the server * * @param sharedStorageURL * @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 * @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 String storeSharedObjectAs(String sharedStorageURL, String container, File obj, String contentType, String name) throws OverQuotaException, FilesException, IOException, HttpException { if (!this.isLoggedin()) { throw new FilesAuthorizationException("You must be logged in", null, null); } if (!isValidContainerName(container)) { throw new FilesInvalidNameException(name); } if (!isValidObjectName(name)) { throw new FilesInvalidNameException(container); } if (!obj.exists()) { throw new FileNotFoundException(name + " does not exist"); } if (obj.isDirectory()) { throw new IOException("The alleged file was a directory"); } HttpPut method = null; try { method = new HttpPut(sharedStorageURL + "/" + sanitizeForURI(container) + "/" + sanitizeForURI(name)); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); if (useETag) { method.setHeader(FilesConstants.E_TAG, md5Sum(obj)); } method.setEntity(new RequestEntityWrapper(new FileEntity(obj, contentType), null)); FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { method.abort(); if (login()) { method = new HttpPut( sharedStorageURL + "/" + sanitizeForURI(container) + "/" + sanitizeForURI(name)); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); if (useETag) { method.setHeader(FilesConstants.E_TAG, md5Sum(obj)); } method.setEntity(new RequestEntityWrapper(new FileEntity(obj, contentType), null)); response = new FilesResponse(client.execute(method)); } else { throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine()); } } int statusCode = response.getStatusCode(); switch (statusCode) { case HttpStatus.SC_CREATED: return response.getResponseHeader(FilesConstants.E_TAG).getValue(); case HttpStatus.SC_PRECONDITION_FAILED: throw new FilesException("Etag missmatch", response.getResponseHeaders(), response.getStatusLine()); case HttpStatus.SC_LENGTH_REQUIRED: throw new FilesException("Length miss-match", response.getResponseHeaders(), response.getStatusLine()); case HttpStatus.SC_REQUEST_TOO_LONG: throw new OverQuotaException("Quota excedeed", response.getResponseHeaders(), response.getStatusLine()); default: throw new FilesException("Unexpected Server Response", response.getResponseHeaders(), response.getStatusLine()); } } finally { if (method != null) { method.abort(); } } } /** * Copies the file to Cloud Files, keeping the original file name in Cloud * Files. * * @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 String storeObject(String container, File obj, String contentType) throws IOException, HttpException, FilesException { return storeObjectAs(container, obj, contentType, obj.getName()); } /** * Store a file 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 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 storeObject(String container, byte obj[], String contentType, String name, Map<String, String> metadata) throws IOException, HttpException, FilesException { return storeObject(container, obj, contentType, name, metadata, null); } /** * Store a file 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 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 storeObject(String container, byte obj[], String contentType, String name, Map<String, String> metadata, IFilesTransferCallback callback) throws IOException, HttpException, FilesException { 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); if (useETag) { method.setHeader(FilesConstants.E_TAG, md5Sum(obj)); } 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.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 (useETag) { method.setHeader(FilesConstants.E_TAG, md5Sum(obj)); } entity = new ByteArrayEntity(obj); 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, including metadata, with the contents coming * from an input stream. This allows you to not know the entire length of * your content when you start to write it. Nor do you have to hold it * entirely in memory at the same time. * * @param container The name of the container * @param data Any object that implements InputStream * @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 * @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 String storeStreamedObject(String container, InputStream data, String contentType, String name, Map<String, String> metadata) throws IOException, HttpException, FilesException { if (this.isLoggedin()) { String objName = name; if (isValidContainerName(container) && isValidObjectName(objName)) { 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.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } method.removeHeaders("Content-Length"); try { FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_CREATED) { return response.getResponseHeader(FilesConstants.E_TAG).getValue(); } else { logger.error(response.getStatusLine()); throw new FilesException("Unexpected result", response.getResponseHeaders(), response.getStatusLine()); } } finally { 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); } } /** * * * @param container The name of the container * @param name The name of the object * @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 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 String storeObjectAs(String container, String name, HttpEntity entity, Map<String, String> metadata, String md5sum) throws IOException, HttpException, FilesException { if (this.isLoggedin()) { String objName = name; if (isValidContainerName(container) && isValidObjectName(objName)) { 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.setHeader(FilesConstants.E_TAG, md5sum); } method.setHeader(entity.getContentType()); for (String key : metadata.keySet()) { method.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } try { FilesResponse response = new FilesResponse(client.execute(method)); if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { method.abort(); login(); 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.setHeader(FilesConstants.X_OBJECT_META + key, sanitizeForURI(metadata.get(key))); } response = new FilesResponse(client.execute(method)); } if (response.getStatusCode() == HttpStatus.SC_CREATED) { return response.getResponseHeader(FilesConstants.E_TAG).getValue(); } else { logger.debug(response.getStatusLine()); throw new FilesException("Unexpected result", response.getResponseHeaders(), response.getStatusLine()); } } finally { 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); } } /** * 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. * * @param container The container name * @param objName The object name * @return FilesConstants.OBJECT_DELETED * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public void deleteObject(String container, String objName) throws IOException, FilesNotFoundException, HttpException, FilesException { if (this.isLoggedin()) { if (isValidContainerName(container) && isValidObjectName(objName)) { HttpDelete method = null; try { 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) { logger.debug("Object Deleted : " + objName); } else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { throw new FilesNotFoundException("Object was not found " + objName, response.getResponseHeaders(), response.getStatusLine()); } else { throw new FilesException("Unexpected status from server", 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); } } /** * Delete the given object from it's container. * * @param container The container name * @param objName The object name * @return FilesConstants.OBJECT_DELETED * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesException */ public void deleteSharedObject(String sharedStorageURL, String container, String objName) throws IOException, FilesNotFoundException, HttpException, FilesException { if (this.isLoggedin()) { if (isValidContainerName(container) && isValidObjectName(objName)) { HttpDelete method = null; try { method = new HttpDelete( sharedStorageURL + "/" + 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( sharedStorageURL + "/" + 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) { logger.debug("Object Deleted : " + objName); } else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND) { throw new FilesNotFoundException("Object was not found " + objName, response.getResponseHeaders(), response.getStatusLine()); } else { throw new FilesException("Unexpected status from server", 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); } } /** * Get an object's metadata * * @param container The name of the container * @param objName The name of the object * @return The object's metadata * @throws IOException There was an IO error doing network communication * @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, FilesNotFoundException, HttpException, FilesAuthorizationException, FilesInvalidNameException { FilesObjectMetaData metaData; if (this.isLoggedin()) { if (isValidContainerName(container) && isValidObjectName(objName)) { 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 || 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); Header[] headers = response.getResponseHeaders(); HashMap<String, String> headerMap = new HashMap<String, String>(); for (Header h : headers) { 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); } 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()); } } finally { 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); } } /** * Get the content of the given object * * @param container The name of the container * @param objName The name of the object * @return The content of the object * @throws IOException There was an IO error doing network communication * @throws HttpException There was an error with the http protocol * @throws FilesAuthorizationException * @throws FilesInvalidNameException * @throws FilesNotFoundException */ public byte[] getObject(String container, String objName) throws IOException, HttpException, FilesAuthorizationException, FilesInvalidNameException, FilesNotFoundException { if (this.isLoggedin()) { if (isValidContainerName(container) && isValidObjectName(objName)) { HttpGet method = new HttpGet( storageURL + "/" + sanitizeForURI(container) + "/" + sanitizeForURI(objName)); method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut); method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken); try { FilesResponse response = new FilesResponse(client.execute(method)); 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()); } } finally { 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); } return null; } /** * Get's the given shared object's content as a stream * * @param container The name of the container * @param objName The name of the object * @return An input stream that will give the objects content when read * from. * @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 getSharedObjectAsStream(String sharedStorageURL, String container, String objName) 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( sharedStorageURL + "/" + 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 HttpGet( sharedStorageURL + "/" + 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 { 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; } /** * Get's the given object's content as a stream * * @param container The name of the container * @param objName The name of the object * @return An input stream that will give the objects content when read * from. * @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, 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); FilesResponse response = new FilesResponse(client.execute(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) { 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 { 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; } /** * Utility function to write an InputStream to a file * * @param is * @param f * @throws IOException */ static void writeInputStreamToFile(InputStream is, File f) throws IOException { BufferedOutputStream bf = new BufferedOutputStream(new FileOutputStream(f)); byte[] buffer = new byte[1024]; int read; while ((read = is.read(buffer)) > 0) { bf.write(buffer, 0, read); } is.close(); bf.flush(); bf.close(); } /** * Reads an input stream into a stream * * @param is The input stream * @return The contents of the stream stored in a string. * @throws IOException */ static String inputStreamToString(InputStream stream, String encoding) throws IOException { char buffer[] = new char[4096]; StringBuilder sb = new StringBuilder(); InputStreamReader isr = new InputStreamReader(stream, "utf-8"); // For // now, // assume // utf-8 // to // work // around // server // bug int nRead; while ((nRead = isr.read(buffer)) >= 0) { sb.append(buffer, 0, nRead); } isr.close(); return sb.toString(); } /** * Calculates the MD5 checksum of a file, returned as a hex encoded string * * @param f The file * @return The MD5 checksum, as a base 16 encoded string * @throws IOException */ public static String md5Sum(File f) throws IOException { MessageDigest digest; try { digest = MessageDigest.getInstance("MD5"); InputStream is = new FileInputStream(f); byte[] buffer = new byte[1024]; int read; while ((read = is.read(buffer)) > 0) { digest.update(buffer, 0, read); } is.close(); byte[] md5sum = digest.digest(); BigInteger bigInt = new BigInteger(1, md5sum); // Front load any zeros cut off by BigInteger String md5 = bigInt.toString(16); while (md5.length() != 32) { md5 = "0" + md5; } return md5; } catch (NoSuchAlgorithmException e) { logger.fatal("The JRE is misconfigured on this computer", e); return null; } } /** * Calculates the MD5 checksum of an array of data * * @param data The data to checksum * @return The checksum, represented as a base 16 encoded string. * @throws IOException */ public static String md5Sum(byte[] data) throws IOException { try { MessageDigest digest = MessageDigest.getInstance("MD5"); byte[] md5sum = digest.digest(data); BigInteger bigInt = new BigInteger(1, md5sum); // Front load any zeros cut off by BigInteger String md5 = bigInt.toString(16); while (md5.length() != 32) { md5 = "0" + md5; } return md5; } catch (NoSuchAlgorithmException nsae) { logger.fatal("Major problems with your Java configuration", nsae); return null; } } /** * Encode any unicode characters that will cause us problems. * * @param str * @return The string encoded for a URI */ public static String sanitizeForURI(String str) { URLCodec codec = new URLCodec(); try { return codec.encode(str).replaceAll("\\+", "%20"); } catch (EncoderException ee) { logger.warn("Error trying to encode string for URI", ee); return 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 { return codec.decode(str); } catch (DecoderException ee) { logger.warn("Error trying to encode string for URI", ee); return str; } } /** * @return The connection timeout used for communicating with the server (in * milliseconds) */ public int getConnectionTimeOut() { return connectionTimeOut; } /** * The timeout we will use for communicating with the server (in * milliseconds) * * @param connectionTimeOut The new timeout for this connection */ public void setConnectionTimeOut(int connectionTimeOut) { this.connectionTimeOut = connectionTimeOut; } /** * @return The storage URL on the other end of the ReST api */ public String getStorageURL() { return storageURL; } /** * @return Get's our storage token. */ @Deprecated public String getStorageToken() { return authToken; } /** * @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. */ public boolean isLoggedin() { return isLoggedin; } /** * The username we are logged in with. * * @return The username */ public String getUserName() { return username; } /** * Set's the username for this client. Note, setting this after login has no * real impact unless the * <code>login()</code> method is called again. * * @param userName the username */ public void setUserName(String userName) { this.username = userName; } /** * The password the client will use for the login. * * @return The password */ public String getPassword() { return password; } /** * Set's the password for this client. Note, setting this after login has no * real impact unless the * <code>login()</code> method is called again. * * @param password The new password */ public void setPassword(String password) { this.password = password; } /** * The URL we will use for Authentication * * @return The URL (represented as a string) */ public String getAuthenticationURL() { return authenticationURL; } /** * Changes the URL of the authentication service. Note, if one is logged in, * this doesn't have an effect unless one calls login again. * * @param authenticationURL The new authentication URL */ public void setAuthenticationURL(String authenticationURL) { this.authenticationURL = authenticationURL; } /** * @return the useETag */ public boolean getUseETag() { return useETag; } /** * @param useETag the useETag to set */ public void setUseETag(boolean useETag) { this.useETag = useETag; } public void setUserAgent(String userAgent) { client.getParams().setParameter(HTTP.USER_AGENT, userAgent); } public String getUserAgent() { return client.getParams().getParameter(HTTP.USER_AGENT).toString(); } private boolean isValidContainerName(String name) { if (name == null) { return false; } int length = name.length(); if (length == 0 || length > FilesConstants.CONTAINER_NAME_LENGTH) { return false; } if (name.indexOf('/') != -1) { return false; } // if (name.indexOf('?') != -1) return false; return true; } private boolean isValidObjectName(String name) { if (name == null) { return false; } int length = name.length(); if (length == 0 || length > FilesConstants.OBJECT_NAME_LENGTH) { return false; } // if (name.indexOf('?') != -1) return false; return true; } /** * @return the cdnManagementURL */ public String getCdnManagementURL() { return cdnManagementURL; } /** * @param config */ public boolean updateObjectManifest(String container, String object, String manifest) throws FilesAuthorizationException, HttpException, IOException, FilesInvalidNameException { return updateObjectMetadataAndManifest(container, object, new HashMap<String, String>(), manifest); } /** * @param config */ public boolean updateObjectMetadata(String container, String object, Map<String, String> metadata) throws FilesAuthorizationException, HttpException, IOException, FilesInvalidNameException { return updateObjectMetadataAndManifest(container, object, metadata, null); } /** * @param config */ public boolean updateObjectMetadataAndManifest(String container, String object, Map<String, String> 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())) { /// GGIPART /// //for (String key: metadata.keySet()) //method.setHeader(FilesConstants.X_OBJECT_META + key, // FilesClient.sanitizeForURI(metadata.get(key))); for (String key : metadata.keySet()) { method.setHeader(key, metadata.get(key)); } /// GGIENDPART /// } 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())) { /// GGIPART /// //for (String key: metadata.keySet()) //method.setHeader(FilesConstants.X_OBJECT_META + key, // FilesClient.sanitizeForURI(metadata.get(key))); for (String key : metadata.keySet()) { method.setHeader(key, metadata.get(key)); } /// GGIENDPART /// } client.execute(method); } } return true; } finally { if (method != null) { method.abort(); } } } private String makeURI(String base, List<NameValuePair> parameters) { return base + "?" + URLEncodedUtils.format(parameters, "UTF-8"); } /* * * private void setQueryParameters(HttpRequestBase method, * List<NameValuePair> 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; } } public HttpClient getClientHTTP() { return client; } }