/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/courier/trunk/courier-tool/tool/src/java/org/sakaiproject/courier/tool/CourierTool.java $ * $Id: CourierTool.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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 org.sakaiproject.courier.tool; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Vector; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.courier.api.Delivery; import org.sakaiproject.courier.api.DeliveryProvider; import org.sakaiproject.courier.cover.CourierService; import org.sakaiproject.courier.cover.PresenceUpdater; import org.sakaiproject.thread_local.cover.ThreadLocalManager; import org.sakaiproject.tool.api.Session; import org.sakaiproject.tool.api.SessionManager; /** * <p> * CourierTool is a "tool" which handles courier requests and delivers courier deliveries. * </p> */ public class CourierTool extends HttpServlet { /** Our log (commons). */ private static Log M_log = LogFactory.getLog(CourierTool.class); private SessionManager sessionManager = (SessionManager) ComponentManager.get(SessionManager.class); /** * Shutdown the servlet. */ public void destroy() { M_log.info("destroy()"); super.destroy(); } /** * Respond to access requests. * * @param req * The servlet request. * @param res * The servlet response. * @throws ServletException. * @throws IOException. */ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // support two "/" separated parameters [1] and [2]) - both get presence updated, the first is the address for delivery (second optional) String[] parts = req.getPathInfo().split("/"); if ((parts.length == 2) || (parts.length == 3)) { String placementId = parts[1]; // if we are in a newly created session where we had an invalid (presumed timed out) session in the request, // send script to cause a sakai top level redirect if (ThreadLocalManager.get(SessionManager.CURRENT_INVALID_SESSION) != null) { String loggedOutUrl = ServerConfigurationService.getLoggedOutUrl(); if (M_log.isDebugEnabled()) M_log.debug("sending top redirect: " + placementId + " : " + loggedOutUrl); sendTopRedirect(res, loggedOutUrl); } else { String requestUserId = req.getParameter("userId"); Session session = sessionManager.getCurrentSession(); if (requestUserId == null || requestUserId.equals(session.getUserId())) { // compute our courier delivery address: this placement in this session String deliveryId = session.getId() + placementId; // find all deliveries for the requested deivery address List deliveries = CourierService.getDeliveries(deliveryId); // see if any DeliveryProviders have deliveries List<DeliveryProvider> providers = CourierService.getDeliveryProviders(); if(providers != null) { List<Delivery> moreDeliveries = new ArrayList<Delivery>(); for(DeliveryProvider provider : providers) { List<Delivery> d = provider.getDeliveries(session.getId(), placementId); if(d != null && ! d.isEmpty()) { moreDeliveries.addAll(d); } } if(moreDeliveries.isEmpty()) { // use deliveries } else if (deliveries.isEmpty()) { deliveries = moreDeliveries; } else { // both lists have deliveries, so add moreDeliveries to deliveries deliveries.addAll(moreDeliveries); } } // form the reply sendDeliveries(res, deliveries); // refresh our presence at the location (placement) if (M_log.isDebugEnabled()) M_log.debug("setting presence: " + placementId); PresenceUpdater.setPresence(placementId); // register another presence if present if (parts.length == 3) { String secondPlacementId = parts[2]; if (M_log.isDebugEnabled()) M_log.debug("setting second presence: " + secondPlacementId); PresenceUpdater.setPresence(secondPlacementId); } } else { //This courier request was not meant for this user (i.e., session), so we won't honour it M_log.debug("out-of-session courier request: requestUserId=" + requestUserId + " session user=" + session.getUserId()); } } } // otherwise this is a bad request! else { M_log.warn("bad courier request: " + req.getPathInfo()); sendDeliveries(res, new Vector()); } } /** * Access the Servlet's information display. * * @return servlet information. */ public String getServletInfo() { return "Sakai Courier Tool"; } /** * Initialize the servlet. * * @param config * The servlet config. * @throws ServletException */ public void init(ServletConfig config) throws ServletException { super.init(config); M_log.info("init()"); } /** * Send any deliveries, or at least something javascrip eval()'able. * * @param res * @param deliveries * The list (possibly empty) of deliveries * @throws IOException */ protected void sendDeliveries(HttpServletResponse res, List deliveries) throws IOException { res.setContentType("text/plain; charset=UTF-8"); res.addDateHeader("Expires", System.currentTimeMillis() - (1000L * 60L * 60L * 24L * 365L)); res.addDateHeader("Last-Modified", System.currentTimeMillis()); res.addHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"); res.addHeader("Pragma", "no-cache"); // get the writer PrintWriter out = res.getWriter(); for (Iterator i = deliveries.iterator(); i.hasNext();) { Delivery d = (Delivery) i.next(); String s = d.compose(); if (M_log.isDebugEnabled()) M_log.debug("sending delivery: " + s); out.println(s); } // make sure we send something if (deliveries.isEmpty()) { String s = "//"; if (M_log.isDebugEnabled()) M_log.debug("sending delivery: " + s); out.println(s); } } /** * Send a redirect so our "top" ends up at the url, via javascript. * * @param url * The redirect url */ protected void sendTopRedirect(HttpServletResponse res, String url) throws IOException { res.setContentType("text/plain; charset=UTF-8"); res.addDateHeader("Expires", System.currentTimeMillis() - (1000L * 60L * 60L * 24L * 365L)); res.addDateHeader("Last-Modified", System.currentTimeMillis()); res.addHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"); res.addHeader("Pragma", "no-cache"); // get the writer PrintWriter out = res.getWriter(); // we are on deep under the main portal window out.println("parent.location.replace('" + url + "');"); } }