package gov.nih.ncgc.bard.capextract.handler;
import gov.nih.ncgc.bard.capextract.CAPConstants;
import gov.nih.ncgc.bard.capextract.CAPUtil;
import gov.nih.ncgc.bard.capextract.SslHttpClient;
import gov.nih.ncgc.bard.capextract.jaxb.Link;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Vector;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.StringEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hazelcast.client.ClientConfig;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.core.ITopic;
//import java.io.BufferedReader;
//import java.io.InputStream;
/**
* A one line summary.
*
* @author Rajarshi Guha
*/
public abstract class CapResourceHandler {
protected Logger log;
private JAXBContext jc;
private HttpClient httpClient;
protected CapResourceHandler() {
httpClient = SslHttpClient.getHttpClient();
log = LoggerFactory.getLogger(this.getClass());
try {
jc = JAXBContext.newInstance("gov.nih.ncgc.bard.capextract.jaxb");
} catch (JAXBException e) {
e.printStackTrace();
}
}
public <T> Vector<T> poll(String url, CAPConstants.CapResource resource) throws IOException {
return poll(url, resource, false);
}
public <T> Vector<T> poll(String url, CAPConstants.CapResource resource, boolean skipPartial) throws IOException {
Vector<T> vec = new Vector<T>();
while (url != null) {
T t = getResponse(url, resource);
vec.add(t);
url = null;
try {
Method getLinkList = t.getClass().getMethod("getLink", (Class<?>[])null);
@SuppressWarnings("unchecked")
List<Link> links = (List<Link>)getLinkList.invoke(t, (Object[])null);
for (Link link: links)
if (link.getRel().equals("next") && !skipPartial)
url = link.getHref();
} catch (Exception e) {;}
}
return vec;
}
protected <T> T getResponse(String url, CAPConstants.CapResource resource) throws IOException {
HttpGet get = new HttpGet(url);
get.setHeader("Accept", resource.getMimeType());
get.setHeader(CAPConstants.CAP_APIKEY_HEADER, CAPConstants.getApiKey());
HttpResponse response;
try {
response = httpClient.execute(get);
} catch (HttpHostConnectException ex) {
ex.printStackTrace();
try {
Thread.sleep(5000);
} catch (InterruptedException ie) {ie.printStackTrace();}
httpClient = SslHttpClient.getHttpClient();
response = httpClient.execute(get);
}
log.info("Got a HTTP " + response.getStatusLine().getStatusCode() + " for " + resource + ": " + url);
if (response.getStatusLine().getStatusCode() != 200 && response.getStatusLine().getStatusCode() != 206)
throw new IOException("Got a HTTP " + response.getStatusLine().getStatusCode() + " for " + resource + ": " + url);
if (response.getStatusLine().getStatusCode() == 206)
log.info("Got a 206 (partial content) ... make sure this is handled appropriately for " + resource + ": " + url);
// For debugging
// if (url.endsWith("assays/1640")) {
// BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
// BufferedWriter writer = new BufferedWriter(new FileWriter("assay-1640.xml"));
// String line;
// while ((line = reader.readLine()) != null) writer.write(line+"\n");
// writer.close();
// System.exit(-1);
//// }
// dump all documents for an entity type
// if (url.contains("/projects/") && !url.endsWith("/projects/")) {
// String[] toks = url.split("/");
// String fname = "tmp-project/"+toks[toks.length-1]+".xml";
// BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
// BufferedWriter writer = new BufferedWriter(new FileWriter(fname));
// String line;
// while ((line = reader.readLine()) != null) writer.write(line+"\n");
// writer.close();
// return null;
// }
Unmarshaller unmarshaller;
try {
unmarshaller = jc.createUnmarshaller();
Reader reader = new InputStreamReader(response.getEntity().getContent(), "UTF-8");
Object o = unmarshaller.unmarshal(reader);
@SuppressWarnings("unchecked")
T t = (T)o;
return t;
} catch (JAXBException e) {
throw new IOException("Error unmarshalling document from " + url, e);
}
}
/**
* Sets the extraction status for a given CAP resource.
*
* @param status Status String, set from CAPConstants.(CAP_STATUS_READY | CAP_STATUS_STARTED | CAP_STATUS_COMPLETE)
* @param url The URL for the CAP resource
* @param resource The CAP resource
* @param entityVersionEtagId CAP resources are versioned, a header field labeled 'Etag' provides the current version
* @return on success returns the new entity version (Etag), else returns -1
*/
public int setExtractionStatus(String status, String url, CAPConstants.CapResource resource) {
int etag = -1;
String etagStr = null;
try {
httpClient = SslHttpClient.getHttpClient();
//need to get the current CAP etag for the header, arggg
HttpGet get = new HttpGet(url);
get.setHeader("Accept", resource.getMimeType());
get.setHeader(CAPConstants.CAP_APIKEY_HEADER, CAPConstants.getApiKey());
HttpResponse baseResponse = httpClient.execute(get);
if(baseResponse != null && baseResponse.getFirstHeader("Etag").getValue() != null) {
etag = Integer.parseInt(baseResponse.getFirstHeader("Etag").getValue());
HttpPut put = new HttpPut(url);
put.setHeader("Accept", resource.getMimeType());
put.setHeader(CAPConstants.CAP_APIKEY_HEADER, CAPConstants.getApiKey());
put.setHeader("If-Match", Integer.toString(etag)); //use the etag here
//set the status
put.setEntity(new StringEntity(status));
HttpResponse response = httpClient.execute(put);
if(response.getStatusLine().getStatusCode() == 200) {
log.info("Changed CAP Entity status to "+status+ " for resource URL:"+url);
etag = Integer.parseInt(response.getFirstHeader("Etag").getValue());
}
}
} catch (ClientProtocolException e) {
log.warn("Error setting CAP extraction status ("+status+")");
e.printStackTrace();
} catch (IOException e) {
log.warn("Error setting CAP extraction status ("+status+")");
e.printStackTrace();
}
return etag;
}
protected boolean setEntityUpdateField(long bardEntityId, CAPConstants.CapResource resource) {
boolean updated = false;
Connection conn = null;
try {
//connect to db
conn = CAPUtil.connectToBARD(CAPConstants.getBardDBJDBCUrl());
conn.setAutoCommit(true);
//determine entity table and entity id type based on resource
String entityTable = null;
String entityIdField = null;
if (resource == CAPConstants.CapResource.ASSAY) {
entityTable = "bard_assay";
entityIdField = "bard_assay_id";
} else if (resource == CAPConstants.CapResource.EXPERIMENT) {
entityTable = "bard_experiment";
entityIdField = "bard_expt_id";
} else if (resource == CAPConstants.CapResource.PROJECT) {
entityTable = "bard_project";
entityIdField = "bard_proj_id";
}
//make sure we have an entity type we can handle
if (entityTable != null) {
Statement stmt = conn.createStatement();
String sql = "update "+entityTable+" set updated=now() where "+entityIdField+"="+bardEntityId;
stmt.execute(sql);
updated = (stmt.getUpdateCount() > 0);
if(updated) {
log.info("Updated the entity *updated* field for "+entityIdField+"="+bardEntityId);
} else {
log.warn("Unable to update the entity *updated* field for "+entityIdField+"="+bardEntityId);
}
}
conn.close();
} catch (SQLException e) {
e.printStackTrace();
return updated;
}
return updated;
}
public boolean updateGlobalBardUpdateTime() {
Connection conn;
boolean updated = false;
try {
conn = CAPUtil.connectToBARD(CAPConstants.getBardDBJDBCUrl());
conn.setAutoCommit(true);
Statement stmt = conn.createStatement();
stmt.execute("update bard_update_time set updated = now()");
stmt.close();
conn.close();
updated = true;
log.info("BARD Global Update Time has been Updated in table bard_update_time.");
} catch(SQLException e) {
e.printStackTrace();
return updated;
}
return updated;
}
public boolean signalFlushRestCache() {
boolean flushed = false;
String ipList = CAPConstants.getBardBroadcastIPList();
log.info("Signalling to Flush Cache");
if(ipList != null) {
String [] ipArr = ipList.split(",");
ClientConfig clientConfig = new ClientConfig();
clientConfig.getGroupConfig().setName("dev").setPassword("dev-pass");
for(String ip : ipArr) {
clientConfig.addAddress(ip.trim());
}
HazelcastClient client = HazelcastClient.newHazelcastClient(clientConfig);
ITopic <String> topic = client.getTopic("FLUSH_BROADCAST");
topic.publish("FLUSH");
client.shutdown();
flushed = true;
log.info("Flush Cache Message Sent!!! to "+ipList);
}
return flushed;
}
}