/* * Copyright (c) 2010-2012 Grid Dynamics Consulting Services, Inc, All Rights Reserved * http://www.griddynamics.com * * This library is free software; you can redistribute it and/or modify it under the terms of * the Apache License; either * version 2.0 of the License, or any later version. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.griddynamics.jagger.coordinator.http.client; import com.google.common.base.Throwables; import com.griddynamics.jagger.coordinator.Command; import com.griddynamics.jagger.coordinator.NodeContext; import com.griddynamics.jagger.coordinator.async.AsyncRunner; import com.griddynamics.jagger.coordinator.http.*; import com.griddynamics.jagger.util.SerializationUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.Serializable; import java.net.SocketException; import java.net.URI; import java.net.URISyntaxException; import java.util.concurrent.Executor; public class ExchangeClient { private static final Logger log = LoggerFactory.getLogger(ExchangeClient.class); private static final String MESSAGE = "message"; private HttpClient httpClient; private String urlBase; private String urlExchangePack; private String urlRegistration; private NodeContext nodeContext; private DefaultPackExchanger packExchanger; public ExchangeClient(Executor executor, AsyncRunner<Command<Serializable>, Serializable> incomingCommandRunner, NodeContext nodeContext) { this.packExchanger = new DefaultPackExchanger(executor, incomingCommandRunner); this.nodeContext = nodeContext; } public DefaultPackExchanger getPackExchanger() { return packExchanger; } public Ack registerNode(RegistrationPack registrationPack) throws IOException { return SerializationUtils.fromString(exchangeData(urlRegistration, registrationPack)); } public void setHttpClient(HttpClient httpClient) { this.httpClient = httpClient; } public void setUrlExchangePack(String urlExchangePack) { this.urlExchangePack = urlExchangePack; } public void setUrlRegistration(String urlRegistration) { this.urlRegistration = urlRegistration; } public void setNodeContext(NodeContext nodeContext) { this.nodeContext = nodeContext; } public PackResponse exchange() throws Throwable { log.debug("Exchange requested from agent {}", nodeContext.getId()); Pack out = packExchanger.retrieve(); log.debug("Going to send pack {} from agent {}", out, nodeContext.getId()); PackRequest request = PackRequest.create(nodeContext.getId(), out); PackResponse packResponse = null; String str = null; try { str = exchangeData(urlExchangePack, request); packResponse = SerializationUtils.fromString(str); log.debug("Pack response {} from agent {}", packResponse, nodeContext.getId()); if (Ack.FAIL.equals(packResponse.getAck())) { log.warn("Pack retrieving failed! Agent {}", nodeContext.getId()); throw packResponse.getError(); } Pack in = packResponse.getPack(); packExchanger.process(in); } catch (IOException e) { if (!out.isEmpty()){ packExchanger.getCommandsToSend().addAll(out.getCommands()); packExchanger.getResultsToSend().addAll(out.getResults()); log.warn("Connection lost! Pack {} will be sent again in the next exchange session!", out); }else{ log.warn("Connection lost! Waiting for the next exchange session!"); } log.warn(e.toString()); } return packResponse; } private String exchangeData(String url, Serializable obj) throws IOException { HttpPost method = new HttpPost(urlBase + url); URIBuilder uri = new URIBuilder(URI.create(urlBase + url)); uri.setParameter(MESSAGE, SerializationUtils.toString(obj)); HttpEntity entity = null; try { method.setURI(uri.build()); HttpResponse response = httpClient.execute(method); int returnCode = response.getStatusLine().getStatusCode(); entity = response.getEntity(); log.debug("Exchange response code {}", returnCode); return EntityUtils.toString(entity); } catch (URISyntaxException e) { log.error("URIException while building uri with: \nurlBase: " + urlBase + "\nurl: " + url + "\nobj: " + obj.toString()); throw Throwables.propagate(e); } catch (IOException e) { log.error("Exception during HTTP request execution "+e.toString()); throw e; } finally { try { EntityUtils.consumeQuietly(entity); method.releaseConnection(); } catch (Throwable e) { log.error("Cannot release connection", e); } } } public void setUrlBase(String urlBase) { this.urlBase = urlBase; } }