List of usage examples for java.net SocketException getMessage
public String getMessage()
From source file:org.zaproxy.zap.extension.ascanrulesBeta.SQLInjectionHypersonic.java
/** * scans for SQL Injection vulnerabilities, using Hypersonic specific syntax. If it doesn't use * specifically Hypersonic syntax, it does not belong in here, but in SQLInjection *//*from w w w. j a v a 2 s .c om*/ @Override public void scan(HttpMessage originalMessage, String paramName, String paramValue) { // DEBUG only // log.setLevel(org.apache.log4j.Level.DEBUG); // this.debugEnabled = true; try { // Timing Baseline check: we need to get the time that it took the original query, to // know if the time based check is working correctly.. HttpMessage msgTimeBaseline = getNewMsg(); long originalTimeStarted = System.currentTimeMillis(); try { sendAndReceive(msgTimeBaseline, false); // do not follow redirects } catch (java.net.SocketTimeoutException e) { // to be expected occasionally, if the base query was one that contains some // parameters exploiting time based SQL injection? if (this.debugEnabled) log.debug("The Base Time Check timed out on [" + msgTimeBaseline.getRequestHeader().getMethod() + "] URL [" + msgTimeBaseline.getRequestHeader().getURI().getURI() + "]"); } catch (SocketException ex) { if (this.debugEnabled) log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: " + msgTimeBaseline.getRequestHeader().getURI().toString() + " for Base Time Check"); return; // No need to keep going } long originalTimeUsed = System.currentTimeMillis() - originalTimeStarted; // end of timing baseline check int countUnionBasedRequests = 0; int countTimeBasedRequests = 0; if (this.debugEnabled) log.debug("Scanning URL [" + getBaseMsg().getRequestHeader().getMethod() + "] [" + getBaseMsg().getRequestHeader().getURI() + "], field [" + paramName + "] with value [" + paramValue + "] for SQL Injection"); // Hypersonic specific time based SQL injection checks for (int timeBasedSQLindex = 0; timeBasedSQLindex < SQL_HYPERSONIC_TIME_REPLACEMENTS.length && doTimeBased && countTimeBasedRequests < doTimeMaxRequests; timeBasedSQLindex++) { HttpMessage msgAttack = getNewMsg(); String newTimeBasedInjectionValue = SQL_HYPERSONIC_TIME_REPLACEMENTS[timeBasedSQLindex] .replace(ORIG_VALUE_TOKEN, paramValue).replace(SLEEP_TOKEN, Integer.toString(sleep)); setParameter(msgAttack, paramName, newTimeBasedInjectionValue); // send it. long modifiedTimeStarted = System.currentTimeMillis(); try { sendAndReceive(msgAttack, false); // do not follow redirects countTimeBasedRequests++; } catch (java.net.SocketTimeoutException e) { // this is to be expected, if we start sending slow queries to the database. // ignore it in this case.. and just get the time. if (this.debugEnabled) log.debug("The time check query timed out on [" + msgTimeBaseline.getRequestHeader().getMethod() + "] URL [" + msgTimeBaseline.getRequestHeader().getURI().getURI() + "] on field: [" + paramName + "]"); } catch (SocketException ex) { if (this.debugEnabled) log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: " + msgTimeBaseline.getRequestHeader().getURI().toString() + " for time check query"); return; // No need to keep going } long modifiedTimeUsed = System.currentTimeMillis() - modifiedTimeStarted; if (this.debugEnabled) log.debug("Time Based SQL Injection test: [" + newTimeBasedInjectionValue + "] on field: [" + paramName + "] with value [" + newTimeBasedInjectionValue + "] took " + modifiedTimeUsed + "ms, where the original took " + originalTimeUsed + "ms"); if (modifiedTimeUsed >= (originalTimeUsed + sleep)) { // takes more than 5 (by default) extra seconds => likely time based SQL // injection. Raise it String extraInfo = Constant.messages.getString( "ascanbeta.sqlinjection.alert.timebased.extrainfo", newTimeBasedInjectionValue, modifiedTimeUsed, paramValue, originalTimeUsed); String attack = Constant.messages.getString("ascanbeta.sqlinjection.alert.booleanbased.attack", paramName, newTimeBasedInjectionValue); // raise the alert bingo(Alert.RISK_HIGH, Alert.CONFIDENCE_MEDIUM, getName() + " - Time Based", getDescription(), getBaseMsg().getRequestHeader().getURI().getURI(), // url paramName, attack, extraInfo, getSolution(), msgAttack); if (log.isDebugEnabled()) { log.debug("A likely Time Based SQL Injection Vulnerability has been found with [" + msgAttack.getRequestHeader().getMethod() + "] URL [" + msgAttack.getRequestHeader().getURI().getURI() + "] on field: [" + paramName + "]"); } return; } // query took longer than the amount of time we attempted to retard it by } // for each time based SQL index // end of check for time based SQL Injection } catch (InvalidRedirectLocationException e) { // Not an error, just means we probably attacked the redirect location } catch (Exception e) { // Do not try to internationalise this.. we need an error message in any event.. // if it's in English, it's still better than not having it at all. log.error("An error occurred checking a url for Hypersonic SQL Injection vulnerabilities", e); } }
From source file:info.pancancer.arch3.worker.WorkerRunnable.java
/** * Create a new Worker.//from w ww . ja v a 2 s . c o m * * @param configFile * - The name of the configuration file to read. * @param vmUuid * - The UUID of the VM on which this worker is running. * @param maxRuns * - The maximum number of workflows this Worker should execute. * @param testMode * - Should this worker run in testMode (seqware job will not actually be launched) * @param endless * - have the worker pick up new jobs as the current job finishes successfully */ public WorkerRunnable(String configFile, String vmUuid, int maxRuns, boolean testMode, boolean endless) { log.debug("WorkerRunnable created with args:\n\tconfigFile: " + configFile + "\n\tvmUuid: " + vmUuid + "\n\tmaxRuns: " + maxRuns + "\n\ttestMode: " + testMode + "\n\tendless: " + endless); try { this.networkAddress = getFirstNonLoopbackAddress().toString().substring(1); } catch (SocketException e) { // TODO Auto-generated catch block log.error("Could not get network address: " + e.getMessage(), e); throw new RuntimeException("Could not get network address: " + e.getMessage()); } this.maxRuns = maxRuns; settings = Utilities.parseConfig(configFile); // TODO: Dyanmically change path to log file, it should be /var/log/arch3.log in production, but for test, ./arch3.log // FileAppender<ILoggingEvent> appender = (FileAppender<ILoggingEvent>) // ((ch.qos.logback.classic.Logger)log).getAppender("FILE_APPENDER"); // appender.setFile("SomePath"); this.queueName = settings.getString(Constants.RABBIT_QUEUE_NAME); if (this.queueName == null) { throw new NullPointerException( "Queue name was null! Please ensure that you have properly configured \"rabbitMQQueueName\" in your config file."); } this.jobQueueName = this.queueName + "_jobs"; this.resultsQueueName = this.queueName + "_results"; this.userName = settings.getString(Constants.WORKER_HOST_USER_NAME, "ubuntu"); /* * If the user specified "--endless" on the CLI, then this.endless=true Else: check to see if "endless" is in the config file, and * if it is, parse the value of it and use that. If not in the config file, then use "false". */ this.endless = endless ? endless : settings.getBoolean(Constants.WORKER_ENDLESS, false); if (this.endless) { log.info("The \"--endless\" flag was set, this worker will run endlessly!"); } this.vmUuid = vmUuid; this.maxRuns = maxRuns; this.testMode = testMode; }
From source file:com.kyne.webby.rtk.web.WebServer.java
public void printJSONObject(final JSONObject data, final Socket clientSocket) { try {/* w w w .j a v a2s . c om*/ final DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream()); out.writeBytes("HTTP/1.1 200 OK\r\n"); out.writeBytes("Content-Type: application/json; charset=utf-8\r\n"); out.writeBytes("Cache-Control: no-cache \r\n"); out.writeBytes("Server: Bukkit Webby\r\n"); out.writeBytes("Connection: Close\r\n\r\n"); out.writeBytes(data.toJSONString()); out.flush(); out.close(); } catch (final SocketException e) { /* .. */ } catch (final Exception e) { LogHelper.error(e.getMessage(), e); } }
From source file:com.kyne.webby.rtk.web.WebServer.java
/** * Print the given String as plain text//from w ww.ja v a2s .com * @param text the text to print * @param clientSocket the client-side socket */ public void printPlainText(final String text, final Socket clientSocket) { try { final DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream()); out.writeBytes("HTTP/1.1 200 OK\r\n"); out.writeBytes("Content-Type: text/plain; charset=utf-8\r\n"); out.writeBytes("Cache-Control: no-cache \r\n"); out.writeBytes("Server: Bukkit Webby\r\n"); out.writeBytes("Connection: Close\r\n\r\n"); out.writeBytes(text); out.flush(); out.close(); } catch (final SocketException e) { /* .. */ } catch (final Exception e) { LogHelper.error(e.getMessage(), e); } }
From source file:com.kyne.webby.rtk.web.WebServer.java
@SuppressWarnings("unchecked") public void printJSON(final Map<String, Object> data, final Socket clientSocket) { try {/*from www . j a v a 2 s .c o m*/ final DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream()); out.writeBytes("HTTP/1.1 200 OK\r\n"); out.writeBytes("Content-Type: application/json; charset=utf-8\r\n"); out.writeBytes("Cache-Control: no-cache \r\n"); out.writeBytes("Server: Bukkit Webby\r\n"); out.writeBytes("Connection: Close\r\n\r\n"); final JSONObject json = new JSONObject(); json.putAll(data); out.writeBytes(json.toJSONString()); out.flush(); out.close(); } catch (final SocketException e) { /* .. */ } catch (final Exception e) { LogHelper.error(e.getMessage(), e); } }
From source file:org.zaproxy.zap.extension.ascanrulesBeta.SQLInjectionMySQL.java
/** * scans for SQL Injection vulnerabilities, using MySQL specific syntax. If it doesn't use * specifically MySQL syntax, it does not belong in here, but in TestSQLInjection *///from w ww . j a v a 2s .co m @Override public void scan(HttpMessage originalMessage, String paramName, String originalParamValue) { try { // Timing Baseline check: we need to get the time that it took the original query, to // know if the time based check is working correctly.. HttpMessage msgTimeBaseline = getNewMsg(); long originalTimeStarted = System.currentTimeMillis(); try { sendAndReceive(msgTimeBaseline, false); // do not follow redirects } catch (java.net.SocketTimeoutException e) { // to be expected occasionally, if the base query was one that contains some // parameters exploiting time based SQL injection? if (this.debugEnabled) log.debug("The Base Time Check timed out on [" + msgTimeBaseline.getRequestHeader().getMethod() + "] URL [" + msgTimeBaseline.getRequestHeader().getURI().getURI() + "]"); } catch (SocketException ex) { if (this.debugEnabled) log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: " + msgTimeBaseline.getRequestHeader().getURI().toString()); return; // No need to keep going } long originalTimeUsed = System.currentTimeMillis() - originalTimeStarted; // if the time was very slow (because JSP was being compiled on first call, for // instance) // then the rest of the time based logic will fail. Lets double-check for that scenario // by requesting the url again. // If it comes back in a more reasonable time, we will use that time instead as our // baseline. If it come out in a slow fashion again, // we will abort the check on this URL, since we will only spend lots of time trying // request, when we will (very likely) not get positive results. if (originalTimeUsed > sleep * 1000) { long originalTimeStarted2 = System.currentTimeMillis(); try { sendAndReceive(msgTimeBaseline, false); // do not follow redirects } catch (java.net.SocketTimeoutException e) { // to be expected occasionally, if the base query was one that contains some // parameters exploiting time based SQL injection? if (this.debugEnabled) log.debug( "Base Time Check 2 timed out on [" + msgTimeBaseline.getRequestHeader().getMethod() + "] URL [" + msgTimeBaseline.getRequestHeader().getURI().getURI() + "]"); } catch (SocketException ex) { if (this.debugEnabled) log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: " + msgTimeBaseline.getRequestHeader().getURI().toString()); return; // No need to keep going } long originalTimeUsed2 = System.currentTimeMillis() - originalTimeStarted2; if (originalTimeUsed2 > sleep * 1000) { // no better the second time around. we need to bale out. if (this.debugEnabled) log.debug("Both base time checks 1 and 2 for [" + msgTimeBaseline.getRequestHeader().getMethod() + "] URL [" + msgTimeBaseline.getRequestHeader().getURI().getURI() + "] are way too slow to be usable for the purposes of checking for time based SQL Injection checking. We are aborting the check on this particular url."); return; } else { // phew. the second time came in within the limits. use the later timing // details as the base time for the checks. originalTimeUsed = originalTimeUsed2; originalTimeStarted = originalTimeStarted2; } } // end of timing baseline check int countTimeBasedRequests = 0; if (this.debugEnabled) log.debug("Scanning URL [" + getBaseMsg().getRequestHeader().getMethod() + "] [" + getBaseMsg().getRequestHeader().getURI() + "], [" + paramName + "] with value [" + originalParamValue + "] for SQL Injection"); // MySQL specific time-based SQL injection checks for (int timeBasedSQLindex = 0; timeBasedSQLindex < SQL_MYSQL_TIME_REPLACEMENTS.length && doTimeBased && countTimeBasedRequests < doTimeMaxRequests; timeBasedSQLindex++) { HttpMessage msg3 = getNewMsg(); String newTimeBasedInjectionValue = SQL_MYSQL_TIME_REPLACEMENTS[timeBasedSQLindex] .replace(ORIG_VALUE_TOKEN, originalParamValue) .replace(SLEEP_TOKEN, Integer.toString(sleep)); setParameter(msg3, paramName, newTimeBasedInjectionValue); // send it. long modifiedTimeStarted = System.currentTimeMillis(); try { sendAndReceive(msg3, false); // do not follow redirects countTimeBasedRequests++; } catch (java.net.SocketTimeoutException e) { // to be expected occasionally, if the contains some parameters exploiting time // based SQL injection if (this.debugEnabled) log.debug("The time check query timed out on [" + msg3.getRequestHeader().getMethod() + "] URL [" + msg3.getRequestHeader().getURI().getURI() + "] on field: [" + paramName + "]"); } catch (SocketException ex) { if (this.debugEnabled) log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: " + msg3.getRequestHeader().getURI().toString()); return; // No need to keep going } long modifiedTimeUsed = System.currentTimeMillis() - modifiedTimeStarted; if (this.debugEnabled) log.debug("Time Based SQL Injection test: [" + newTimeBasedInjectionValue + "] on field: [" + paramName + "] with value [" + newTimeBasedInjectionValue + "] took " + modifiedTimeUsed + "ms, where the original took " + originalTimeUsed + "ms"); // add some small leeway on the time, since adding a 5 (by default) second delay in // the SQL query will not cause the request // to take a full 5 (by default) seconds longer to run than the original.. if (modifiedTimeUsed >= (originalTimeUsed + (sleep * 1000) - 200)) { // takes more than 5 (by default) extra seconds => likely time based SQL // injection. Raise it // Likely a SQL Injection. Raise it String extraInfo = Constant.messages.getString( "ascanbeta.sqlinjection.alert.timebased.extrainfo", newTimeBasedInjectionValue, modifiedTimeUsed, originalParamValue, originalTimeUsed); // raise the alert bingo(Alert.RISK_HIGH, Alert.CONFIDENCE_MEDIUM, getName(), getDescription(), getBaseMsg().getRequestHeader().getURI().getURI(), // url paramName, newTimeBasedInjectionValue, extraInfo, getSolution(), msg3); if (this.debugEnabled) log.debug("A likely Time Based SQL Injection Vulnerability has been found with [" + msg3.getRequestHeader().getMethod() + "] URL [" + msg3.getRequestHeader().getURI().getURI() + "] on field: [" + paramName + "]"); return; } // query took longer than the amount of time we attempted to retard it by // bale out if we were asked nicely if (isStop()) { if (this.debugEnabled) log.debug("Stopping the scan due to a user request"); return; } } // for each time based SQL index // end of check for MySQL time based SQL Injection } catch (InvalidRedirectLocationException e) { // Not an error, just means we probably attacked the redirect location } catch (Exception e) { // Do not try to internationalise this.. we need an error message in any event.. // if it's in English, it's still better than not having it at all. log.error("An error occurred checking a url for MySQL SQL Injection vulnerabilities", e); } }
From source file:info.pancancer.arch3.worker.WorkerRunnable.java
/** * This function will execute a workflow, based on the content of the Job object that is passed in. * * @param message//from w w w . ja v a 2 s.c om * - The message that will be published on the queue when the worker starts running the job. * @param job * - The job contains information about what workflow to execute, and how. * @return The complete stdout and stderr from the workflow execution will be returned. */ private WorkflowResult launchJob(String message, Job job, String seqwareEngine, String seqwareSettingsFile, String dockerImage) { WorkflowResult workflowResult = null; ExecutorService exService = Executors.newFixedThreadPool(2); WorkflowRunner workflowRunner = new WorkflowRunner(); try { Path pathToINI = writeINIFile(job); resultsChannel.basicPublish(this.resultsQueueName, this.resultsQueueName, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes(StandardCharsets.UTF_8)); resultsChannel.waitForConfirms(); //TODO: Parameterize dockerImage if (dockerImage == null || dockerImage.trim() == null) { dockerImage = "pancancer/seqware_whitestar_pancancer:latest"; } CommandLine cli = new CommandLine("docker"); cli.addArgument("run"); List<String> args = new ArrayList<>( Arrays.asList("--rm", "-h", "master", "-t", "-v", "/var/run/docker.sock:/var/run/docker.sock", "-v", job.getWorkflowPath() + ":/workflow", "-v", pathToINI + ":/ini", "-v", "/datastore:/datastore", "-v", "/home/" + this.userName + "/.gnos:/home/ubuntu/.gnos")); if (seqwareSettingsFile != null) { args.addAll(Arrays.asList("-v", seqwareSettingsFile + ":/home/seqware/.seqware/settings")); } args.addAll(Arrays.asList(dockerImage, "seqware", "bundle", "launch", "--dir", "/workflow", "--ini", "/ini", "--no-metadata", "--engine", seqwareEngine)); String[] argsArray = new String[args.size()]; cli.addArguments(args.toArray(argsArray)); WorkerHeartbeat heartbeat = new WorkerHeartbeat(); heartbeat.setQueueName(this.resultsQueueName); // channels should not be shared between threads https://www.rabbitmq.com/api-guide.html#channel-threads // heartbeat.setReportingChannel(resultsChannel); heartbeat.setSettings(settings); heartbeat.setSecondsDelay( settings.getDouble(Constants.WORKER_HEARTBEAT_RATE, WorkerHeartbeat.DEFAULT_DELAY)); heartbeat.setJobUuid(job.getUuid()); heartbeat.setVmUuid(this.vmUuid); heartbeat.setNetworkID(this.networkAddress); heartbeat.setStatusSource(workflowRunner); long presleep = settings.getLong(Constants.WORKER_PREWORKER_SLEEP, WorkerRunnable.DEFAULT_PRESLEEP); long postsleep = settings.getLong(Constants.WORKER_POSTWORKER_SLEEP, WorkerRunnable.DEFAULT_POSTSLEEP); long presleepMillis = Base.ONE_SECOND_IN_MILLISECONDS * presleep; long postsleepMillis = Base.ONE_SECOND_IN_MILLISECONDS * postsleep; workflowRunner.setCli(cli); workflowRunner.setPreworkDelay(presleepMillis); workflowRunner.setPostworkDelay(postsleepMillis); // Submit both @SuppressWarnings("unused") // We will never actually do submit.get(), because the heartbeat should keep running until it is terminated by // exService.shutdownNow(). Future<?> submit = exService.submit(heartbeat); Future<WorkflowResult> workflowResultFuture = exService.submit(workflowRunner); // make sure both are complete workflowResult = workflowResultFuture.get(); // don't get the heartbeat if the workflow is complete already log.info("Docker execution result: " + workflowResult.getWorkflowStdout()); } catch (SocketException e) { // This comes from trying to get the IP address. log.error(e.getMessage(), e); } catch (IOException e) { // This could be caused by a problem writing the file, or publishing a message to the queue. log.error(e.getMessage(), e); } catch (ExecutionException e) { log.error("Error executing workflow: " + e.getMessage(), e); } catch (InterruptedException e) { log.error("Workflow may have been interrupted: " + e.getMessage(), e); } finally { exService.shutdownNow(); } return workflowResult; }
From source file:com.kyne.webby.rtk.web.WebServer.java
/** * Read a print a static file (js, css, html or png). * @param path the path to the file//from w w w .j a v a 2s. c o m * @param type the mimetype * @param jsStates some javascripts variables that may be initialized in the printed content. Null if not required. * @param clientSocket the client-side socket */ public void printStaticFile(final String path, final String type, final Socket clientSocket, final Map<String, String> jsStates) { try { final File htmlPage = new File(path); if (htmlPage.exists()) { final DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream()); out.writeBytes("HTTP/1.1 200 OK\r\n"); out.writeBytes("Content-Type: " + type + "; charset=utf-8\r\n"); out.writeBytes("Cache-Control: no-cache \r\n"); out.writeBytes("Server: Bukkit Webby\r\n"); out.writeBytes("Connection: Close\r\n\r\n"); if (jsStates != null) { out.writeBytes("<script type='text/javascript'>"); for (final String var : jsStates.keySet()) { out.writeBytes("var " + var + " = '" + jsStates.get(var) + "';"); } out.writeBytes("</script>"); } if (!this.htmlCache.containsKey(path)) { //Pages are static, so we can "pre-read" them. Dynamic content will be rendered with javascript final FileInputStream fis = new FileInputStream(htmlPage); final byte fileContent[] = new byte[(int) htmlPage.length()]; fis.read(fileContent); fis.close(); this.htmlCache.put(path, fileContent); } else { LogHelper.debug("File will be added in Webby's cache"); } out.write(this.htmlCache.get(path)); out.flush(); out.close(); } else { LogHelper.warn("Requested file " + path + " can't be found"); } } catch (final SocketException e) { /* Or not ! */ } catch (final Exception e) { LogHelper.error(e.getMessage(), e); } }
From source file:org.eclipse.smarthome.binding.lifx.internal.LifxLightDiscovery.java
@Override protected void activate(Map<String, Object> configProperties) { super.activate(configProperties); broadcastAddresses = new ArrayList<InetSocketAddress>(); interfaceAddresses = new ArrayList<InetAddress>(); Enumeration<NetworkInterface> networkInterfaces = null; try {/*w w w. j a v a2 s .c om*/ networkInterfaces = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e) { logger.debug("An exception occurred while discovering LIFX lights : '{}'", e.getMessage()); } if (networkInterfaces != null) { while (networkInterfaces.hasMoreElements()) { NetworkInterface iface = networkInterfaces.nextElement(); try { if (iface.isUp() && !iface.isLoopback()) { for (InterfaceAddress ifaceAddr : iface.getInterfaceAddresses()) { if (ifaceAddr.getAddress() instanceof Inet4Address) { logger.debug("Adding '{}' as interface address with MTU {}", ifaceAddr.getAddress(), iface.getMTU()); if (iface.getMTU() > bufferSize) { bufferSize = iface.getMTU(); } interfaceAddresses.add(ifaceAddr.getAddress()); if (ifaceAddr.getBroadcast() != null) { logger.debug("Adding '{}' as broadcast address", ifaceAddr.getBroadcast()); broadcastAddresses .add(new InetSocketAddress(ifaceAddr.getBroadcast(), BROADCAST_PORT)); } } } } } catch (SocketException e) { logger.debug("An exception occurred while discovering LIFX lights : '{}'", e.getMessage()); } } } }
From source file:com.xerox.amazonws.common.AWSQueryConnection.java
/** * Make a http request and process the response. This method also performs automatic retries. * * @param method The HTTP method to use (GET, POST, DELETE, etc) * @param action the name of the action for this query request * @param params map of request params//ww w. j a v a 2 s . c om * @param respType the class that represents the desired/expected return type */ protected <T> T makeRequest(HttpMethodBase method, String action, Map<String, String> params, Class<T> respType) throws HttpException, IOException, JAXBException { // add auth params, and protocol specific headers Map<String, String> qParams = new HashMap<String, String>(params); qParams.put("Action", action); qParams.put("AWSAccessKeyId", getAwsAccessKeyId()); qParams.put("SignatureVersion", "" + sigVersion); qParams.put("Timestamp", httpDate()); if (headers != null) { for (Iterator<String> i = headers.keySet().iterator(); i.hasNext();) { String key = i.next(); for (Iterator<String> j = headers.get(key).iterator(); j.hasNext();) { qParams.put(key, j.next()); } } } // sort params by key ArrayList<String> keys = new ArrayList<String>(qParams.keySet()); Collator stringCollator = Collator.getInstance(); stringCollator.setStrength(Collator.PRIMARY); Collections.sort(keys, stringCollator); // build param string StringBuilder resource = new StringBuilder(); if (sigVersion == 0) { // ensure Action, Timestamp come first! resource.append(qParams.get("Action")); resource.append(qParams.get("Timestamp")); } else { for (String key : keys) { resource.append(key); resource.append(qParams.get(key)); } } // calculate signature String encoded = urlencode(encode(getSecretAccessKey(), resource.toString(), false)); // build param string, encoding values and adding request signature resource = new StringBuilder(); for (String key : keys) { resource.append("&"); resource.append(key); resource.append("="); resource.append(urlencode(qParams.get(key))); } resource.setCharAt(0, '?'); // set first param delimeter resource.append("&Signature="); resource.append(encoded); // finally, build request object URL url = makeURL(resource.toString()); method.setURI(new URI(url.toString(), true)); method.setRequestHeader(new Header("User-Agent", userAgent)); if (sigVersion == 0) { method.setRequestHeader(new Header("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")); } Object response = null; boolean done = false; int retries = 0; boolean doRetry = false; String errorMsg = ""; do { int responseCode = 600; // default to high value, so we don't think it is valid try { responseCode = getHttpClient().executeMethod(method); } catch (SocketException ex) { // these can generally be retried. Treat it like a 500 error doRetry = true; errorMsg = ex.getMessage(); } // 100's are these are handled by httpclient if (responseCode < 300) { // 200's : parse normal response into requested object if (respType != null) { InputStream iStr = method.getResponseBodyAsStream(); response = JAXBuddy.deserializeXMLStream(respType, iStr); } done = true; } else if (responseCode < 400) { // 300's : what to do? throw new HttpException("redirect error : " + responseCode); } else if (responseCode < 500) { // 400's : parse client error message String body = getStringFromStream(method.getResponseBodyAsStream()); throw new HttpException("Client error : " + getErrorDetails(body)); } else if (responseCode < 600) { // 500's : retry... doRetry = true; String body = getStringFromStream(method.getResponseBodyAsStream()); errorMsg = getErrorDetails(body); } if (doRetry) { retries++; if (retries > maxRetries) { throw new HttpException("Number of retries exceeded : " + action + ", " + errorMsg); } doRetry = false; try { Thread.sleep((int) Math.pow(2.0, retries) * 1000); } catch (InterruptedException ex) { } } } while (!done); return (T) response; }