package org.evolved.core.shared; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.net.ssl.SSLContext; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.config.CookieSpecs; 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.HttpClients; import org.apache.http.impl.io.EmptyInputStream; import org.apache.http.ssl.SSLContextBuilder; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.openedit.Data; import org.openedit.OpenEditException; import org.openedit.hittracker.HitTracker; import org.openedit.hittracker.SearchQuery; import org.openedit.hittracker.Term; public class RemoteHitTracker extends HitTracker { private static final Log log = LogFactory.getLog(RemoteHitTracker.class); protected String fieldBaseUrl; protected String fieldEntermediaKey; protected String fieldSessionId; protected SearchQuery fieldSearchQuery; protected int fieldSize; protected boolean fieldConnected = false; protected int fieldPage = 1; protected String fieldRemoteSearchtype; public String getRemoteSearchtype() { return fieldRemoteSearchtype; } public void setRemoteSearchtype(String inRemoteSearchtype) { fieldRemoteSearchtype = inRemoteSearchtype; } protected HttpClient fieldHttpClient; public HttpClient getSharedClient() { if (fieldHttpClient == null) { try { SSLContext sslContext; sslContext = SSLContextBuilder.create().useProtocol("TLSv1.2").build(); RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.DEFAULT).setConnectTimeout(15 * 1000).setSocketTimeout(120 * 1000).build(); fieldHttpClient = HttpClients.custom().useSystemProperties().setDefaultRequestConfig(globalConfig).setSSLContext(sslContext).build(); } catch (Throwable e) { throw new OpenEditException(e); } } return fieldHttpClient; } public String getSessionId() { if (fieldSessionId == null) { return super.getSessionId(); } return fieldSessionId; } public void setSessionId(String inSessionId) { fieldSessionId = inSessionId; } public String getBaseUrl() { if (fieldBaseUrl == null) { fieldBaseUrl = getSearcher().getPropertyDetails().getSettingValue("host"); } return fieldBaseUrl; } public void setBaseUrl(String inBaseUrl) { fieldBaseUrl = inBaseUrl; } public String getEntermediaKey() { return fieldEntermediaKey; } public void setEntermediaKey(String inEntermediaKey) { fieldEntermediaKey = inEntermediaKey; } @Override public Data get(int inCount) { log.info("Looking for item" + inCount); // ie 50 / 40 = 1 int page = (inCount / getHitsPerPage()) + 1; log.info("Item is on page" + page); // 50 - (1 * 40) = 10 relative int indexlocation = inCount - ((page-1) * getHitsPerPage()); log.info("Item is in slot " + indexlocation); if (getPage() != page) { setPage(page); } List pageOfHits = getPageOfHits(); log.info("Hits: " + pageOfHits); return (Data) pageOfHits.get(indexlocation); } @Override public Iterator iterator() { return new RemoteHitIterator(this); } @Override public boolean contains(Object inHit) { throw new OpenEditException("Not implemented"); } @Override public int size() { if (fieldConnected == false) { getPageOfHits(); fieldConnected = true; } return fieldSize; } public List getPageOfHits() { if (fieldCurrentPage == null) { JSONObject object = new JSONObject(); object.put("page", String.valueOf(getPage())); //object.put("hitsperpage",String.valueOf( getHitsPerPage())); JSONObject query = new JSONObject(); object.put("query", query); JSONArray terms = new JSONArray(); for (Iterator iterator = getSearchQuery().getTerms().iterator(); iterator.hasNext();) { Term term = (Term) iterator.next(); JSONObject nextterm = new JSONObject(); nextterm.put("field", term.getId()); nextterm.put("operator", term.getOperation()); nextterm.put("value", term.getValue()); for (Iterator iterator2 = term.getParameters().keySet().iterator(); iterator2.hasNext();) { String key = (String) iterator2.next(); nextterm.put(key, term.getParameters().get(key)); } terms.add(nextterm); } query.put("terms", terms); ArrayList currentpage = new ArrayList(); HttpPost post = new HttpPost(getBaseUrl() + "/services/lists/search/" + getRemoteSearchtype() + "?entermedia.key=" + getEntermediaKey()); post.addHeader("entermedia.key", getEntermediaKey()); StringEntity params = new StringEntity(object.toJSONString(), "UTF-8"); post.setEntity(params); try { HttpResponse response = getSharedClient().execute(post); StatusLine sl = response.getStatusLine(); int status = sl.getStatusCode(); if (status >= 400) { throw new OpenEditException("error from server " + status + " " + sl.getReasonPhrase()); } HttpEntity entity = response.getEntity(); JSONObject json = null; JSONParser parser = new JSONParser(); String charset = "utf-8"; if (entity.getContentEncoding() != null) { charset = entity.getContentEncoding().getValue(); } InputStream content = entity.getContent(); //String contents = IOUtils.toString(content, "UTF-8"); if(content instanceof EmptyInputStream) { return null; } InputStreamReader reader = new InputStreamReader(content, charset); json = (JSONObject) parser.parse(reader); JSONObject data = (JSONObject) json.get("response"); setHitsPerPage(toInt(data.get("hitsperpage"))); setSessionId((String) data.get("hitssessionid")); fieldSize = toInt(data.get("totalhits")); JSONArray results = (JSONArray) json.get("results"); for (Iterator iterator = results.iterator(); iterator.hasNext();) { JSONObject hit = (JSONObject) iterator.next(); RemoteData rdata = new RemoteData((Map) hit); currentpage.add(rdata); } fieldCurrentPage = currentpage; return currentpage; } catch (Exception e) { throw new OpenEditException(e); } } else { return fieldCurrentPage; } } public Integer toInt(Object object) { if (object instanceof String) { return Integer.valueOf((String) object); } if (object instanceof Long) { return ((Long) object).intValue(); } if (object instanceof Integer) { return (Integer) object; } return null; } }