177 lines
6.9 KiB
Java
177 lines
6.9 KiB
Java
package org.gcube.socialnetworking.socialdataindexer.utils;
|
|
|
|
import static org.gcube.resources.discovery.icclient.ICFactory.client;
|
|
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
|
|
|
import java.io.IOException;
|
|
import java.net.HttpURLConnection;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.apache.http.Header;
|
|
import org.apache.http.HttpResponse;
|
|
import org.apache.http.client.ClientProtocolException;
|
|
import org.apache.http.client.methods.HttpPost;
|
|
import org.apache.http.entity.ContentType;
|
|
import org.apache.http.entity.StringEntity;
|
|
import org.apache.http.impl.client.CloseableHttpClient;
|
|
import org.apache.http.impl.client.HttpClientBuilder;
|
|
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
|
import org.gcube.common.resources.gcore.GCoreEndpoint;
|
|
import org.gcube.common.scope.api.ScopeProvider;
|
|
import org.gcube.resources.discovery.client.api.DiscoveryClient;
|
|
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
|
|
import org.gcube.vremanagement.executor.plugin.PluginStateEvolution;
|
|
import org.gcube.vremanagement.executor.plugin.PluginStateNotification;
|
|
import org.json.simple.JSONObject;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
/**
|
|
* Send a notification to the interested person.
|
|
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
|
|
*/
|
|
public class SendNotification extends PluginStateNotification {
|
|
|
|
private Map<String, String> pluginInputs;
|
|
private static Logger logger = LoggerFactory.getLogger(SendNotification.class);
|
|
private static final String NOTIFY_METHOD = "2/notifications/notify-job-status";
|
|
private static final String resource = "jersey-servlet";
|
|
private static final String serviceName = "SocialNetworking";
|
|
private static final String serviceClass = "Portal";
|
|
|
|
// user to contact on exception via social-networking ws
|
|
private final static String RECIPIENT_KEY = "recipient";
|
|
|
|
// service name
|
|
private final static String SERVICE_NAME = "Smart-Executor";
|
|
|
|
public SendNotification(Map<String, String> inputs) {
|
|
super(inputs);
|
|
this.pluginInputs = inputs;
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
public void pluginStateEvolution(PluginStateEvolution pluginStateEvolution,
|
|
Exception exception) throws Exception {
|
|
|
|
switch(pluginStateEvolution.getPluginState()){
|
|
|
|
// case DONE:
|
|
case STOPPED:
|
|
case FAILED:
|
|
case DISCARDED:
|
|
|
|
// check what happened
|
|
String recipient = pluginInputs.get(RECIPIENT_KEY);
|
|
String basePath = discoverEndPoint();
|
|
logger.info("Recipient of the notification is " + recipient + ". Base path found for the notification service is " + basePath);
|
|
|
|
if(basePath != null && recipient != null){
|
|
|
|
basePath = basePath.endsWith("/") ? basePath : basePath + "/";
|
|
basePath += NOTIFY_METHOD + "?gcube-token=" + SecurityTokenProvider.instance.get();
|
|
basePath = basePath.trim();
|
|
|
|
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build()){
|
|
JSONObject obj = new JSONObject();
|
|
obj.put("job_id", pluginStateEvolution.getUUID().toString());
|
|
obj.put("recipient", recipient);
|
|
obj.put("job_name", pluginStateEvolution.getPluginDefinition().getName());
|
|
obj.put("service_name", SERVICE_NAME);
|
|
// if(pluginStateEvolution.getPluginState().equals(PluginState.DONE))
|
|
// obj.put("status", "SUCCEEDED");
|
|
// else{
|
|
obj.put("status", "FAILED");
|
|
obj.put("status_message", "original status reported by " + SERVICE_NAME + " was " + pluginStateEvolution.getPluginState()
|
|
+ ". Exception is " + exception != null ? exception.getMessage() : null);
|
|
// }
|
|
logger.debug("Request json is going to be " + obj.toJSONString());
|
|
|
|
HttpResponse response = performRequest(httpClient, basePath, obj.toJSONString());
|
|
|
|
logger.info(response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
|
|
|
|
int status = response.getStatusLine().getStatusCode();
|
|
|
|
if(status == HttpURLConnection.HTTP_OK){
|
|
logger.info("Notification sent");
|
|
}
|
|
else if(status == HttpURLConnection.HTTP_MOVED_TEMP
|
|
|| status == HttpURLConnection.HTTP_MOVED_PERM
|
|
|| status == HttpURLConnection.HTTP_SEE_OTHER){
|
|
|
|
// redirect -> fetch new location
|
|
Header[] locations = response.getHeaders("Location");
|
|
Header lastLocation = locations[locations.length - 1];
|
|
String realLocation = lastLocation.getValue();
|
|
logger.info("New location is " + realLocation);
|
|
|
|
response = performRequest(httpClient, realLocation, obj.toJSONString());
|
|
|
|
logger.info(" " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
|
|
}else
|
|
logger.warn(" " + response.getStatusLine().getStatusCode() + " and response message is " + response.getStatusLine().getReasonPhrase());
|
|
}catch (Exception e) {
|
|
logger.warn("Something failed when trying to notify the user", e);
|
|
}
|
|
}
|
|
break;
|
|
default: logger.info("No notification is going to be sent, because the status of the plugin execution is " + pluginStateEvolution.getPluginState().name());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Perform the post/json request
|
|
* @param httpClient
|
|
* @param path
|
|
* @param params
|
|
* @return
|
|
* @throws ClientProtocolException
|
|
* @throws IOException
|
|
*/
|
|
private static HttpResponse performRequest(CloseableHttpClient httpClient, String path, String params) throws ClientProtocolException, IOException{
|
|
|
|
HttpPost request = new HttpPost(path);
|
|
StringEntity paramsEntity = new StringEntity(params, ContentType.APPLICATION_JSON);
|
|
request.setEntity(paramsEntity);
|
|
return httpClient.execute(request);
|
|
|
|
}
|
|
|
|
/**
|
|
* Discover the social networking service base path.
|
|
* @return base path of the service.
|
|
*/
|
|
private static String discoverEndPoint(){
|
|
String context = ScopeProvider.instance.get();
|
|
String basePath = null;
|
|
try{
|
|
|
|
SimpleQuery query = queryFor(GCoreEndpoint.class);
|
|
query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'",serviceClass));
|
|
query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'");
|
|
query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'",serviceName));
|
|
query.setResult("$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \""+resource+"\"]/text()");
|
|
|
|
DiscoveryClient<String> client = client();
|
|
List<String> endpoints = client.submit(query);
|
|
if (endpoints == null || endpoints.isEmpty())
|
|
throw new Exception("Cannot retrieve the GCoreEndpoint serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+context);
|
|
|
|
basePath = endpoints.get(0);
|
|
if(basePath==null)
|
|
throw new Exception("Endpoint:"+resource+", is null for serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+context);
|
|
|
|
logger.info("found entryname "+basePath+" for ckanResource: "+resource);
|
|
|
|
}catch(Exception e){
|
|
logger.error("Unable to retrieve such service endpoint information!", e);
|
|
}
|
|
|
|
return basePath;
|
|
}
|
|
|
|
}
|