package net.openesb.sdk.http;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.openesb.model.api.*;
import net.openesb.sdk.impl.mapper.ModelObjectMapper;
import net.openesb.sdk.ClientConfiguration;
import net.openesb.sdk.OpenESBClient;
import net.openesb.sdk.OpenESBClientException;
import net.openesb.sdk.model.*;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
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.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
/**
*
* @author David BRASSELY (brasseld at gmail.com)
* @author OpenESB Community
*/
public class OpenESBClientImpl implements OpenESBClient {
/**
* The API endpoint, such as "http://localhost:4848/api"
*/
private URL base;
private final static Logger logger = Logger.getLogger(OpenESBClientImpl.class.getSimpleName());
private ClientConfiguration openESBClientConfiguration;
private final static String API_ROOT = "/api";
private ObjectMapper mapper = new ModelObjectMapper();
/**
* Internal client for sending HTTP requests
*/
private final HttpClient httpClient;
private static HttpClientFactory httpClientFactory = new HttpClientFactory();
private String authorizationToken = null;
public OpenESBClientImpl(ClientConfiguration openESBClientConfiguration) {
this.openESBClientConfiguration = openESBClientConfiguration;
init();
this.httpClient = httpClientFactory.createHttpClient(openESBClientConfiguration);
}
public OpenESBClientImpl() {
this(new ClientConfiguration());
}
public OpenESBClientImpl(String server) {
this(new ClientConfiguration(server));
}
/**
* Common initialization code in this class.
*/
private void init() {
ClientConfiguration conf = getOpenESBClientConfiguration();
try {
base = new URL(conf.getServerApiUrl());
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid API URL:" + conf.getServerApiUrl(), e);
}
}
public ClientConfiguration getOpenESBClientConfiguration() {
return openESBClientConfiguration;
}
private <T> T executeRequest(Request req, HttpEntity entity, ResponseHandler<? extends T> responseHandler) throws OpenESBClientException {
HttpHost host = new HttpHost(base.getHost(), base.getPort());
try {
HttpRequestBase httpRequest;
URIBuilder uriBuilder = new URIBuilder()
.setPath(API_ROOT + req.uri());
if (req.parameters()!= null && !req.parameters().isEmpty()) {
for (Map.Entry<String, String> param : req.parameters().entrySet()) {
uriBuilder.addParameter(param.getKey(), param.getValue());
}
}
URI uri = uriBuilder.build();
switch (req.method()) {
case GET:
httpRequest = new HttpGet(uri);
break;
case POST:
HttpPost postMethod = new HttpPost(uri);
if (entity != null) {
postMethod.setEntity(entity);
}
httpRequest = postMethod;
break;
case PUT:
HttpPut putMethod = new HttpPut(uri);
if (entity != null) {
putMethod.setEntity(entity);
}
httpRequest = putMethod;
break;
case DELETE:
httpRequest = new HttpDelete(uri);
break;
case HEAD:
httpRequest = new HttpHead(uri);
break;
default:
throw new OpenESBClientException("Unknown HTTP method name: " + req.method());
}
if (req.headers() != null && !req.headers().isEmpty()) {
for (Map.Entry<String, String> header : req.headers().entrySet()) {
httpRequest.addHeader(header.getKey(), header.getValue());
}
}
if (authorizationToken != null) {
httpRequest.addHeader(HttpHeaders.AUTHORIZATION, "Token " + authorizationToken);
}
return httpClient.execute(host, httpRequest, responseHandler);
} catch (Exception ex) {
// Logger.getLogger(OpenESBClientImpl.class.getName()).log(Level.SEVERE, null, ex);
throw new OpenESBClientException(ex.getMessage(), ex);
}
}
@Override
public Set<JBIComponent> listComponents(ListComponentsRequest request) throws OpenESBClientException {
return executeRequest(
request,
null,
new JacksonResponseHandler<Set<JBIComponent>>(
new TypeReference<Set<JBIComponent>>() {
}));
}
@Override
public JBIComponent getComponent(GetComponentRequest request) throws OpenESBClientException {
return executeRequest(
request,
null,
new JacksonResponseHandler<JBIComponent>(JBIComponent.class));
}
@Override
public SharedLibrary getSharedLibrary(GetSharedLibraryRequest request) throws Exception {
return executeRequest(
request,
null,
new JacksonResponseHandler<SharedLibrary>(SharedLibrary.class));
}
@Override
public String getComponentDescriptor(GetComponentDescriptorRequest request) throws OpenESBClientException {
return StringEscapeUtils.unescapeXml(
executeRequest(request,
null,
new StringResponseHandler()));
}
@Override
public String installComponent(InstallComponentRequest request) throws OpenESBClientException {
return executeRequest(
request,
createHttpEntity("component", request.getArchiveUrl()),
new StringResponseHandler());
}
@Override
public void upgradeComponent(UpgradeComponentRequest request) throws OpenESBClientException {
executeRequest(
request,
createHttpEntity("component", request.getArchiveUrl()),
new StringResponseHandler());
}
@Override
public void uninstallComponent(UninstallComponentRequest request) throws OpenESBClientException {
executeRequest(
request,
null,
new StringResponseHandler());
}
@Override
public void startComponent(StartComponentRequest request) throws Exception {
executeRequest(
request,
null,
new StringResponseHandler());
}
@Override
public void stopComponent(StopComponentRequest request) throws Exception {
executeRequest(
request,
null,
new StringResponseHandler());
}
@Override
public void shutdownComponent(ShutdownComponentRequest request) throws Exception {
executeRequest(
request,
null,
new StringResponseHandler());
}
@Override
public Set<ApplicationVariable> listComponentApplicationVariables(ListComponentApplicationVariablesRequest request) throws Exception {
return executeRequest(
request,
null,
new JacksonResponseHandler<Set<ApplicationVariable>>(
new TypeReference<Set<ApplicationVariable>>() {
}));
}
@Override
public Set<ApplicationVariable> addComponentApplicationVariables(AddComponentApplicationVariablesRequest request) throws Exception {
String json = mapper.writeValueAsString(request.getApplicationVariables());
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
return executeRequest(
request,
entity,
new JacksonResponseHandler<Set<ApplicationVariable>>(
new TypeReference<Set<ApplicationVariable>>() {
}));
}
@Override
public void setComponentConfigurations(SetComponentConfigurationRequest request) throws Exception {
String json = mapper.writeValueAsString(request.getComponentConfigurations());
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
executeRequest(
request,
entity,
new JacksonResponseHandler<Set<ComponentConfiguration>>(
new TypeReference<Set<ComponentConfiguration>>() {
}));
}
@Override
public void setComponentLogger(SetComponentLoggerRequest request) throws Exception {
executeRequest(
request,
null,
new JacksonResponseHandler<Set<net.openesb.model.api.Logger>>(
new TypeReference<Set<net.openesb.model.api.Logger>>() {
}));
}
@Override
public Set<ComponentConfiguration> listComponentConfigurations(ListComponentConfigurationsRequest request) throws Exception {
return executeRequest(
request,
null,
new JacksonResponseHandler<Set<ComponentConfiguration>>(
new TypeReference<Set<ComponentConfiguration>>() {
}));
}
@Override
public Set<net.openesb.model.api.Logger> listComponentLoggers(ListComponentLoggersRequest request) throws Exception {
return executeRequest(
request,
null,
new JacksonResponseHandler<Set<net.openesb.model.api.Logger>>(
new TypeReference<Set<net.openesb.model.api.Logger>>() {
}));
}
@Override
public Set<ServiceAssembly> listServiceAssemblies(ListServiceAssembliesRequest request) throws Exception {
return executeRequest(
request,
null,
new JacksonResponseHandler<Set<ServiceAssembly>>(
new TypeReference<Set<ServiceAssembly>>() {
}));
}
@Override
public String deployServiceAssembly(DeployServiceAssemblyRequest request) throws Exception {
return executeRequest(
request,
createHttpEntity("assembly", request.getArchiveUrl()),
new StringResponseHandler());
}
@Override
public void undeployServiceAssembly(UndeployServiceAssemblyRequest request) throws Exception {
executeRequest(
request,
null,
new StringResponseHandler());
}
@Override
public ServiceAssembly getServiceAssembly(GetServiceAssemblyRequest request) throws Exception {
return executeRequest(
request,
null,
new JacksonResponseHandler<ServiceAssembly>(ServiceAssembly.class));
}
@Override
public String getServiceAssemblyDescriptor(GetServiceAssemblyDescriptorRequest request) throws Exception {
return StringEscapeUtils.unescapeXml(
executeRequest(
request,
null,
new StringResponseHandler()));
}
@Override
public void startServiceAssembly(StartServiceAssemblyRequest request) throws Exception {
executeRequest(
request,
null,
new StringResponseHandler());
}
@Override
public void stopServiceAssembly(StopServiceAssemblyRequest request) throws Exception {
executeRequest(
request,
null,
new StringResponseHandler());
}
@Override
public void shutdownServiceAssembly(ShutdownServiceAssemblyRequest request) throws Exception {
executeRequest(
request,
null,
new StringResponseHandler());
}
@Override
public Set<SharedLibrary> listSharedLibraries(ListSharedLibrariesRequest request) throws Exception {
return executeRequest(
request,
null,
new JacksonResponseHandler<Set<SharedLibrary>>(
new TypeReference<Set<SharedLibrary>>() {
}));
}
@Override
public String getSharedLibraryDescriptor(GetSharedLibraryDescriptorRequest request) throws Exception {
return StringEscapeUtils.unescapeXml(
executeRequest(
request,
null,
new StringResponseHandler()));
}
@Override
public String installSharedLibrary(InstallSharedLibraryRequest request) throws Exception {
return executeRequest(
request,
createHttpEntity("sharedLibrary", request.getArchiveUrl()),
new StringResponseHandler());
}
@Override
public void uninstallSharedLibrary(UninstallSharedLibraryRequest request) throws Exception {
executeRequest(
request,
null,
new StringResponseHandler());
}
private HttpEntity createHttpEntity(String name, URL archiveUrl) throws OpenESBClientException {
try {
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart(name, new FileBody(new File(archiveUrl.toURI())));
return multipartEntity.build();
} catch (URISyntaxException ex) {
logger.log(Level.SEVERE, "Unable to create an HTTP entity to upload file : " + archiveUrl, ex);
throw new OpenESBClientException("Unable to create an HTTP entity to upload file : " + archiveUrl, ex);
}
}
@Override
public String login(LoginRequest request) throws OpenESBClientException {
if (authorizationToken == null) {
authorizationToken = executeRequest(
request,
null,
new StringResponseHandler());
} else {
logger.warning("Damn! It seems you're already login... Please disconnect to perform login request again");
}
return authorizationToken;
}
@Override
public void logout(LogoutRequest request) throws OpenESBClientException {
if (authorizationToken != null) {
executeRequest(
request,
null,
new StringResponseHandler());
authorizationToken = null;
} else {
logger.warning("You're not yet authenticated! Skip...");
}
}
@Override
public Set<ApplicationVariable> updateComponentApplicationVariables(UpdateComponentApplicationVariablesRequest request) throws Exception {
String json = mapper.writeValueAsString(request.getApplicationVariables());
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
return executeRequest(
request,
entity,
new JacksonResponseHandler<Set<ApplicationVariable>>(
new TypeReference<Set<ApplicationVariable>>() {
}));
}
@Override
public Set<ApplicationVariable> deleteComponentApplicationVariables(DeleteComponentApplicationVariablesRequest request) throws Exception {
String json = mapper.writeValueAsString(request.getApplicationVariables());
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
return executeRequest(
request,
entity,
new JacksonResponseHandler<Set<ApplicationVariable>>(
new TypeReference<Set<ApplicationVariable>>() {
}));
}
private abstract class AbstractResponseHandler<T> implements ResponseHandler<T> {
@Override
public T handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
int status = response.getStatusLine().getStatusCode();
if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
return readResponse(response);
} if (status == HttpStatus.SC_UNAUTHORIZED) {
String error = "Unable to perform request. You need to be authenticated.";
logger.log(Level.SEVERE, error);
throw new HttpResponseException(status, error);
} if (status == HttpStatus.SC_BAD_REQUEST) {
String error = "Unable to perform request since this one seems to be bad... ";
logger.log(Level.SEVERE, error);
throw new HttpResponseException(status, error);
} else {
String error = EntityUtils.toString(response.getEntity());
logger.log(Level.SEVERE, "Unexpected response status: {0} - {1}", new Object[]{status, error});
throw new HttpResponseException(status, error);
}
}
protected abstract T readResponse(HttpResponse response) throws IOException;
}
private class StringResponseHandler extends AbstractResponseHandler<String> {
@Override
protected String readResponse(HttpResponse response) throws IOException {
return EntityUtils.toString(response.getEntity());
}
}
private class JacksonResponseHandler<T> extends AbstractResponseHandler<T> {
final TypeReference<T> _type;
final Class<T> _clazz;
protected JacksonResponseHandler(TypeReference<T> type) {
_type = type;
_clazz = null;
}
protected JacksonResponseHandler(Class<T> clazz) {
_clazz = clazz;
_type = null;
}
@Override
protected T readResponse(HttpResponse response) throws IOException {
if (_clazz != null) {
return mapper.readValue(
response.getEntity().getContent(),
_clazz);
} else {
return mapper.readValue(
response.getEntity().getContent(),
_type);
}
}
}
}