Java tutorial
/******************************************************************************* * Copyright (c) 2010 Yadu. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Yadu - initial API and implementation ******************************************************************************/ package code.google.restclient.client; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.UnknownHostException; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.entity.FileEntity; import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.message.BasicNameValuePair; import org.apache.log4j.Logger; import code.google.restclient.common.RCConstants; import code.google.restclient.common.RCUtil; import code.google.restclient.core.Hitter; import code.google.restclient.core.HttpHandler; import code.google.restclient.exception.RCException; import code.google.restclient.init.Configurator; import code.google.restclient.mime.MimeTypeUtil; /** * @author Yaduvendra.Singh */ public class HitterClient { private static final Logger LOG = Logger.getLogger(HitterClient.class); private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled(); private static final SimpleDateFormat SDF = new SimpleDateFormat("MMddyyyyHHmmssSS"); private volatile boolean abort = false; public boolean isAbort() { return abort; } public void setAbort(boolean abort) { this.abort = abort; } public void hit(ViewRequest req, ViewResponse resp) throws RCException { Hitter hitter = new Hitter(); HttpHandler handler = new HttpHandler(); // hitter.setProxy("", -1); // set proxy taking values from UI try { String url = req.getUrlToHit(); HttpEntity reqBodyEntity = null; if (RCUtil.isEntityEnclosingMethod(req.getMethod())) { // if request method has body if (req.isPostParams()) reqBodyEntity = getUrlEncodedFormEntity(req); else if (req.isMultipart()) reqBodyEntity = getMultipartEntity(req); else reqBodyEntity = getStringOrFileEntity(req.getBodyToPost()); handler.setReqBodyEntity(reqBodyEntity); } hitter.hit(url, req.getMethod(), handler, req.getInputHeaders()); } catch (UnknownHostException uhe) { LOG.error("hit(): Error: Uknown host", uhe); throw new RCException("Error: Uknown host"); } catch (Exception e) { LOG.error("hit(): Error occured while hiting url", e); throw new RCException("Error: " + RCUtil.removeMethodName(e.getMessage())); } finally { req = prepareViewRequest(req, handler); resp = prepareViewResponse(resp, handler); if (!handler.isReqAborted()) handler.closeConnection(); } } /* ***************** Entity creator methods ***************** */ private HttpEntity getStringOrFileEntity(String body) throws RCException { if (body == null) body = ""; HttpEntity reqEntity = null; if (body.startsWith("@")) { String path = Pattern.compile("^@").matcher(body).replaceAll(""); String mimeType = MimeTypeUtil.getMimeType(path); // TODO not specifying charset as part of mime type i.e. "text/plain" and not "text/plain; charset=UTF-8" reqEntity = new FileEntity(new File(path), mimeType); // second argument is contentType e.g. "text/plain; charset=\"UTF-8\""); } else { try { reqEntity = new StringEntity(body, RCConstants.DEFAULT_CHARSET); } catch (UnsupportedEncodingException e) { throw new RCException( "getStringOrFileEntity(): Could not prepare string post entity due to unsupported encoding", e); } } return reqEntity; } private UrlEncodedFormEntity getUrlEncodedFormEntity(ViewRequest req) throws RCException { List<NameValuePair> formparams = new ArrayList<NameValuePair>(); Map<String, String> params = req.getParams(); for (String paramName : params.keySet()) { formparams.add(new BasicNameValuePair(paramName, params.get(paramName))); } try { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, RCConstants.DEFAULT_CHARSET); if (DEBUG_ENABLED) LOG.debug("getParamsPostEntity() - post body: " + streamToString(entity.getContent())); return entity; } catch (UnsupportedEncodingException e) { throw new RCException( "getParamsPostEntity(): Could not prepare params post entity due to unsupported encoding", e); } catch (IOException e) { throw new RCException("getParamsPostEntity(): request entity body could not be read"); } } private MultipartEntity getMultipartEntity(ViewRequest req) throws RCException { MultipartEntity reqEntity = new MultipartEntity(); Map<String, String> params = req.getParams(); String paramValue = null; StringBody stringBody = null; try { for (String paramName : params.keySet()) { paramValue = params.get(paramName); stringBody = new StringBody(paramValue, Charset.forName(RCConstants.DEFAULT_CHARSET)); reqEntity.addPart(paramName, stringBody); } String fileParamName = req.getFileParamName(); File selectedFile = new File(req.getFilePath()); if (selectedFile.exists() && !RCUtil.isEmpty(fileParamName)) { String mimeType = MimeTypeUtil.getMimeType(req.getFilePath()); FileBody fileBody = new FileBody(selectedFile, mimeType); reqEntity.addPart(fileParamName, fileBody); } } catch (UnsupportedEncodingException e) { throw new RCException( "getMultipartEntity(): Could not prepare multipart entity due to unsupported encoding", e); } return reqEntity; } /** * Method to get file entity from file object */ private FileEntity hit(File body) throws Exception { FileEntity fileEntity = new FileEntity(body, ""); // second argument is contentType e.g. "text/plain; charset=\"UTF-8\""); return fileEntity; } /** * Method to make get input stream entity from input stream object */ private InputStreamEntity hit(InputStream body) throws Exception { InputStreamEntity isEntity = new InputStreamEntity(body, -1); // content length is unknown so -1 return isEntity; } /* ***************** Methods to prepare view request and response objects ***************** */ private ViewRequest prepareViewRequest(ViewRequest req, HttpHandler handler) { if (handler != null && req != null) { req.setReqLine(handler.getRequestLine()); // req.setUrl(handler.getUrl()); req.setHeaders(handler.getRequestHeaders()); URI uri = handler.getUri(); if (uri != null) { req.setHost(uri.getHost()); req.setPort(uri.getPort()); req.setPath(uri.getRawPath()); req.setScheme(uri.getScheme()); req.setQueryStrRaw(uri.getRawQuery()); } req.setProtocolVersion(handler.getProtocolVersion()); } return req; } private ViewResponse prepareViewResponse(ViewResponse resp, HttpHandler handler) throws RCException { if (handler != null && resp != null) { resp.setStatusLine(handler.getStatusLine()); resp.setUrl(handler.getUrl()); resp.setHeaders(handler.getResponseHeaders()); String contentType = handler.getResponseContentType(); resp.setContentType(contentType); String respStr = null; if (isTextOrXmlResponse(handler)) { respStr = streamToString(handler); resp.setBodyStr(respStr); } else resp.setBodyFile(streamToFile(handler, contentType)); // writing xml response to file as well as keeping it as body string. This is just for showing // xml in browser with syntax highlighting until there is syntax highlighter for response pane if (!RCUtil.isEmpty(respStr) && isXmlResponse(handler)) { resp.setBodyFile(stringToFile(respStr, contentType)); } } return resp; } /* ***************** Helper methods ***************** */ private String streamToString(HttpHandler handler) throws RCException { InputStream is = handler.getResponseStream(); if (is == null) return null; StringBuilder sb = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line = null; try { while ((line = reader.readLine()) != null) { sb.append("\n"); if (abort) { handler.abort(); abort = false; break; } sb.append(line); } } catch (IOException e) { throw new RCException("streamToString(): error occurred while converting response stream to string", e); } finally { try { if (reader != null && !handler.isReqAborted()) reader.close(); } catch (IOException e) { throw new RCException("streamToString(): error occurred while closing input stream", e); } } return sb.toString().replaceFirst("\n", ""); } private String streamToString(InputStream is) throws RCException { if (is == null) return null; StringBuilder sb = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line = null; try { while ((line = reader.readLine()) != null) { sb.append("\n"); sb.append(line); } } catch (IOException e) { throw new RCException("streamToString(): error occurred while converting response stream to string", e); } finally { try { if (reader != null) reader.close(); } catch (IOException e) { throw new RCException("streamToString(): error occurred while closing input stream", e); } } return sb.toString().replaceFirst("\n", ""); } private File streamToFile(HttpHandler handler, String contentType) throws RCException { InputStream is = handler.getResponseStream(); if (is == null) return null; String timeStamp = SDF.format(new Date()); File tmpFile = new File(Configurator.getTempRespFilesDir(), "output_" + timeStamp + "." + RCConstants.TEMP_FILE_EXT); File outputFile = null; FileOutputStream fos = null; byte[] buf = new byte[2 * 1024]; int len; try { fos = new FileOutputStream(tmpFile); while ((len = is.read(buf)) != -1) { if (abort) { handler.abort(); abort = false; break; } fos.write(buf, 0, len); } fos.flush(); } catch (Exception e) { throw new RCException("streamToFile(): error occurred while writing to file", e); } finally { try { if (fos != null) fos.close(); outputFile = changeFileExtension(tmpFile, contentType); } catch (IOException e) { throw new RCException("streamToFile(): error occurred while closing input/output stream", e); } } return outputFile; } private File stringToFile(String str, String contentType) throws RCException { if (RCUtil.isEmpty(str)) return null; String timeStamp = SDF.format(new Date()); File tmpFile = new File(Configurator.getTempRespFilesDir(), "output_" + timeStamp + "." + RCConstants.TEMP_FILE_EXT); File outputFile = null; FileWriter fw = null; try { fw = new FileWriter(tmpFile); fw.write(str); fw.flush(); } catch (Exception e) { throw new RCException("stringToFile(): error occurred while writing to file", e); } finally { try { if (fw != null) fw.close(); outputFile = changeFileExtension(tmpFile, contentType); } catch (IOException e) { throw new RCException("stringToFile(): error occurred while closing file writer", e); } } return outputFile; } private File changeFileExtension(File tmpFile, String contentType) throws IOException { // change extension of file to its media type String ext = ""; if (RCUtil.isEmpty(contentType)) contentType = MimeTypeUtil.getMimeType(tmpFile); ext = getSubType(contentType); if (ext.contains("xml")) ext = "xml"; /* if ( contentType != null && contentType.indexOf("/") > 0 ) { // i.e. application/ssml+xml; charset=UTF-8 ext = contentType.substring(contentType.indexOf("/") + 1); if ( ext.indexOf(";") > 0 ) ext = ext.substring(0, ext.indexOf(";")).trim(); if ( ext.contains("xml") ) ext = "xml"; } */ if (!RCUtil.isEmpty(ext)) { String filePath = tmpFile.getCanonicalPath(); String newFileName = filePath.replaceFirst("\\." + RCConstants.TEMP_FILE_EXT + "$", "." + ext); File outputFile = new File(newFileName); boolean success = tmpFile.renameTo(outputFile); if (success) return outputFile; } return tmpFile; } /** * Returns true if response is of text or xml type or if content type is null */ private boolean isTextOrXmlResponse(HttpHandler handler) { String contentType = handler.getResponseContentType(); if (contentType != null) { if (contentType.indexOf(";") > 0) { contentType = contentType.substring(0, contentType.indexOf(";")).trim(); } // check for extra text content types specified in config file String[] extraTextContTypes = RCConstants.EXTRA_TEXT_CONTENT_TYPES.split(","); for (String extraContType : extraTextContTypes) { if (extraContType.equalsIgnoreCase(contentType)) return true; } } if (contentType != null && !contentType.startsWith("text")) return false; return true; } private boolean isXmlResponse(HttpHandler handler) { String contentType = handler.getResponseContentType(); String subType = getSubType(contentType); if (subType != null) { if (contentType.startsWith("text") && subType.contains("xml")) return true; // check for extra text content types specified in config file String[] extraTextContTypes = RCConstants.EXTRA_TEXT_CONTENT_TYPES.split(","); for (String extraContType : extraTextContTypes) { String xSubType = extraContType.substring(extraContType.indexOf("/") + 1); if (xSubType.equalsIgnoreCase(subType)) return true; } } return false; } private String getSubType(String contentType) { // process content type which is generally in format "type/subtype; charset=XYZ" // i.e. application/ssml+xml; charset=UTF-8 String subType = null; if (contentType != null && contentType.indexOf("/") > 0) { // remove type subType = contentType.substring(contentType.indexOf("/") + 1); // remove charset if (subType.indexOf(";") > 0) subType = subType.substring(0, subType.indexOf(";")).trim(); } if (DEBUG_ENABLED) LOG.debug("getSubType() - returning sub type " + subType); return subType; } /* public static void main(String[] args) { HitterClient client = new HitterClient(); ViewRequest req = new ViewRequest(); ViewResponse resp = new ViewResponse(); req.setUrl("http://localhost.mlbam.com:8080/stage/v1.1/14/content/item/read/6845668?test= you # me"); //req.setUrl("http://localhost.mlbam.com:8080/stage/v1.1/14/content/item/viewImage?fileLocation=/images/04022010/6845668/Sunset.jpg"); req.setHeadersStr("fingerprint=offline-fingerprint\nidentitypointid=9364"); req.setMethod("GET"); req.setParamsStr("output=json"); //client.setAbort(); try { client.hit(req, resp); } catch (RCException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("************ Request ****************"); System.out.println("Request Headers: \n" + req.getDisplayHeaderPart()); System.out.println("Request Body: \n" + req.getDisplayBodyPart()); System.out.println("************ Response ****************"); System.out.println("ViewResponse Headers:\n" + resp.getDisplayHeaderPart()); System.out.println("ViewResponse Body:\n" + resp.getDisplayBodyPart()); System.out.println("ViewResponse Body File Path:\n" + resp.getBodyFile()); } */ }