View Javadoc

1   /* Copyright (2006-2008) Schibsted Søk AS
2    * This file is part of SESAT.
3    *
4    *   SESAT is free software: you can redistribute it and/or modify
5    *   it under the terms of the GNU Affero General Public License as published by
6    *   the Free Software Foundation, either version 3 of the License, or
7    *   (at your option) any later version.
8    *
9    *   SESAT is distributed in the hope that it will be useful,
10   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   *   GNU Affero General Public License for more details.
13   *
14   *   You should have received a copy of the GNU Affero General Public License
15   *   along with SESAT.  If not, see <http://www.gnu.org/licenses/>.
16  
17   */
18  package no.sesat.search.run;
19  
20  
21  import java.io.IOException;
22  import java.util.Enumeration;
23  import java.util.Hashtable;
24  import java.util.Map;
25  import java.util.Set;
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpServletResponse;
28  import no.sesat.search.datamodel.DataModel;
29  import no.sesat.search.site.SiteKeyedFactoryInstantiationException;
30  import org.apache.commons.lang.StringEscapeUtils;
31  import org.apache.commons.lang.StringUtils;
32  import org.apache.log4j.Logger;
33  
34  /**
35   * @version <tt>$Id: RunningWebQuery.java 6637 2008-05-26 12:07:21Z ssmiweve $</tt>
36   *
37   */
38  public final class RunningWebQuery extends RunningQueryImpl {
39  
40      private static final Logger LOG = Logger.getLogger(RunningWebQuery.class);
41      private static final String ERR_SEND_ERROR = "!!! Unable to sendError !!!";
42  
43      private final HttpServletRequest request;
44      private final HttpServletResponse response;
45  
46  
47      /**
48       * Request attributes that should be added to parameter map. This is needed because request.getAttributeNames()
49       * does not include all attributes passed by mod_jk. http://issues.apache.org/bugzilla/show_bug.cgi?id=25363.
50       */
51      private static final String[] ATTRS_TO_COPY = new String[] {
52              "REMOTE_ADDR"
53      };
54  
55      /**
56       * Request headers to be copied to parameter map.
57       */
58      private static final String[] HEADERS_TO_COPY = new String[] {
59              "user-agent",
60              "x-forwarded-for"
61      };
62  
63      /**
64       *
65       * @param cxt
66       * @param query
67       * @param request
68       * @param response
69       * @throws SiteKeyedFactoryInstantiationException
70       */
71      public RunningWebQuery(final Context cxt,
72                             final String query,
73                             final HttpServletRequest request,
74                             final HttpServletResponse response) throws SiteKeyedFactoryInstantiationException {
75  
76          super(cxt, query);
77  
78          this.request = request;
79          this.response = response;
80  
81          if (LOG.isTraceEnabled()) {
82              LOG.trace("RunningWebQuery(mode, " + query + ", request, response)");
83          }
84  
85          // XXX The rest is redundant code!! stop using junkyard!
86          final Map<String,Object> parameters = datamodel.getJunkYard().getValues();
87  
88          // Add all request parameters
89          /* SEE "Add all request attributes" below */
90  
91          for (String key : datamodel.getParameters().getValues().keySet()) {
92  
93              final String value = datamodel.getParameters().getValue(key).getString();
94              parameters.put(key,  value);
95  
96              if (LOG.isTraceEnabled()) {
97                  LOG.trace("Added " + key + ", value: " + value + ", ");
98              }
99          }
100 
101         // Hack to keep vg site search working. Dependent on old query
102         // parameters. Remove when vg has been reimplented a proper site search.
103         if (parameters.containsKey("nav_newspaperNames")) {
104             parameters.put("nav_newspaperNames", "newssourcenavigator");
105         }
106 
107         if (parameters.containsKey("nav_videosourceNames")) {
108             parameters.put("nav_videosourceNames", "videosourcenavigator");
109         }
110 
111         if (parameters.containsKey("ywpopnavn")) {
112             parameters.put("newssource", parameters.get("ywpopnavn"));
113             parameters.remove("ywpopnavn");
114         }
115 
116         // Add all request attributes (servlet may have added some things already)...
117         for (Enumeration<String> e = (Enumeration<String>)request.getAttributeNames(); e.hasMoreElements();) {
118 
119             final String attrName = e.nextElement();
120             /*
121                 // HACK backwards-compatibility since we never designed for unique names across parameters & attributes
122                 //  any attribute that overlaps a parameter's name won't be added!!
123 
124              * this has now been changed. request parameters are first put into the parameters map and
125              * are overwritten with request attributes. this is a basic attempt to prevent parameter injection.
126              */
127             parameters.put(attrName, request.getAttribute(attrName));
128             if (LOG.isTraceEnabled()) {
129                 LOG.trace("Added " + attrName + ", value: " + request.getAttribute(attrName));
130             }
131         }
132 
133         for (final String attrName : ATTRS_TO_COPY) {
134             if (request.getAttribute(attrName) != null) {
135                 parameters.put(attrName, request.getAttribute(attrName));
136 
137                 if (LOG.isTraceEnabled()) {
138                     LOG.trace("Added(Manually) " + attrName + ", value: " + request.getAttribute(attrName));
139                 }
140             }
141         }
142 
143         for (final String header : HEADERS_TO_COPY) {
144             if (request.getHeader(header) != null) {
145                 parameters.put(header, request.getHeader(header));
146 
147                 if (LOG.isTraceEnabled()) {
148                     LOG.trace("Added HTTP header " + header + ", value: " + request.getHeader(header));
149                 }
150             }
151         }
152 
153         parameters.put("request", request);
154         parameters.put("response", response);
155 
156 
157     }
158 
159     @Override
160     public void run() throws InterruptedException{
161 
162         super.run();
163 
164         if( allCancelled ){
165 
166             try {
167 
168                 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
169             } catch (IOException ex) {
170                 LOG.error(ERR_SEND_ERROR, ex);
171             }
172 
173         }else{
174 
175             // push all parameters into request attributes, they are needed by jsp and taglib
176             for( Map.Entry<String,Object> entry : datamodel.getJunkYard().getValues().entrySet() ){
177                 // don't put back in String array that only contains one element
178                 if( entry.getValue() instanceof String[] && ((String[])entry.getValue()).length ==1 ){
179                     request.setAttribute(entry.getKey(), ((String[])entry.getValue())[0]);
180                 }else{
181                     request.setAttribute(entry.getKey(), entry.getValue());
182                 }
183                 if (LOG.isTraceEnabled()) {
184                     LOG.trace("Added " + entry.getKey() + ", value: " + request.getAttribute(entry.getKey()));
185                 }
186             }
187 
188             // ...and...
189             request.setAttribute("hits",getHits());
190         }
191     }
192 }