/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.core.common.notifications;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.roda.core.RodaCoreFactory;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.utils.JsonUtils;
import org.roda.core.data.v2.jobs.Job;
import org.roda.core.data.v2.notifications.Notification;
import org.roda.core.data.v2.notifications.Notification.NOTIFICATION_STATE;
import org.roda.core.model.ModelService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HTTPNotificationProcessor implements NotificationProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(HTTPNotificationProcessor.class);
public static final String JOB_KEY = "job";
private String endpoint;
private Map<String, Object> scope;
public HTTPNotificationProcessor(String endpoint, Map<String, Object> scope) {
this.endpoint = endpoint;
this.scope = scope;
}
@Override
public Notification processNotification(ModelService model, Notification notification) {
if (scope.containsKey(JOB_KEY)) {
Job job = (Job) scope.get(JOB_KEY);
String content = createNotificationContent(job);
notification.setBody(content);
if (endpoint != null) {
LOGGER.debug("Sending notification via HTTP ...");
int timeout = RodaCoreFactory.getRodaConfiguration().getInt(RodaConstants.NOTIFICATION_HTTP_TIMEOUT, 10000);
boolean success = post(endpoint, content, timeout);
if (success) {
LOGGER.debug("Notification sent");
notification.setState(NOTIFICATION_STATE.COMPLETED);
} else {
LOGGER.debug("Notification not sent");
notification.setState(NOTIFICATION_STATE.FAILED);
}
} else {
LOGGER.warn("No endpoint, cannot send notification.");
}
}
return notification;
}
private String createNotificationContent(Job job) {
// TODO: create content (XML?) from Job
return JsonUtils.getJsonFromObject(job);
}
private boolean post(String endpoint, String content, int timeout) {
boolean success = true;
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout)
.setConnectionRequestTimeout(timeout).build();
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
HttpPost httppost = new HttpPost(endpoint);
httppost.setConfig(requestConfig);
httppost.setEntity(new StringEntity(content));
HttpResponse response = httpclient.execute(httppost);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
success = false;
} else {
HttpEntity entity = response.getEntity();
String responseTxt = processEntity(entity);
LOGGER.debug("HTTP response: {}", responseTxt);
}
} catch (IOException e) {
LOGGER.debug("HTTP POST error: {}", e.getMessage());
success = false;
}
return success;
}
// FIXME 20160905 hsilva: is this method really needed? and, is this the best
// way to implement it (30 lines)?
private String processEntity(HttpEntity entity) {
String responseTxt = null;
if (entity != null) {
InputStream is = null;
try {
is = entity.getContent();
StringBuilder sb = new StringBuilder();
String line;
try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
// do nothing
}
responseTxt = sb.toString();
} catch (UnsupportedOperationException | IOException e1) {
// do nothing
} finally {
IOUtils.closeQuietly(is);
}
}
return responseTxt;
}
}