/* Copyright (2006-2012) Schibsted ASA
* This file is part of Possom.
*
* Possom is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Possom is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Possom. If not, see <http://www.gnu.org/licenses/>.
*/
package no.sesat.search.run;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import no.sesat.search.site.SiteKeyedFactoryInstantiationException;
import org.apache.log4j.Logger;
/**
* @version <tt>$Id$</tt>
*
*/
public final class RunningWebQuery extends RunningQueryImpl {
private static final Logger LOG = Logger.getLogger(RunningWebQuery.class);
private static final String ERR_SEND_ERROR = "!!! Unable to sendError !!!";
private final HttpServletRequest request;
private final HttpServletResponse response;
/**
* Request attributes that should be added to parameter map. This is needed because request.getAttributeNames()
* does not include all attributes passed by mod_jk. http://issues.apache.org/bugzilla/show_bug.cgi?id=25363.
*/
private static final String[] ATTRS_TO_COPY = new String[] {
"REMOTE_ADDR"
};
/**
* Request headers to be copied to parameter map.
*/
private static final String[] HEADERS_TO_COPY = new String[] {
"user-agent",
"x-forwarded-for"
};
/**
*
* @param cxt
* @param query
* @param request
* @param response
* @throws SiteKeyedFactoryInstantiationException
*/
public RunningWebQuery(final Context cxt,
final String query,
final HttpServletRequest request,
final HttpServletResponse response) throws SiteKeyedFactoryInstantiationException {
super(cxt, query);
this.request = request;
this.response = response;
if (LOG.isTraceEnabled()) {
LOG.trace("RunningWebQuery(mode, " + query + ", request, response)");
}
// XXX The rest is redundant code!! stop using junkyard!
final Map<String,Object> parameters = datamodel.getJunkYard().getValues();
// Add all request parameters
/* SEE "Add all request attributes" below */
for (String key : datamodel.getParameters().getValues().keySet()) {
final String value = datamodel.getParameters().getValue(key).getString();
parameters.put(key, value);
if (LOG.isTraceEnabled()) {
LOG.trace("Added " + key + ", value: " + value + ", ");
}
}
// Hack to keep vg site search working. Dependent on old query
// parameters. Remove when vg has been reimplented a proper site search.
if (parameters.containsKey("nav_newspaperNames")) {
parameters.put("nav_newspaperNames", "newssourcenavigator");
}
if (parameters.containsKey("nav_videosourceNames")) {
parameters.put("nav_videosourceNames", "videosourcenavigator");
}
if (parameters.containsKey("ywpopnavn")) {
parameters.put("newssource", parameters.get("ywpopnavn"));
parameters.remove("ywpopnavn");
}
// Add all request attributes (servlet may have added some things already)...
for (Enumeration<String> e = (Enumeration<String>)request.getAttributeNames(); e.hasMoreElements();) {
final String attrName = e.nextElement();
/*
// HACK backwards-compatibility since we never designed for unique names across parameters & attributes
// any attribute that overlaps a parameter's name won't be added!!
* this has now been changed. request parameters are first put into the parameters map and
* are overwritten with request attributes. this is a basic attempt to prevent parameter injection.
*/
parameters.put(attrName, request.getAttribute(attrName));
if (LOG.isTraceEnabled()) {
LOG.trace("Added " + attrName + ", value: " + request.getAttribute(attrName));
}
}
for (final String attrName : ATTRS_TO_COPY) {
if (request.getAttribute(attrName) != null) {
parameters.put(attrName, request.getAttribute(attrName));
if (LOG.isTraceEnabled()) {
LOG.trace("Added(Manually) " + attrName + ", value: " + request.getAttribute(attrName));
}
}
}
for (final String header : HEADERS_TO_COPY) {
if (request.getHeader(header) != null) {
parameters.put(header, request.getHeader(header));
if (LOG.isTraceEnabled()) {
LOG.trace("Added HTTP header " + header + ", value: " + request.getHeader(header));
}
}
}
parameters.put("request", request);
parameters.put("response", response);
}
@Override
public void run() throws InterruptedException{
super.run();
if( isAllCancelled() ){
try {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} catch (IOException ex) {
LOG.error(ERR_SEND_ERROR, ex);
}
}else{
// push all parameters into request attributes, they are needed by jsp and taglib
for( Map.Entry<String,Object> entry : datamodel.getJunkYard().getValues().entrySet() ){
// don't put back in String array that only contains one element
if( entry.getValue() instanceof String[] && ((String[])entry.getValue()).length ==1 ){
request.setAttribute(entry.getKey(), ((String[])entry.getValue())[0]);
}else{
request.setAttribute(entry.getKey(), entry.getValue());
}
if (LOG.isTraceEnabled()) {
LOG.trace("Added " + entry.getKey() + ", value: " + request.getAttribute(entry.getKey()));
}
}
// ...and...
request.setAttribute("hits",getHits());
}
}
}