/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.esri.gpt.control.rest.search;
import com.esri.gpt.catalog.discovery.rest.RestQuery;
import com.esri.gpt.catalog.search.SearchCriteria;
import com.esri.gpt.catalog.search.SearchException;
import com.esri.gpt.catalog.search.SearchResult;
import com.esri.gpt.catalog.search.SearchResultRecord;
import com.esri.gpt.catalog.search.SearchResultRecords;
import com.esri.gpt.control.georss.FeedWriter;
import com.esri.gpt.control.georss.RestQueryServlet;
import com.esri.gpt.control.search.SearchController;
import com.esri.gpt.framework.collection.StringSet;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.http.IOUtility;
import com.esri.gpt.framework.jsf.FacesContextBroker;
import com.esri.gpt.framework.jsf.MessageBroker;
import com.esri.gpt.framework.util.Val;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
/**
* End-point for distributed search requests.
*/
@SuppressWarnings("serial")
public class DistributedSearchServlet extends RestQueryServlet {
// class variables =============================================================
/** class logger **/
private static Logger LOG = Logger.getLogger(DistributedSearchServlet.class
.getCanonicalName());
/** Default max search time TODO: Get it from SearchConfig **/
private static int DEFAULT_MAX_SEARCH_TIME = 5000;
// instance variables ==========================================================
/** constructors ============================================================ */
/** Default constructor. */
public DistributedSearchServlet() {
}
/** methods ================================================================= */
/**
* Processes the HTTP request.
*
* @param request
* the HTTP request.
* @param response
* HTTP response.
* @param context
* request context
* @throws Exception
* if an exception occurs
*/
@Override
public void execute(HttpServletRequest request, HttpServletResponse response,
RequestContext context) throws Exception {
LOG.finer("Handling rest query string=" + request.getQueryString());
MessageBroker msgBroker = new FacesContextBroker(request, response)
.extractMessageBroker();
// parse the query
RestQuery query = null;
PrintWriter printWriter = null;
try {
query = parseRequest(request, context);
if (query == null)
query = new RestQuery();
this.executeQuery(request, response, context, msgBroker, query);
} catch (Exception e) {
LOG.log(Level.SEVERE, "Error executing query.", e);
String msg = Val.chkStr(e.getMessage());
if (msg.length() == 0)
msg = e.toString();
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
} finally {
printWriter = response.getWriter();
if (printWriter != null) {
try {
try {
printWriter.flush();
} catch (Throwable e) {
LOG.log(Level.FINE, "Error while flushing printwriter", e);
}
} catch (Throwable t) {
LOG.log(Level.FINE, "Error while closing printwriter", t);
}
}
}
}
/**
*
* @see com.esri.gpt.control.georss.RestQueryServlet#executeQuery(javax.servlet.http.HttpServletRequest, com.esri.gpt.framework.context.RequestContext, com.esri.gpt.framework.jsf.MessageBroker, com.esri.gpt.catalog.discovery.rest.RestQuery)
*/
protected SearchResultRecords executeQuery(HttpServletRequest request,
HttpServletResponse response,
RequestContext context, MessageBroker msgBroker, RestQuery query)
throws SearchException {
// determine the rids
StringSet rids = this.getRids(request);
// Get the criteria
SearchCriteria criteria = this.toSearchCriteria(request, context, query);
SearchResultRecords searchResultRecords = new SearchResultRecords();
try {
// make the search context
SearchContext searchContext = new SearchContext();
searchContext.setHttpRequest(request);
searchContext.setMessageBroker(msgBroker);
searchContext.setRestQuery(query);
searchContext.setRIDs(rids);
searchContext.setSearchCriteria(criteria);
searchContext.setRequestContext(context);
int maxSearchTime =
Val.chkInt(getRequestParameter(request,"maxSearchTimeMilliSec"),
DEFAULT_MAX_SEARCH_TIME);
if(maxSearchTime <= 0) {
maxSearchTime = DEFAULT_MAX_SEARCH_TIME;
}
searchContext.setMaxSearchTime(maxSearchTime);
// execute the search
ISearchListener sp = null;
String sFormat = getRequestParameter(request,"f");
if (sFormat.equalsIgnoreCase("searchpage")) {
sp = new DistributedAdpSearchPageWriter();
} else if (sFormat.equalsIgnoreCase("atom")) {
sp = new DistributedAdpAtomSearchPageWriter();
} else if (sFormat.equalsIgnoreCase("html")) {
sp = new DistributedAdpHtmlWriter();
} else {
throw new Exception("Format f= not understood");
}
sp.setServletRequest(request);
sp.setServletResponse(response);
sp.setMessageBroker(msgBroker);
DistributedSearchDispatcher distributedSearch = new DistributedSearchDispatcher();
distributedSearch.setSearchContext(searchContext);
distributedSearch.addActionListener(sp);
distributedSearch.search();
} catch (Exception e) {
throw new SearchException(e.getMessage(), e);
}
return searchResultRecords;
}
/**
* Gets the RIDs specified within the request.
*
* @param request
* the HTTP request
* @return the RIDs
*/
@SuppressWarnings("unchecked")
private StringSet getRids(HttpServletRequest request) {
StringSet rids = new StringSet();
Map<String, String[]> requestParameterMap = request.getParameterMap();
for (Map.Entry<String, String[]> e : requestParameterMap.entrySet()) {
if (e.getKey().equalsIgnoreCase("rids")) {
String[] values = e.getValue();
if (values != null) {
for (String tokens : values) {
StringTokenizer st = new StringTokenizer(tokens, ",");
while (st.hasMoreElements()) {
String value = Val.chkStr((String) st.nextElement());
if (value.length() > 0) {
try {
rids.add(URLDecoder.decode(value, "UTF-8"));
} catch (UnsupportedEncodingException e1) {
// Should never happen
LOG.log(Level.WARNING, "Could not decde uuid", e1);
}
}
}
}
}
}
}
String arrRids[] = request.getParameterValues("rid");
for(int i = 0; arrRids != null && i < arrRids.length; i++) {
rids.add(arrRids[i]);
}
return rids;
}
}