/* * Created on Nov 22, 2004 * Copyright (C) Andrea Schweer, 2004 * * This file is part of the Greenstone Alerting Service. * Refer to the COPYING file in the base directory of this package * for licensing information. */ package org.greenstone.gsdlas; import java.lang.reflect.Method; import java.net.URL; import java.sql.SQLException; import java.util.*; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.*; import org.apache.velocity.Template; import org.apache.velocity.context.Context; import org.apache.velocity.servlet.VelocityServlet; import org.greenstone.gsdlas.database.DatabaseException; import org.greenstone.gsdlas.profiles.Predicate; import org.greenstone.gsdlas.profiles.Subscription; import org.greenstone.gsdlas.users.UserManagementException; import org.greenstone.gsdlas.users.UserManager; import org.greenstone.gsdlas.util.ArrayHelper; /** * @author schweer * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class AlertingService extends VelocityServlet { /* (non-Javadoc) * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) */ public void init(ServletConfig config) throws ServletException { super.init(config); System.out.println("reloading subs"); ProfileStore.getInstance().restoreFromDatabase(); try { Set subs = ProfileStore.getInstance().getAllSubscriptionsFor("andrea"); System.out.println("reloaded " + subs.size() + " subs for andrea: "); for (Iterator iter = subs.iterator(); iter.hasNext();) { System.out.println(iter.next()); } } catch (DatabaseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static final String[] actions = new String[] { "createSubscription", "deleteSubscription", "editSubscription", "showEvents", "showFeed", "listSubscriptions", "login", "register", "logout", "showLoginForm", "showRegistrationForm" }; protected Template handleRequest(HttpServletRequest req, HttpServletResponse res, Context context) { String action = req.getParameter(Constants.ACTION_PARAM); Map args = req.getParameterMap(); if (action != null && action.equals("receiveEvent")) { receiveEvent(args); return null; } args = normalise(args); if (action == null || !ArrayHelper.contains(actions, action)) { String title = "Unknown action"; String message = "I don't know how to " + action; String details = "The only actions I know are " + Arrays.toString(actions); return showError(context, message, details); } String templateString = ""; try { Method method = AlertingService.class.getDeclaredMethod(action, new Class[] {Map.class, Context.class}); templateString = (String) method.invoke(this, new Object[] {args, context}); } catch (Exception e) { String message = "An error has occured, I couldn't do what you told me to do."; String details = e.getMessage() + " (" + e.getClass().getName() + "); " + e.getCause() + " ; action is " + action; return showError(context, message, details); } Template template = null; try { template = getTemplate(templateString); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); try { error((HttpServletRequest)context.get(REQUEST), (HttpServletResponse)context.get(RESPONSE), e); } catch (Exception e2) { // TODO Auto-generated catch block e2.printStackTrace(); } } return template; } /** * @param arguments * @param context * @return the Velocity template to use * @throws Exception */ public String createSubscription(Map arguments, Context context) throws Exception { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); if (!UserManager.getInstance().isLoggedIn(session)) { session.setAttribute("next_action", "createSubscription"); return showLoginForm(arguments, context); } if (arguments.containsKey("next_page") && arguments.get("next_page").equals("finish")) { arguments.putAll(getPageArgsFromSession(session)); arguments.put("username", session.getAttribute("username")); ProfileStore.getInstance().createSubscription(arguments); return listSubscriptions(arguments, context); } else { return showSubscriptionWizardPage(arguments, context, true); } } public String deleteSubscription(Map arguments, Context context) { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); if (!UserManager.getInstance().isLoggedIn(session)) { session.setAttribute("next_action", "deleteSubscription"); return showLoginForm(arguments, context); } String subscriptionID = (String) arguments.get("subscriptionID"); try { ProfileStore.getInstance().deleteSubscription(subscriptionID); } catch (DatabaseException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return listSubscriptions(arguments, context); } public String editSubscription(Map arguments, Context context) throws Exception { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); if (!UserManager.getInstance().isLoggedIn(session)) { session.setAttribute("next_action", "editSubscription"); return showLoginForm(arguments, context); } if (arguments.containsKey("next_page") && arguments.get("next_page").equals("finish")) { ProfileStore.getInstance().changeSubscription(arguments, session); return listSubscriptions(arguments, context); } else { return showSubscriptionWizardPage(arguments, context, false); } } public String showFeed(Map arguments, Context context) throws NumberFormatException, DatabaseException, SQLException { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); if (!UserManager.getInstance().isLoggedIn(session)) { session.setAttribute("next_action", "showFeed"); return showLoginForm(arguments, context); } String subscriptionID = (String) arguments.get("subscriptionID"); Integer subID = new Integer(subscriptionID); Set events = EventStore.getInstance().getEvents(subID); context.put("list", events); context.put("subscription", ProfileStore.getInstance().getSubscription(subID.intValue())); HttpServletResponse res = (HttpServletResponse) context.get(RESPONSE); res.setContentType("text/xml"); return "feed.vm"; } public String showEvents(Map arguments, Context context) throws NumberFormatException, DatabaseException, SQLException { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); if (!UserManager.getInstance().isLoggedIn(session)) { session.setAttribute("next_action", "showEvents"); return showLoginForm(arguments, context); } String subscriptionID = (String) arguments.get("subscriptionID"); Integer subID = new Integer(subscriptionID); Set events = EventStore.getInstance().getEvents(subID); context.put("list", events); context.put("subscription", ProfileStore.getInstance().getSubscription(subID.intValue())); return "events.vm"; } public String showLoginForm(Map arguments, Context context) { return "login.vm"; } public String showRegistrationForm(Map arguments, Context context) { return "register.vm"; } public String listSubscriptions(Map arguments, Context context) { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); if (!UserManager.getInstance().isLoggedIn(session)) { session.setAttribute("next_action", "listSubscriptions"); return showLoginForm(arguments, context); } String username = (String) session.getAttribute("username"); context.put("title", "List of Subscriptions for " + username); try { Collection subscriptions = ProfileStore.getInstance().getAllSubscriptionsFor(username); context.put("list", subscriptions); return "list.vm"; } catch (DatabaseException de) { context.put("message", "couldn't get list of subscriptions for " + username); context.put("details", de.getMessage()); return "error.vm"; } } public String login(Map arguments, Context context) throws Exception { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); try { UserManager.getInstance().loginUser(arguments, session); } catch (UserManagementException e) { context.put("error", Boolean.TRUE); context.put("errormessage", e.getMessage()); return showLoginForm(arguments, context); } if (session.getAttribute("next_action") != null) { String nextAction = (String) session.getAttribute("next_action"); Method method = AlertingService.class.getDeclaredMethod(nextAction, new Class[] {Map.class, Context.class}); return (String) method.invoke(this, new Object[] {arguments, context}); } return listSubscriptions(arguments, context); } public String register(Map arguments, Context context) throws Exception { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); try { UserManager.getInstance().createUser(arguments, session); } catch (UserManagementException e) { context.put("error", Boolean.TRUE); context.put("errormessage", e.getMessage()); return showRegistrationForm(arguments, context); } return login(arguments, context); } public String logout(Map arguments, Context context) { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); Enumeration atts = session.getAttributeNames(); while (atts.hasMoreElements()) { session.removeAttribute((String) atts.nextElement()); } session.invalidate(); return "general.vm"; } public void receiveEvent(Map rawEvent) { Map event = new TreeMap(); for (Iterator iter = rawEvent.keySet().iterator(); iter.hasNext();) { String key = (String) iter.next(); if (key.equals("action")) continue; // we don't want this String[] value = (String[]) rawEvent.get(key); event.put(key, value[0]); } System.out.println("receiving event " + event); GreenstoneCommunicator gsComm = null; try { String hostID = (String) event.get(Constants.HOST_ID_FIELD); gsComm = new GreenstoneCommunicator(new URL(hostID)); } catch (Exception e) { System.err.println("Can't communicate to Greenstone: " + e.getMessage()); e.printStackTrace(); } Set matchedSubscriptions = ProfileStore.getInstance().filter(event, gsComm); try { EventStore.getInstance().add(event, matchedSubscriptions); Notifier.getInstance().sendNotifications(event, matchedSubscriptions); } catch (Exception e) { System.err.println("Couldn't save events: " + e.getMessage()); e.printStackTrace(); } System.out.println(matchedSubscriptions.size() + " matching subscriptions: " + matchedSubscriptions); } /** * @param args */ private Map normalise(Map args) { Map result = new TreeMap(); for (Iterator iter = args.keySet().iterator(); iter.hasNext();) { String key = (String) iter.next(); if (Predicate.isMultiValued(key) || key.equals("way")) { // multi-valued attributes String[] values = ((String[]) args.get(key)); result.put(key, Arrays.asList(values)); } else { String firstValue = ((String[])args.get(key))[0]; result.put(key, firstValue); } } return result; } /** * @param context * @param message * @param details * @return */ private Template showError(Context context, String message, String details) { context.put("title", "Error"); context.put("message", message); context.put("details", details); try { return getTemplate("error.vm"); } catch (Exception e) { try { super.error((HttpServletRequest)context.get("req"), (HttpServletResponse)context.get("res"), e); } catch (Exception e2) { e2.printStackTrace(); } } return null; } /** * @param arguments * @param context * @param create * @return * @throws Exception */ private String showSubscriptionWizardPage(Map arguments, Context context, boolean create) throws Exception { HttpSession session = ((HttpServletRequest)context.get(REQUEST)).getSession(true); if (create) { context.put(Constants.ACTION_PARAM, "createSubscription"); } else { // prefill from existing subscription context.put(Constants.ACTION_PARAM, "editSubscription"); String subscriptionID = (String) arguments.get("subscriptionID"); int subID = Integer.parseInt(subscriptionID); prefillFromSubscription(session, subID); } if (!arguments.containsKey("current_page")) { return "sub_type-details.vm"; } String currentPage = (String) arguments.get("current_page"); String direction = (String) arguments.get("next_page"); if (arguments.containsKey(Constants.HOST_QUERY_FIELD)) { String hostQuery = (String) arguments.get(Constants.HOST_QUERY_FIELD); if (hostQuery != null && hostQuery.length() != 0) arguments.remove(Constants.HOST_ID_FIELD); } if (arguments.containsKey(Constants.COLLECTION_QUERY_FIELD)) { String collQuery = (String) arguments.get(Constants.COLLECTION_QUERY_FIELD); if (collQuery != null && collQuery.length() != 0) arguments.remove(Constants.COLLECTION_ID_FIELD); } // save page arguments savePageArgsToSession(currentPage, arguments, session); String nextPage = getNextPage(currentPage, direction); // fill prefill context.put("prefill", getPageArgsFromSession(nextPage, session)); // fill preview context.put("preview", getPagePreview(nextPage, session)); // get page-specific stuff if (nextPage.equals("host")) { String[] hostNames; try { GreenstoneCommunicator gsComm = new GreenstoneCommunicator(); hostNames = gsComm.getHostNames(); } catch (Exception e) { hostNames = new String[] { "localhost" }; } context.put("hostnames", hostNames); session.setAttribute("hostnames", hostNames); } else if (nextPage.equals("collection")) { List hostNames = (List) arguments.get(Constants.HOST_ID_FIELD); if (hostNames == null || hostNames.isEmpty()) { hostNames = new Vector(); // no host names -> use host query String[] hostsFromSession = (String[]) session.getAttribute("hostnames"); if (hostsFromSession == null || hostsFromSession.length == 0) { try { GreenstoneCommunicator gsComm = new GreenstoneCommunicator(); hostsFromSession = gsComm.getHostNames(); } catch (Exception e) { hostsFromSession = new String[] { "localhost" }; } } String hostQuery = (String) arguments.get(Constants.HOST_QUERY_FIELD); for (int i = 0; i < hostsFromSession.length; i++) { if (hostsFromSession[i] != null && hostsFromSession[i].indexOf(hostQuery) >= 0) { hostNames.add(hostsFromSession[i]); } } } Map collNames = new TreeMap(); for (Iterator iter = hostNames.iterator(); iter.hasNext();) { String host = (String) iter.next(); Set collNamesForHost = new TreeSet(); try { URL url = new URL("http://" + host + ":8080/soap/servlet/rpcrouter"); GreenstoneCommunicator gsComm = new GreenstoneCommunicator(url); collNamesForHost.addAll(Arrays.asList(gsComm.getCollectionNames())); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } collNames.put(host, collNamesForHost); } context.put("collectionnames", collNames); context.put("hostnames", hostNames); } return "sub_" + nextPage + ".vm"; } /** * @param session * @param subID */ private void prefillFromSubscription(HttpSession session, int subID) { Subscription sub = ProfileStore.getInstance().getSubscription(subID); Map typeArgs = new HashMap(); // TODO really fill stuff savePageArgsToSession("type-details", typeArgs, session); Map hostArgs = new HashMap(); savePageArgsToSession("host", hostArgs, session); Map collArgs = new HashMap(); savePageArgsToSession("collection", collArgs, session); Map notificationArgs = new HashMap(); savePageArgsToSession("notification", notificationArgs, session); } /** * @param nextPage * @param session * @return */ private Map getPagePreview(String nextPage, HttpSession session) { Map preview = new TreeMap(); if (nextPage.equals("type-details")) { return preview; } preview.putAll(getPageArgsFromSession("type-details", session)); if (nextPage.equals("host")) { return preview; } preview.putAll(getPageArgsFromSession("host", session)); if (nextPage.equals("collection")) { return preview; } preview.putAll(getPageArgsFromSession("collection", session)); return preview; } /** * @param currentPage * @param direction * @return * @throws Exception */ private String getNextPage(String currentPage, String direction) throws Exception { String nextPage; if (currentPage.equals("host") && direction.equals("back")) { nextPage = "type-details"; } else if (currentPage.equals("type-details") || (currentPage.equals("collection") && direction.equals("back"))) { nextPage = "host"; } else if (currentPage.equals("host") || (currentPage.equals("notification") && direction.equals("back"))) { nextPage = "collection"; } else if (currentPage.equals("collection")) { nextPage = "notification"; } else { throw new Exception("unknown combination of currentPage=" + currentPage + " and nextPage=" + direction); } return nextPage; } /** * @param page * @param session * @return */ private Map getPageArgsFromSession(String page, HttpSession session) { Map pageArgs = (Map) session.getAttribute("page_args"); if (pageArgs == null || !pageArgs.containsKey(page)) return new TreeMap(); return (Map) pageArgs.get(page); } private Map getPageArgsFromSession(HttpSession session) { Map result = new TreeMap(); Map pageArgs = (Map) session.getAttribute("page_args"); if (pageArgs != null) { for (Iterator iter = pageArgs.values().iterator(); iter.hasNext();) { Map args = (Map) iter.next(); result.putAll(args); } } return result; } /** * @param page * @param arguments * @param session */ private void savePageArgsToSession(String page, Map arguments, HttpSession session) { Map pageArgs = (Map) session.getAttribute("page_args"); if (pageArgs == null) { pageArgs = new TreeMap(); } pageArgs.put(page, arguments); session.setAttribute("page_args", pageArgs); } }