Java tutorial
/** * Copyright (C) 2009-2013 Dell, Inc. * * ==================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== */ package org.dasein.cloud.opsource; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; import javax.annotation.Nonnull; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.ParseException; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; 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.HttpOptions; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpTrace; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.params.AuthPolicy; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.entity.AbstractHttpEntity; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.AbstractHttpMessage; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; import org.dasein.cloud.CloudException; import org.dasein.cloud.InternalException; import org.dasein.cloud.ProviderContext; import org.dasein.cloud.util.APITrace; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class OpSourceMethod { static private final Logger logger = OpSource.getLogger(OpSourceMethod.class); static private final Logger wire = OpSource.getWireLogger(OpSourceMethod.class); private Map<String, String> parameters = null; private OpSource provider = null; private String endpoint = null; static public class ParsedError { public int code; public String message; } public OpSourceMethod(OpSource provider, String url, Map<String, String> parameters) throws InternalException { this.endpoint = url; this.parameters = parameters; this.provider = provider; } protected AbstractHttpMessage getMethod(String httpMethod, String urlStr) { AbstractHttpMessage method = null; if (httpMethod.equals("GET")) { method = new HttpGet(urlStr); } else if (httpMethod.equals("POST")) { method = new HttpPost(urlStr); } else if (httpMethod.equals("PUT")) { method = new HttpPut(urlStr); } else if (httpMethod.equals("DELETE")) { method = new HttpDelete(urlStr); } else if (httpMethod.equals("HEAD")) { method = new HttpHead(urlStr); } else if (httpMethod.equals("OPTIONS")) { method = new HttpOptions(urlStr); } else if (httpMethod.equals("HEAD")) { method = new HttpTrace(urlStr); } else { return null; } return method; } private @Nonnull HttpClient getClient(@Nonnull ProviderContext ctx, boolean ssl) { HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); //noinspection deprecation HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); HttpProtocolParams.setUserAgent(params, "Dasein Cloud"); Properties p = ctx.getCustomProperties(); if (p != null) { String proxyHost = p.getProperty("proxyHost"); String proxyPort = p.getProperty("proxyPort"); if (proxyHost != null) { int port = 0; if (proxyPort != null && proxyPort.length() > 0) { port = Integer.parseInt(proxyPort); } params.setParameter(ConnRoutePNames.DEFAULT_PROXY, new HttpHost(proxyHost, port, ssl ? "https" : "http")); } } return new DefaultHttpClient(params); } public Document invoke() throws CloudException, InternalException { if (logger.isTraceEnabled()) { logger.trace("enter - " + OpSource.class.getName() + ".invoke()"); } try { URL url = null; try { url = new URL(endpoint); } catch (MalformedURLException e1) { throw new CloudException(e1); } final String host = url.getHost(); final int urlPort = url.getPort() == -1 ? url.getDefaultPort() : url.getPort(); final String urlStr = url.toString(); DefaultHttpClient httpclient = new DefaultHttpClient(); /** HTTP Authentication */ String uid = new String(provider.getContext().getAccessPublic()); String pwd = new String(provider.getContext().getAccessPrivate()); /** Type of authentication */ List<String> authPrefs = new ArrayList<String>(2); authPrefs.add(AuthPolicy.BASIC); httpclient.getParams().setParameter("http.auth.scheme-pref", authPrefs); httpclient.getCredentialsProvider().setCredentials(new AuthScope(host, urlPort, null), new UsernamePasswordCredentials(uid, pwd)); if (wire.isDebugEnabled()) { wire.debug("--------------------------------------------------------------> " + urlStr); wire.debug(""); } AbstractHttpMessage method = this.getMethod(parameters.get(OpSource.HTTP_Method_Key), urlStr); method.setParams(new BasicHttpParams().setParameter(urlStr, url)); /** Set headers */ method.addHeader(OpSource.Content_Type_Key, parameters.get(OpSource.Content_Type_Key)); /** POST/PUT method specific logic */ if (method instanceof HttpEntityEnclosingRequest) { HttpEntityEnclosingRequest entityEnclosingMethod = (HttpEntityEnclosingRequest) method; String requestBody = parameters.get(OpSource.HTTP_Post_Body_Key); if (requestBody != null) { if (wire.isDebugEnabled()) { wire.debug(requestBody); } AbstractHttpEntity entity = new ByteArrayEntity(requestBody.getBytes()); entity.setContentType(parameters.get(OpSource.Content_Type_Key)); entityEnclosingMethod.setEntity(entity); } else { throw new CloudException("The request body is null for a post request"); } } /** Now parse the xml */ try { HttpResponse httpResponse; int status; if (wire.isDebugEnabled()) { for (org.apache.http.Header header : method.getAllHeaders()) { wire.debug(header.getName() + ": " + header.getValue()); } } /** Now execute the request */ APITrace.trace(provider, method.toString() + " " + urlStr); httpResponse = httpclient.execute((HttpUriRequest) method); status = httpResponse.getStatusLine().getStatusCode(); if (wire.isDebugEnabled()) { wire.debug("invoke(): HTTP Status " + httpResponse.getStatusLine().getStatusCode() + " " + httpResponse.getStatusLine().getReasonPhrase()); } org.apache.http.Header[] headers = httpResponse.getAllHeaders(); HttpEntity entity = httpResponse.getEntity(); if (wire.isDebugEnabled()) { wire.debug("HTTP xml status code ---------" + status); for (org.apache.http.Header h : headers) { if (h.getValue() != null) { wire.debug(h.getName() + ": " + h.getValue().trim()); } else { wire.debug(h.getName() + ":"); } } /** Can not enable this line, otherwise the entity would be empty*/ // wire.debug("OpSource Response Body for request " + urlStr + " = " + EntityUtils.toString(entity)); wire.debug("-----------------"); } if (entity == null) { parseError(status, "Empty entity"); } String responseBody = EntityUtils.toString(entity); if (status == HttpStatus.SC_OK) { InputStream input = null; try { input = new ByteArrayInputStream(responseBody.getBytes("UTF-8")); if (input != null) { Document doc = null; try { doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input); if (wire.isDebugEnabled()) { try { TransformerFactory transfac = TransformerFactory.newInstance(); Transformer trans = transfac.newTransformer(); trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); trans.setOutputProperty(OutputKeys.INDENT, "yes"); StringWriter sw = new StringWriter(); StreamResult result = new StreamResult(sw); DOMSource source = new DOMSource(doc); trans.transform(source, result); String xmlString = sw.toString(); wire.debug(xmlString); } catch (Exception ex) { ex.printStackTrace(); } } } catch (Exception ex) { ex.printStackTrace(); logger.debug(ex.toString(), ex); } return doc; } } catch (IOException e) { logger.error( "invoke(): Failed to read xml error due to a cloud I/O error: " + e.getMessage()); throw new CloudException(e); } /* catch( SAXException e ) { throw new CloudException(e); } catch( ParserConfigurationException e ) { throw new InternalException(e); } */ } else if (status == HttpStatus.SC_NOT_FOUND) { throw new CloudException("An internal error occured: The endpoint was not found"); } else { if (responseBody != null) { parseError(status, responseBody); Document parsedError = null; if (!responseBody.contains("<HR")) { parsedError = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new ByteArrayInputStream(responseBody.getBytes("UTF-8"))); if (wire.isDebugEnabled()) { try { TransformerFactory transfac = TransformerFactory.newInstance(); Transformer trans = transfac.newTransformer(); trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); trans.setOutputProperty(OutputKeys.INDENT, "yes"); StringWriter sw = new StringWriter(); StreamResult result = new StreamResult(sw); DOMSource source = new DOMSource(parsedError); trans.transform(source, result); String xmlString = sw.toString(); wire.debug(xmlString); } catch (Exception ex) { ex.printStackTrace(); } } } else logger.debug("Error message was unparsable"); return parsedError; } } } catch (ParseException e) { throw new CloudException(e); } catch (SAXException e) { throw new CloudException(e); } catch (IOException e) { e.printStackTrace(); throw new CloudException(e); } catch (ParserConfigurationException e) { throw new CloudException(e); } finally { httpclient.getConnectionManager().shutdown(); } } finally { if (logger.isTraceEnabled()) { logger.trace("exit - " + OpSource.class.getName() + ".invoke()"); } if (wire.isDebugEnabled()) { wire.debug(""); wire.debug("--------------------------------------------------------------> " + endpoint); } } return null; } public String requestResult(String action, Document doc, String resultTag, String resultDetailTag) throws CloudException, InternalException { if (doc == null) { throw new CloudException("Action -> " + action + " failed because request reponse is null"); } if (wire.isDebugEnabled()) { wire.debug(provider.convertDomToString(doc)); } String sNS = ""; try { sNS = doc.getDocumentElement().getTagName().substring(0, doc.getDocumentElement().getTagName().indexOf(":") + 1); } catch (IndexOutOfBoundsException ex) { } NodeList blocks = doc.getElementsByTagName(sNS + resultTag); if (blocks != null) { for (int i = 0; i < blocks.getLength(); i++) { Node attr = blocks.item(i); if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_SUCCESS_VALUE)) { blocks = doc.getElementsByTagName(sNS + resultDetailTag); if (blocks == null) { throw new CloudException(action + " fails " + "without explaination !!!"); } else { return blocks.item(0).getFirstChild().getNodeValue(); } } else if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_ERROR_VALUE)) { blocks = doc.getElementsByTagName(sNS + resultDetailTag); if (blocks == null) { throw new CloudException(action + " fails " + "without explaination !!!"); } else { throw new CloudException(blocks.item(0).getFirstChild().getNodeValue()); } } } } return null; } public String requestResultCode(String action, Document doc, String resultCode) throws CloudException, InternalException { if (wire.isDebugEnabled()) { wire.debug(provider.convertDomToString(doc)); } String sNS = ""; try { sNS = doc.getDocumentElement().getTagName().substring(0, doc.getDocumentElement().getTagName().indexOf(":") + 1); } catch (IndexOutOfBoundsException ex) { } NodeList blocks = doc.getElementsByTagName(sNS + resultCode); if (blocks != null) { return blocks.item(0).getFirstChild().getNodeValue(); } return null; } public String getRequestResultId(String action, Document doc, String resultTag, String resultDetailTag) throws CloudException, InternalException { if (wire.isDebugEnabled()) { wire.debug(provider.convertDomToString(doc)); } String sNS = ""; try { sNS = doc.getDocumentElement().getTagName().substring(0, doc.getDocumentElement().getTagName().indexOf(":") + 1); } catch (IndexOutOfBoundsException ex) { } NodeList blocks = doc.getElementsByTagName(sNS + resultTag); if (blocks != null) { for (int i = 0; i < blocks.getLength(); i++) { Node attr = blocks.item(i); if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_SUCCESS_VALUE)) { blocks = doc.getElementsByTagName(sNS + resultDetailTag); if (blocks == null) { throw new CloudException(action + " fails " + "without explaination !!!"); } else { String result = blocks.item(0).getFirstChild().getNodeValue().toLowerCase(); return result.split("id:")[1].substring(0, result.split("id:")[1].indexOf(")")).trim(); } } if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_ERROR_VALUE)) { blocks = doc.getElementsByTagName(sNS + OpSource.RESPONSE_RESULT_DETAIL_TAG); if (blocks == null) { logger.error(action + " fails " + "without explaination !!!"); throw new CloudException(action + " fails " + "without explaination !!!"); } else { logger.error(blocks.item(0).getFirstChild().getNodeValue()); throw new CloudException(blocks.item(0).getFirstChild().getNodeValue()); } } } } return null; } public boolean requestResult(String action, Document doc) throws CloudException, InternalException { if (wire.isDebugEnabled()) { wire.debug(provider.convertDomToString(doc)); } String sNS = ""; try { sNS = doc.getDocumentElement().getTagName().substring(0, doc.getDocumentElement().getTagName().indexOf(":") + 1); } catch (IndexOutOfBoundsException ex) { } NodeList blocks = doc.getElementsByTagName(sNS + OpSource.RESPONSE_RESULT_TAG); if (blocks != null) { for (int i = 0; i < blocks.getLength(); i++) { Node attr = blocks.item(i); if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_SUCCESS_VALUE)) { return true; } if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_ERROR_VALUE)) { blocks = doc.getElementsByTagName(sNS + OpSource.RESPONSE_RESULT_DETAIL_TAG); if (blocks == null) { throw new CloudException(action + " fails " + "without explaination !!!"); } else { throw new CloudException(blocks.item(0).getFirstChild().getNodeValue()); } } } } return false; } public boolean parseRequestResult(String action, Document doc, String resultTag, String resultDetailTag) throws CloudException, InternalException { if (wire.isDebugEnabled()) { wire.debug(provider.convertDomToString(doc)); } String sNS = ""; try { sNS = doc.getDocumentElement().getTagName().substring(0, doc.getDocumentElement().getTagName().indexOf(":") + 1); } catch (IndexOutOfBoundsException ex) { } NodeList blocks = doc.getElementsByTagName(sNS + resultTag); if (blocks != null) { for (int i = 0; i < blocks.getLength(); i++) { Node attr = blocks.item(i); if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_SUCCESS_VALUE)) { return true; } if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_ERROR_VALUE)) { blocks = doc.getElementsByTagName(sNS + resultDetailTag); if (blocks == null) { logger.error(action + " fails " + "without explaination !!!"); throw new CloudException(action + " fails " + "without explaination !!!"); } else { logger.error(blocks.item(0).getFirstChild().getNodeValue()); throw new CloudException(blocks.item(0).getFirstChild().getNodeValue()); } } } } return false; } public boolean parseRequestResultNoError(String action, Document doc, String resultTag, String resultDetailTag) throws CloudException, InternalException { if (wire.isDebugEnabled()) { wire.debug(provider.convertDomToString(doc)); } String sNS = ""; try { sNS = doc.getDocumentElement().getTagName().substring(0, doc.getDocumentElement().getTagName().indexOf(":") + 1); } catch (IndexOutOfBoundsException ex) { } NodeList blocks = doc.getElementsByTagName(sNS + resultTag); if (blocks != null) { for (int i = 0; i < blocks.getLength(); i++) { Node attr = blocks.item(i); if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_SUCCESS_VALUE)) { return true; } if (attr.getFirstChild().getNodeValue().equals(OpSource.RESPONSE_RESULT_ERROR_VALUE)) { blocks = doc.getElementsByTagName(sNS + resultDetailTag); if (blocks == null) { logger.error(action + " fails " + "without explaination !!!"); throw new CloudException(action + " fails " + "without explaination !!!"); } else { logger.trace(blocks.item(0).getFirstChild().getNodeValue()); throw new CloudException(blocks.item(0).getFirstChild().getNodeValue()); } } } } return false; } private ParsedError parseError(int httpStatus, String assumedXml) throws InternalException { if (logger.isTraceEnabled()) { logger.trace("enter - " + OpSourceMethod.class.getName() + ".parseError(" + httpStatus + "," + assumedXml + ")"); } try { ParsedError error = new ParsedError(); error.code = httpStatus; error.message = null; try { Document doc = parseResponse(httpStatus, assumedXml); String sNS = ""; try { sNS = doc.getDocumentElement().getTagName().substring(0, doc.getDocumentElement().getTagName().indexOf(":") + 1); } catch (IndexOutOfBoundsException ex) { } NodeList codes = doc.getElementsByTagName(sNS + "resultCode"); String reasoncode = codes.item(0).getFirstChild().getNodeValue(); reasoncode = reasoncode.substring(reasoncode.indexOf("_") + 1); error.code = Integer.parseInt(reasoncode); /*for( int i=0; i<codes.getLength(); i++ ) { Node n = codes.item(i); if( n != null && n.hasChildNodes() ) { error.code = Integer.parseInt(n.getFirstChild().getNodeValue().trim()); } }*/ NodeList text = doc.getElementsByTagName(sNS + "resultDetail"); error.message = text.item(0).getFirstChild().getNodeValue(); /*for( int i=0; i<text.getLength(); i++ ) { Node n = text.item(i); if( n != null && n.hasChildNodes() ) { error.message = n.getFirstChild().getNodeValue(); } }*/ logger.error(error.code + ": " + error.message); } catch (Throwable ignore) { String errorMessage = ""; try { errorMessage = URLDecoder.decode(ignore.getMessage(), "UTF-8"); } catch (Exception ex) { } logger.warn("parseError(): Error was unparsable: " + errorMessage); if (error.message == null) { error.message = assumedXml; } } if (error.message == null) { if (httpStatus == 401) { error.message = "Unauthorized user"; } else if (httpStatus == 430) { error.message = "Malformed parameters"; } else if (httpStatus == 547 || httpStatus == 530) { error.message = "Server error in cloud (" + httpStatus + ")"; } else if (httpStatus == 531) { error.message = "Unable to find account"; } else { error.message = "Received error code from server: " + httpStatus; } } logger.trace("errors - " + error.message); return error; } finally { if (logger.isTraceEnabled()) { logger.trace("exit - " + OpSourceMethod.class.getName() + ".parseError()"); } } } private Document parseResponse(int code, String xml) throws CloudException, InternalException { if (logger.isTraceEnabled()) { logger.trace("enter - " + OpSourceMethod.class.getName() + ".parseResponse(" + xml + ")"); } try { try { if (wire.isDebugEnabled()) { wire.debug(xml); } //ByteArrayInputStream input = new ByteArrayInputStream(xml.getBytes("UTF-8")); //return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input); Document parseForError = null; if (!xml.contains("<HR")) { parseForError = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new ByteArrayInputStream(xml.getBytes("UTF-8"))); return parseForError; } throw new InternalException("Unparsable error: " + xml); } catch (IOException e) { throw new CloudException(e); } catch (ParserConfigurationException e) { throw new CloudException(e); } catch (SAXException e) { throw new CloudException("Received error code from server [" + code + "]: " + xml); } } finally { if (logger.isTraceEnabled()) { logger.trace("exit - " + OpSourceMethod.class.getName() + ".parseResponse()"); } } } }