S3Response invoke( @Nullable String bucket, @Nullable String object, @Nullable String temporaryEndpoint) throws S3Exception, CloudException, InternalException { if (wire.isDebugEnabled()) { wire.debug(""); wire.debug( "----------------------------------------------------------------------------------"); } try { StringBuilder url = new StringBuilder(); boolean leaveOpen = false; HttpRequestBase method; HttpClient client; int status; if (provider.getEC2Provider().isAWS()) { url.append("https://"); if (temporaryEndpoint == null) { boolean validDomainName = isValidDomainName(bucket); if (bucket != null && validDomainName) { url.append(bucket); url.append("."); } url.append("s3.amazonaws.com/"); if (bucket != null && !validDomainName) { url.append(bucket); url.append("/"); } } else { url.append(temporaryEndpoint); url.append("/"); } } else if (provider.getEC2Provider().isStorage() && "google".equalsIgnoreCase(provider.getProviderName())) { url.append("https://"); if (temporaryEndpoint == null) { if (bucket != null) { url.append(bucket); url.append("."); } url.append("commondatastorage.googleapis.com/"); } else { url.append(temporaryEndpoint); url.append("/"); } } else { int idx = 0; if (!provider.getContext().getEndpoint().startsWith("http")) { url.append("https://"); } else { idx = provider.getContext().getEndpoint().indexOf("https://"); if (idx == -1) { idx = "http://".length(); url.append("http://"); } else { idx = "https://".length(); url.append("https://"); } } String service = ""; if (provider.getEC2Provider().isEucalyptus()) { service = "Walrus/"; } if (temporaryEndpoint == null) { url.append(provider.getContext().getEndpoint().substring(idx)); if (!provider.getContext().getEndpoint().endsWith("/")) { url.append("/").append(service); } else { url.append(service); } } else { url.append(temporaryEndpoint); url.append("/"); url.append(service); } if (bucket != null) { url.append(bucket); url.append("/"); } } if (object != null) { url.append(object); } else if (parameters != null) { boolean first = true; if (object != null && object.indexOf('?') != -1) { first = false; } for (Map.Entry<String, String> entry : parameters.entrySet()) { String key = entry.getKey(); String val = entry.getValue(); if (first) { url.append("?"); first = false; } else { url.append("&"); } if (val != null) { url.append(AWSCloud.encode(key, false)); url.append("="); url.append(AWSCloud.encode(val, false)); } else { url.append(AWSCloud.encode(key, false)); } } } if (provider.getEC2Provider().isStorage() && provider.getProviderName().equalsIgnoreCase("Google")) { headers.put(AWSCloud.P_GOOG_DATE, getDate()); } else { headers.put(AWSCloud.P_AWS_DATE, getDate()); } method = action.getMethod(url.toString()); if (headers != null) { for (Map.Entry<String, String> entry : headers.entrySet()) { method.addHeader(entry.getKey(), entry.getValue()); } } if (contentType == null && body != null) { contentType = "application/xml"; method.addHeader("Content-Type", contentType); } try { String hash = null; String signature; signature = provider.signS3( new String(provider.getContext().getAccessPublic(), "utf-8"), provider.getContext().getAccessPrivate(), method.getMethod(), hash, contentType, headers, bucket, object); method.addHeader(AWSCloud.P_CFAUTH, signature); } catch (UnsupportedEncodingException e) { logger.error(e); e.printStackTrace(); throw new InternalException(e); } if (body != null) { try { ((HttpEntityEnclosingRequestBase) method) .setEntity(new StringEntity(body, "application/xml", "utf-8")); } catch (UnsupportedEncodingException e) { throw new InternalException(e); } } else if (uploadFile != null) { ((HttpEntityEnclosingRequestBase) method) .setEntity(new FileEntity(uploadFile, contentType)); } attempts++; client = getClient(url.toString(), body == null && uploadFile == null); if (wire.isDebugEnabled()) { wire.debug("[" + url.toString() + "]"); wire.debug(method.getRequestLine().toString()); for (Header header : method.getAllHeaders()) { wire.debug(header.getName() + ": " + header.getValue()); } wire.debug(""); if (body != null) { try { wire.debug(EntityUtils.toString(((HttpEntityEnclosingRequestBase) method).getEntity())); } catch (IOException ignore) { } wire.debug(""); } else if (uploadFile != null) { wire.debug("-- file upload --"); wire.debug(""); } } S3Response response = new S3Response(); HttpResponse httpResponse; try { httpResponse = client.execute(method); if (wire.isDebugEnabled()) { wire.debug(httpResponse.getStatusLine().toString()); for (Header header : httpResponse.getAllHeaders()) { wire.debug(header.getName() + ": " + header.getValue()); } wire.debug(""); } status = httpResponse.getStatusLine().getStatusCode(); } catch (IOException e) { logger.error(url + ": " + e.getMessage()); e.printStackTrace(); throw new InternalException(e); } response.headers = httpResponse.getAllHeaders(); HttpEntity entity = httpResponse.getEntity(); InputStream input = null; if (entity != null) { try { input = entity.getContent(); } catch (IOException e) { throw new CloudException(e); } } try { if (status == HttpServletResponse.SC_OK || status == HttpServletResponse.SC_CREATED || status == HttpServletResponse.SC_ACCEPTED) { Header clen = httpResponse.getFirstHeader("Content-Length"); long len = -1L; if (clen != null) { len = Long.parseLong(clen.getValue()); } if (len != 0L) { try { Header ct = httpResponse.getFirstHeader("Content-Type"); if (ct != null && (ct.getValue().startsWith("application/xml") || ct.getValue().startsWith("text/xml"))) { try { response.document = parseResponse(input); return response; } finally { input.close(); } } else if (ct != null && ct.getValue().startsWith("application/octet-stream") && len < 1) { return null; } else { response.contentLength = len; if (ct != null) { response.contentType = ct.getValue(); } response.input = input; response.method = method; leaveOpen = true; return response; } } catch (IOException e) { logger.error(e); e.printStackTrace(); throw new CloudException(e); } } else { return response; } } else if (status == HttpServletResponse.SC_NO_CONTENT) { return response; } else if (status == HttpServletResponse.SC_NOT_FOUND) { throw new S3Exception(status, null, null, "Object not found."); } else { if (status == HttpServletResponse.SC_SERVICE_UNAVAILABLE || status == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) { if (attempts >= 5) { String msg; if (status == HttpServletResponse.SC_SERVICE_UNAVAILABLE) { msg = "Cloud service is currently unavailable."; } else { msg = "The cloud service encountered a server error while processing your request."; } logger.error(msg); throw new CloudException(msg); } else { leaveOpen = true; if (input != null) { try { input.close(); } catch (IOException ignore) { } } try { Thread.sleep(5000L); } catch (InterruptedException ignore) { } return invoke(bucket, object); } } try { Document doc; try { logger.warn("Received error code: " + status); doc = parseResponse(input); } finally { input.close(); } if (doc != null) { String endpoint = null, code = null, message = null, requestId = null; NodeList blocks = doc.getElementsByTagName("Error"); if (blocks.getLength() > 0) { Node error = blocks.item(0); NodeList attrs; attrs = error.getChildNodes(); for (int i = 0; i < attrs.getLength(); i++) { Node attr = attrs.item(i); if (attr.getNodeName().equals("Code") && attr.hasChildNodes()) { code = attr.getFirstChild().getNodeValue().trim(); } else if (attr.getNodeName().equals("Message") && attr.hasChildNodes()) { message = attr.getFirstChild().getNodeValue().trim(); } else if (attr.getNodeName().equals("RequestId") && attr.hasChildNodes()) { requestId = attr.getFirstChild().getNodeValue().trim(); } else if (attr.getNodeName().equals("Endpoint") && attr.hasChildNodes()) { endpoint = attr.getFirstChild().getNodeValue().trim(); } } } if (endpoint != null && code.equals("TemporaryRedirect")) { if (temporaryEndpoint != null) { throw new CloudException("Too deep redirect to " + endpoint); } else { return invoke(bucket, object, endpoint); } } else { if (message == null) { throw new CloudException( "Unable to identify error condition: " + status + "/" + requestId + "/" + code); } throw new S3Exception(status, requestId, code, message); } } else { throw new CloudException("Unable to parse error."); } } catch (IOException e) { if (status == HttpServletResponse.SC_FORBIDDEN) { throw new S3Exception( status, "", "AccessForbidden", "Access was denied without explanation."); } throw new CloudException(e); } catch (RuntimeException e) { throw new CloudException(e); } catch (Error e) { throw new CloudException(e); } } } finally { if (!leaveOpen) { if (input != null) { try { input.close(); } catch (IOException ignore) { } } } } } finally { if (wire.isDebugEnabled()) { wire.debug( "----------------------------------------------------------------------------------"); wire.debug(""); } } }
public void tempRedirectInvoke( @Nonnull String tempEndpoint, @Nonnull String method, @Nonnull String account, @Nonnull String resource, @Nonnull String body) throws CloudException, InternalException { if (logger.isTraceEnabled()) { logger.trace( "enter - " + AzureMethod.class.getName() + ".post(" + account + "," + resource + ")"); } if (wire.isDebugEnabled()) { wire.debug( "POST --------------------------------------------------------> " + endpoint + account + resource); wire.debug(""); } try { HttpClient client = getClient(); String url = tempEndpoint + account + resource; HttpRequestBase httpMethod = getMethod(method, url); // If it is networking configuration services if (httpMethod instanceof HttpPut) { if (url.endsWith("/services/networking/media")) { httpMethod.addHeader("Content-Type", "text/plain"); } else { httpMethod.addHeader("Content-Type", "application/xml;charset=UTF-8"); } } else { httpMethod.addHeader("Content-Type", "application/xml;charset=UTF-8"); } // dmayne version is older for anything to do with images and for disk deletion if (url.indexOf("/services/images") > -1 || (httpMethod instanceof HttpDelete && url.indexOf("/services/disks") > -1)) { httpMethod.addHeader("x-ms-version", "2012-08-01"); } else { httpMethod.addHeader("x-ms-version", "2012-03-01"); } if (strategy != null && strategy.getSendAsHeader()) { httpMethod.addHeader(strategy.getHeaderName(), strategy.getRequestId()); } if (wire.isDebugEnabled()) { wire.debug(httpMethod.getRequestLine().toString()); for (Header header : httpMethod.getAllHeaders()) { wire.debug(header.getName() + ": " + header.getValue()); } wire.debug(""); if (body != null) { wire.debug(body); wire.debug(""); } } if (httpMethod instanceof HttpEntityEnclosingRequestBase) { HttpEntityEnclosingRequestBase entityEnclosingMethod = (HttpEntityEnclosingRequestBase) httpMethod; if (body != null) { try { entityEnclosingMethod.setEntity(new StringEntity(body, "application/xml", "utf-8")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } HttpResponse response; StatusLine status; try { response = client.execute(httpMethod); status = response.getStatusLine(); } catch (IOException e) { logger.error( "post(): Failed to execute HTTP request due to a cloud I/O error: " + e.getMessage()); if (logger.isTraceEnabled()) { e.printStackTrace(); } throw new CloudException(e); } if (logger.isDebugEnabled()) { logger.debug("post(): HTTP Status " + status); } Header[] headers = response.getAllHeaders(); if (wire.isDebugEnabled()) { wire.debug(status.toString()); for (Header h : headers) { if (h.getValue() != null) { wire.debug(h.getName() + ": " + h.getValue().trim()); } else { wire.debug(h.getName() + ":"); } } wire.debug(""); } if (status.getStatusCode() != HttpServletResponse.SC_OK && status.getStatusCode() != HttpServletResponse.SC_CREATED && status.getStatusCode() != HttpServletResponse.SC_ACCEPTED) { logger.error("post(): Expected OK for GET request, got " + status.getStatusCode()); HttpEntity entity = response.getEntity(); if (entity == null) { throw new AzureException( CloudErrorType.GENERAL, status.getStatusCode(), status.getReasonPhrase(), "An error was returned without explanation"); } try { body = EntityUtils.toString(entity); } catch (IOException e) { throw new AzureException( CloudErrorType.GENERAL, status.getStatusCode(), status.getReasonPhrase(), e.getMessage()); } if (wire.isDebugEnabled()) { wire.debug(body); } wire.debug(""); AzureException.ExceptionItems items = AzureException.parseException(status.getStatusCode(), body); if (items == null) { throw new CloudException( CloudErrorType.GENERAL, status.getStatusCode(), "Unknown", "Unknown"); } logger.error( "post(): [" + status.getStatusCode() + " : " + items.message + "] " + items.details); throw new AzureException(items); } } finally { if (logger.isTraceEnabled()) { logger.trace("exit - " + AzureMethod.class.getName() + ".post()"); } if (wire.isDebugEnabled()) { wire.debug(""); wire.debug( "POST --------------------------------------------------------> " + endpoint + account + resource); } } }