001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/search/tags/sakai_2-4-1/search-tool/tool/src/java/org/sakaiproject/search/tool/ControllerServlet2.java $
003: * $Id: ControllerServlet2.java 29315 2007-04-20 14:28:12Z ajpoland@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006, 2007 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.search.tool;
021:
022: import java.io.IOException;
023: import java.util.HashMap;
024: import java.util.Map;
025: import java.util.Properties;
026:
027: import javax.servlet.ServletConfig;
028: import javax.servlet.ServletContext;
029: import javax.servlet.ServletException;
030: import javax.servlet.http.HttpServlet;
031: import javax.servlet.http.HttpServletRequest;
032: import javax.servlet.http.HttpServletResponse;
033:
034: import org.apache.commons.logging.Log;
035: import org.apache.commons.logging.LogFactory;
036: import org.apache.velocity.VelocityContext;
037: import org.apache.velocity.app.VelocityEngine;
038: import org.sakaiproject.exception.PermissionException;
039: import org.sakaiproject.search.tool.api.SearchBeanFactory;
040: import org.sakaiproject.tool.api.SessionManager;
041: import org.sakaiproject.tool.api.Tool;
042: import org.sakaiproject.tool.api.ToolSession;
043: import org.sakaiproject.util.ResourceLoader;
044: import org.springframework.web.context.WebApplicationContext;
045: import org.springframework.web.context.support.WebApplicationContextUtils;
046:
047: /**
048: * @author ieb
049: */
050: public class ControllerServlet2 extends HttpServlet {
051: private static final Log log = LogFactory
052: .getLog(ControllerServlet2.class);
053:
054: private static final String MACROS = "/WEB-INF/vm/macros.vm";
055:
056: private static final String BUNDLE_NAME = "org.sakaiproject.search.tool.bundle.Messages"; //$NON-NLS-1$
057:
058: private static final ResourceLoader rlb = new ResourceLoader(
059: BUNDLE_NAME);
060:
061: /**
062: * Required for serialization... also to stop eclipse from giving me a
063: * warning!
064: */
065: private static final long serialVersionUID = 676743152200357708L;
066:
067: public static final String SAVED_REQUEST_URL = "org.sakaiproject.search.api.last-request-url";
068:
069: private static final String PANEL = "panel";
070:
071: private static final Object TITLE_PANEL = "Title";
072:
073: private WebApplicationContext wac;
074:
075: private SearchBeanFactory searchBeanFactory = null;
076:
077: private SessionManager sessionManager;
078:
079: private Map<String, String> contentTypes = new HashMap<String, String>();
080:
081: private Map<String, String> characterEncodings = new HashMap<String, String>();
082:
083: private VelocityEngine vengine;
084:
085: private String inlineMacros;
086:
087: private String basePath;
088:
089: @Override
090: public void init(ServletConfig servletConfig)
091: throws ServletException {
092: super .init(servletConfig);
093:
094: ServletContext sc = servletConfig.getServletContext();
095:
096: wac = WebApplicationContextUtils.getWebApplicationContext(sc);
097: if (wac == null) {
098: throw new ServletException(
099: "Unable to get WebApplicationContext ");
100: }
101: searchBeanFactory = (SearchBeanFactory) wac
102: .getBean("search-searchBeanFactory");
103: if (searchBeanFactory == null) {
104: throw new ServletException(
105: "Unable to get search-searchBeanFactory ");
106: }
107: sessionManager = (SessionManager) wac
108: .getBean(SessionManager.class.getName());
109: if (sessionManager == null) {
110: throw new ServletException("Unable to get "
111: + SessionManager.class.getName());
112: }
113:
114: searchBeanFactory.setContext(sc);
115:
116: inlineMacros = MACROS;
117: try {
118: vengine = new VelocityEngine();
119:
120: vengine.setApplicationAttribute(ServletContext.class
121: .getName(), sc);
122:
123: Properties p = new Properties();
124: p.load(this .getClass().getResourceAsStream(
125: "searchvelocity.config"));
126: vengine.init(p);
127: vengine.getTemplate(inlineMacros);
128:
129: } catch (Exception ex) {
130: throw new ServletException(ex);
131: }
132: contentTypes.put("opensearch",
133: "application/opensearchdescription+xml");
134: contentTypes.put("sakai.src",
135: "application/opensearchdescription+xml");
136: contentTypes.put("rss20", "text/xml");
137: }
138:
139: protected void doGet(final HttpServletRequest request,
140: HttpServletResponse response) throws ServletException,
141: IOException {
142:
143: execute(request, response);
144: }
145:
146: protected void doPost(HttpServletRequest request,
147: HttpServletResponse response) throws ServletException,
148: IOException {
149: execute(request, response);
150: }
151:
152: public void execute(HttpServletRequest request,
153: HttpServletResponse response) throws ServletException,
154: IOException {
155: request.setAttribute(Tool.NATIVE_URL, Tool.NATIVE_URL);
156:
157: VelocityContext vc = new VelocityContext();
158:
159: String sakaiHeader = (String) request
160: .getAttribute("sakai.html.head");
161: String toolPlacement = (String) request
162: .getAttribute("sakai.tool.placement.id");
163: String toolPlacementJs = toolPlacement.toString().replace('-',
164: 'x');
165: String skin = "default/"; // this could be changed in the future to
166: // make search skin awaire
167:
168: vc.put("skin", skin);
169: vc.put("sakaiheader", sakaiHeader);
170: vc.put("rlb", rlb);
171: vc.put("sakai_tool_placement_id", toolPlacement);
172: vc.put("sakai_tool_placement_id_js", toolPlacementJs);
173:
174: String targetURL = persistState(request);
175: if (targetURL != null && targetURL.trim().length() > 0) {
176: response.sendRedirect(targetURL);
177: return;
178: }
179: String template = null;
180: if (TITLE_PANEL.equals(request.getParameter(PANEL))) {
181: template = "title";
182:
183: } else {
184:
185: String path = request.getPathInfo();
186: if (path == null || path.length() == 0) {
187: path = "index";
188: }
189: if (path.startsWith("/")) {
190: path = path.substring(1);
191: }
192: template = path;
193: }
194: log.debug("Path is " + template + " for "
195: + request.getPathInfo());
196: if ("sakai.gif".equals(template)) {
197: try {
198: searchBeanFactory.newSherlockSearchBean(request)
199: .sendIcon(response);
200: } catch (PermissionException e) {
201: log.warn("Failed to send gif ", e);
202: }
203: return;
204: }
205: try {
206: vc.put("searchModel", searchBeanFactory
207: .newSearchBean(request));
208: } catch (PermissionException e1) {
209: }
210: try {
211: vc.put("adminModel", searchBeanFactory
212: .newSearchAdminBean(request));
213: } catch (PermissionException e1) {
214: }
215: try {
216: vc.put("sherlockModel", searchBeanFactory
217: .newSherlockSearchBean(request));
218: } catch (PermissionException e1) {
219: }
220: try {
221: vc.put("openSearchModel", searchBeanFactory
222: .newOpenSearchBean(request));
223: } catch (PermissionException e1) {
224: }
225: try {
226:
227: String filePath = "/WEB-INF/vm/" + template + ".vm";
228: String contentType = contentTypes.get(template);
229: if (contentType == null) {
230: contentType = "text/html";
231: }
232: String characterEncoding = characterEncodings.get(template);
233: if (characterEncoding == null) {
234: characterEncoding = "UTF-8";
235: }
236:
237: response.setContentType(contentType);
238: response.setCharacterEncoding(characterEncoding);
239: vengine.mergeTemplate(filePath, vc, response.getWriter());
240:
241: request.removeAttribute(Tool.NATIVE_URL);
242: } catch (Exception e) {
243: throw new ServletException("Search Failed ", e);
244: }
245: }
246:
247: public void addLocalHeaders(HttpServletRequest request) {
248: }
249:
250: /**
251: * returns the request state for the tool. If the state is restored, we set
252: * the request attribute RWikiServlet.REQUEST_STATE_RESTORED to Boolean.TRUE
253: * and a Thread local named RWikiServlet.REQUEST_STATE_RESTORED to
254: * Boolean.TRUE. These MUST be checked by anything that modifies state, to
255: * ensure that a reinitialisation of Tool state does not result in a repost
256: * of data.
257: *
258: * @param request
259: * @return
260: */
261: private String persistState(HttpServletRequest request) {
262: ToolSession ts = sessionManager.getCurrentToolSession();
263: if (isPageToolDefault(request)) {
264: log.debug("Incomming URL is "
265: + request.getRequestURL().toString() + "?"
266: + request.getQueryString());
267: log.debug("Restore " + ts.getAttribute(SAVED_REQUEST_URL));
268: return (String) ts.getAttribute(SAVED_REQUEST_URL);
269: }
270: if (isPageRestorable(request)) {
271: ts.setAttribute(SAVED_REQUEST_URL, request.getRequestURL()
272: .toString()
273: + "?" + request.getQueryString());
274: log.debug("Saved " + ts.getAttribute(SAVED_REQUEST_URL));
275: }
276: return null;
277: }
278:
279: /**
280: * Check to see if the reques represents the Tool default page. This is not
281: * the same as the view Home. It is the same as first entry into a Tool or
282: * when the page is refreshed
283: *
284: * @param request
285: * @return true if the page is the Tool default page
286: */
287: private boolean isPageToolDefault(HttpServletRequest request) {
288: if (TITLE_PANEL.equals(request.getParameter(PANEL)))
289: return false;
290: String pathInfo = request.getPathInfo();
291: String queryString = request.getQueryString();
292: String method = request.getMethod();
293: return ("GET".equalsIgnoreCase(method)
294: && (pathInfo == null || request.getPathInfo().length() == 0) && (queryString == null || queryString
295: .length() == 0));
296: }
297:
298: /**
299: * Check to see if the request represents a page that can act as a restor
300: * point.
301: *
302: * @param request
303: * @return true if it is possible to restore to this point.
304: */
305: private boolean isPageRestorable(HttpServletRequest request) {
306:
307: if (TITLE_PANEL.equals(request.getParameter(PANEL)))
308: return false;
309: String pathInfo = request.getPathInfo();
310: if (pathInfo != null) {
311: if (request.getPathInfo().endsWith(".gif")) {
312: return false;
313: }
314: if (request.getPathInfo().endsWith(".src")) {
315: return false;
316: }
317: }
318:
319: if ("GET".equalsIgnoreCase(request.getMethod()))
320: return true;
321:
322: return false;
323: }
324:
325: }
|