/**
* Copyright (c) 2008--2013 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.satellite.search.rpc.handlers;
import com.redhat.satellite.search.db.DatabaseManager;
import com.redhat.satellite.search.db.Query;
import com.redhat.satellite.search.index.IndexManager;
import com.redhat.satellite.search.index.Result;
import com.redhat.satellite.search.index.QueryParseException;
import com.redhat.satellite.search.scheduler.ScheduleManager;
import org.apache.log4j.Logger;
import redstone.xmlrpc.XmlRpcFault;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* XML-RPC handler which handles calls for database queries
*
* TODO:
* 1) Restrict this class to only being able to call queries
* defined in specified namespaces, for now that would be: "errataHandler",
* errata_handler.xml.
* 2) Screenhits returned, verify these objects are allowed to be seen by the logged in
* user.
*
*
* @version $Rev$
*/
public class DatabaseHandler {
private static Logger log = Logger.getLogger(DatabaseHandler.class);
private DatabaseManager databaseManager;
/**
* Constructor
* @param idxManager IndexManager - unused param, needed for interface compatibility
* with RpcServer constructing us.
* @param dbMgr DatabaseManager
* Will perform database queries
* @param schedManager ScheduleManager unused param, needed for interface compatibility
* with RpcServer constructing us.
*/
public DatabaseHandler(IndexManager idxManager, DatabaseManager dbMgr,
ScheduleManager schedManager) {
databaseManager = dbMgr;
}
/**
* Search database
*
* @param sessionId
* user's application session id
* @param namespace
* namespace query is located in
* @param query
* search query
* @return list of document ids as results
* @throws XmlRpcFault something bad happened
*/
public List<Result> search(long sessionId, String namespace, String query)
throws XmlRpcFault {
if (log.isDebugEnabled()) {
log.debug("DatabaseHandler:: searching for <" + namespace + ">: " + query);
}
try {
String queryName = getQueryName(query);
Map<String, Object> params = getQueryParams(query);
if (log.isDebugEnabled()) {
log.debug("Calling runQuery(" + sessionId + ", " + namespace +
", " + queryName + ", " + params + ")");
}
List<Result> hits = runQuery(sessionId, namespace, queryName,
params);
log.info("Returned " + hits.size() + " records");
return hits;
}
catch (SQLException e) {
log.warn("Caught SQLException: " + e.getMessage());
e.printStackTrace();
throw new XmlRpcFault(IndexHandler.DB_ERROR, e.getMessage());
}
catch (QueryParseException e) {
log.warn("Caught QueryParseException: " + e.getMessage());
e.printStackTrace();
throw new XmlRpcFault(IndexHandler.QUERY_ERROR, e.getMessage());
}
}
/**
*
* @param queryIn format "name(param1, param2, ....)"
* @return query name from query
* @throws QueryParseException thrown when queryIn is malformed
*/
private String getQueryName(String queryIn) throws QueryParseException {
queryIn = queryIn.trim();
int index = queryIn.indexOf(":(");
if (index < 0) {
throw new QueryParseException("Could not parse query: '" + queryIn + "'");
}
String queryName = queryIn.substring(0, index);
return queryName;
}
/**
*
* @param queryIn String format of "name(param1, param2, ....)"
* @return List of params from query
* @throws QueryParseException thrown when queryIn is malformed
*/
private Map<String, Object> getQueryParams(String queryIn) throws QueryParseException {
queryIn = queryIn.trim();
String delim = ":(";
int index = queryIn.indexOf(delim);
if (index < 0) {
throw new QueryParseException("Could not parse query: '" + queryIn + "'");
}
int indexB = queryIn.indexOf(")", index);
if (indexB < 0) {
throw new QueryParseException("Could not parse query: '" + queryIn + "'");
}
index = index + delim.length() - 1; // We want to be pointed to end of location of
// delim
String[] temps = queryIn.substring(index + delim.length() - 1, indexB).split(",");
Map<String, Object> params = new HashMap<String, Object>();
for (int i = 0; i < temps.length; i++) {
params.put("param" + new Integer(i).toString(), temps[i].trim());
}
return params;
}
/** Will need to generalize this... right now it's specific to Errata only
*
* @param namespace namespace query lives in
* @param queryName query to run
* @param args parameters to the query
* @return List of results
*/
private List<Result> runQuery(Long sessionId, String namespace, String queryName,
Map<String, Object> args)
throws SQLException {
// Look up Query in DB
args.put("sessionId", sessionId);
Query<Result> query = databaseManager.getQuery(queryName);
List<Result> retval;
try {
retval = query.loadList(args);
}
finally {
query.close();
}
return retval;
}
}