/* * BerryBasket.java * Copyright (C) 2006 New Zealand Digital Library, http://www.nzdl.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.greenstone.gsdl3.service; import java.sql.Statement; import java.util.Hashtable; import java.util.HashMap; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.greenstone.util.GlobalProperties; import org.greenstone.gsdl3.util.GSXML; import org.greenstone.gsdl3.util.GSPath; import org.greenstone.gsdl3.util.UserContext; import org.greenstone.gsdl3.util.XMLConverter; import java.io.Serializable; import java.net.InetAddress; import java.util.Properties; import java.util.Date; import javax.mail.*; import javax.mail.internet.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Timer; import org.apache.log4j.*; public class BerryBasket extends ServiceRack { static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.BerryBasket.class.getName()); // the services on offer // these strings must match what is found in the properties file protected static final String ADD_ITEM_SERVICE = "AddItem"; protected static final String DISPLAY_ITEMS_SERVICE = "DisplayList"; protected static final String ITEM_NUM_SERVICE = "ItemNum"; protected static final String DELETE_ITEMS_SERVICE = "DeleteItems"; protected static final String SEND_MAIL_SERVICE = "SendMail"; //protected static final String DELETE_ITEM_SERVICE = "DeleteItem"; // for AddItem protected static final String ITEM_PARAM = "item"; // for DeleteItems protected static final String ITEMS_PARAM = "items"; // for SendMail protected static final String ADDRESS_PARAM = "address"; protected static final String SUBJECT_PARAM = "subject"; protected static final String CONTENT_PARAM = "content"; protected static final String CC_PARAM = "cc"; protected static final String BCC_PARAM = "bcc"; protected static final String delimiter = "|"; protected static final int delay = 1800000; protected Hashtable>> userMap = null; protected Hashtable timerMap = null; protected String username = ""; protected String password = ""; HashSet meta_names = null; /** constructor */ public BerryBasket() { userMap = new Hashtable>>(); timerMap = new Hashtable(); } private Hashtable> updateDocMap(Element request) { UserContext userContext = new UserContext(request); String id = null; String user_name =userContext.getUsername(); if (user_name == null || user_name.equals("")) { id = userContext.getUserID(); } else { id = user_name; } if (userMap.containsKey(id)) { if (timerMap.containsKey(id)) { UserTimer timer = timerMap.get(id); timer.restart(); } return userMap.get(id); } else { UserTimer timer = new UserTimer(delay, id); timerMap.put(id, timer); timer.start(); Hashtable> newDocs = new Hashtable>(); userMap.put(id, newDocs); return newDocs; } } /** configure this service */ public boolean configure(Element info, Element extra_info) { logger.info("Configuring BerryBasket..."); this.config_info = info; // set up short_service_info_ - for now just has name and type Element add_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM); add_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? add_service.setAttribute(GSXML.NAME_ATT, ADD_ITEM_SERVICE); this.short_service_info.appendChild(add_service); // set up short_service_info_ - for now just has name and type Element disp_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM); disp_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? disp_service.setAttribute(GSXML.NAME_ATT, DISPLAY_ITEMS_SERVICE); this.short_service_info.appendChild(disp_service); // set up short_service_info_ - for now just has name and type Element num_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM); num_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? num_service.setAttribute(GSXML.NAME_ATT, ITEM_NUM_SERVICE); this.short_service_info.appendChild(num_service); // set up short_service_info_ - for now just has name and type Element delete_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM); delete_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? delete_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEMS_SERVICE); this.short_service_info.appendChild(delete_service); // set up short_service_info_ - for now just has name and type // Element deleteone_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM); // deleteone_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? // deleteone_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEM_SERVICE); // this.short_service_info.appendChild(deleteone_service); // set up short_service_info_ - for now just has name and type Element mail_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM); mail_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? mail_service.setAttribute(GSXML.NAME_ATT, SEND_MAIL_SERVICE); this.short_service_info.appendChild(mail_service); // set up the metadata names - this is the list of metadata retrieved for each item in the berry basket. meta_names = new HashSet(); meta_names.add("Title"); // the default meta_names.add("root_Title"); meta_names.add("Date"); meta_names.add("root_assocfilepath"); // these two needed for source linking meta_names.add("root_srclinkFile"); // are there any custom ones in the config file? Element meta_list_elem = (Element) GSXML.getChildByTagName(info, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER); if (meta_list_elem !=null) { NodeList meta_list = meta_list_elem.getElementsByTagName(GSXML.METADATA_ELEM); for (int i = 0; i < meta_list.getLength(); i++) { Element s = (Element) meta_list.item(i); meta_names.add(s.getAttribute(GSXML.NAME_ATT)); } } // if any params should be saved in the session, add them to save_params here // this.save_params.add(XXX_PARAM); return true; } /** returns a specific service description */ protected Element getServiceDescription(Document doc, String service_id, String lang, String subset) { if (service_id.equals(ADD_ITEM_SERVICE)) { Element add_service = doc.createElement(GSXML.SERVICE_ELEM); add_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? add_service.setAttribute(GSXML.NAME_ATT, ADD_ITEM_SERVICE); return add_service; } if (service_id.equals(DISPLAY_ITEMS_SERVICE)) { Element disp_service = doc.createElement(GSXML.SERVICE_ELEM); disp_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? disp_service.setAttribute(GSXML.NAME_ATT, DISPLAY_ITEMS_SERVICE); return disp_service; } if (service_id.equals(ITEM_NUM_SERVICE)) { Element num_service = doc.createElement(GSXML.SERVICE_ELEM); num_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? num_service.setAttribute(GSXML.NAME_ATT, ITEM_NUM_SERVICE); return num_service; } if (service_id.equals(DELETE_ITEMS_SERVICE)) { Element del_service = doc.createElement(GSXML.SERVICE_ELEM); del_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? del_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEMS_SERVICE); return del_service; } // if (service_id.equals(DELETE_ITEM_SERVICE)) // { // Element delone_service = doc.createElement(GSXML.SERVICE_ELEM); // delone_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? // delone_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEM_SERVICE); // return delone_service; // } if (service_id.equals(SEND_MAIL_SERVICE)) { Element mail_service = doc.createElement(GSXML.SERVICE_ELEM); mail_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what?? mail_service.setAttribute(GSXML.NAME_ATT, SEND_MAIL_SERVICE); return mail_service; } return null; } protected Element processAddItem(Element request) { Hashtable> docsMap = updateDocMap(request); // Create a new (empty) result message Document result_doc = XMLConverter.newDOM(); Element result = result_doc.createElement(GSXML.RESPONSE_ELEM); // Get the parameters of the request Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER); if (param_list == null) { logger.error("BerryBasket Error: AddItem request had no paramList."); return result; // Return the empty result } HashMap params = GSXML.extractParams(param_list, false); String item = (String) params.get(ITEM_PARAM); String collection = ""; int pos = item.indexOf(":"); if (pos != -1) { collection = item.substring(0, pos); item = item.substring(pos + 1); } if (docsMap.containsKey(collection)) { Hashtable items = docsMap.get(collection); if (!items.containsKey(item)) { Item newItem = generateItem(collection, item); items.put(item, newItem); result.appendChild(newItem.wrapIntoElement(result_doc)); } } else { Hashtable items = new Hashtable(); Item newItem = generateItem(collection, item); items.put(item, newItem); docsMap.put(collection, items); result.appendChild(newItem.wrapIntoElement(result_doc)); } return result; } private Item generateItem(String collection, String id) { Item item = new Item(collection, id); String to = GSPath.appendLink(collection, "DocumentMetadataRetrieve"); ArrayList tmp = new ArrayList(); tmp.add(id); UserContext userContext = new UserContext(); userContext.setLanguage("en"); userContext.setUserID("dumy"); Element response = getDocumentMetadata(to, userContext, tmp.iterator()); Element doc_node = (Element) response.getElementsByTagName(GSXML.DOC_NODE_ELEM).item(0); String node_id = doc_node.getAttribute(GSXML.NODE_ID_ATT); Element metadata_list = (Element) doc_node.getElementsByTagName(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER).item(0); NodeList meta_elems = metadata_list.getElementsByTagName(GSXML.METADATA_ELEM); for (int i=0; i> docsMap = updateDocMap(request); // Create a new (empty) result message Document result_doc = XMLConverter.newDOM(); Element result = result_doc.createElement(GSXML.RESPONSE_ELEM); // Get the parameters of the request Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER); if (param_list == null) { logger.error("BerryBasket Error: DeleteItem request had no paramList."); return result; // Return the empty result } HashMap params = GSXML.extractParams(param_list, false); String param = (String) params.get(ITEMS_PARAM); if (param == null) return result; String[] items = param.split("\\|"); for (int i = 0; i < items.length; i++) { String item = items[i]; if (item.trim().length() == 0) continue; String collection = ""; int pos = item.indexOf(":"); if (pos != -1) { collection = item.substring(0, pos); item = item.substring(pos + 1); } if (docsMap.containsKey(collection)) { Hashtable itemMap = docsMap.get(collection); if (itemMap.containsKey(item)) { itemMap.remove(item); } if (itemMap.size() == 0) { docsMap.remove(collection); } } } return result; } protected Element processItemNum(Element request) { Hashtable> docsMap = updateDocMap(request); // Create a new (empty) result message Document result_doc = XMLConverter.newDOM(); Element result = result_doc.createElement(GSXML.RESPONSE_ELEM); int size = 0; String ids = ""; Iterator keys = docsMap.keySet().iterator(); while (keys.hasNext()) { Hashtable items = docsMap.get(keys.next()); size += items.size(); Iterator values = items.values().iterator(); while (values.hasNext()) { Item item = (Item) values.next(); result.appendChild(item.wrapIntoElement(result_doc)); } } Element selement = result_doc.createElement("size"); selement.setAttribute("value", size + ""); result.appendChild(selement); return result; } private Element getDocumentMetadata(String to, UserContext userContext, Iterator ids) { // Build a request to obtain some document metadata Document doc = XMLConverter.newDOM(); Element dm_message = doc.createElement(GSXML.MESSAGE_ELEM); Element dm_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, to, userContext); dm_message.appendChild(dm_request); // Create a parameter list to specify the required metadata information Element param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER); Element param = null; Iterator i = meta_names.iterator(); while (i.hasNext()) { String name = i.next(); param = doc.createElement(GSXML.PARAM_ELEM); param_list.appendChild(param); param.setAttribute(GSXML.NAME_ATT, "metadata"); param.setAttribute(GSXML.VALUE_ATT, name); } dm_request.appendChild(param_list); // create the doc node list for the metadata request Element dm_doc_list = doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER); dm_request.appendChild(dm_doc_list); while (ids.hasNext()) { // Add the documentNode to the list Element dm_doc_node = doc.createElement(GSXML.DOC_NODE_ELEM); dm_doc_list.appendChild(dm_doc_node); dm_doc_node.setAttribute(GSXML.NODE_ID_ATT, ids.next()); } return (Element) this.router.process(dm_message); } protected Element processDisplayList(Element request) { Hashtable> docsMap = updateDocMap(request); // Create a new (empty) result message Document result_doc = XMLConverter.newDOM(); Element result = result_doc.createElement(GSXML.RESPONSE_ELEM); Iterator keys = docsMap.keySet().iterator(); while (keys.hasNext()) { String collection = keys.next(); Hashtable items = docsMap.get(collection); Iterator itemItr = items.values().iterator(); Element collectionNode = result_doc.createElement("berryList"); collectionNode.setAttribute("name", collection); result.appendChild(collectionNode); while (itemItr.hasNext()) { Item item = (Item) itemItr.next(); collectionNode.appendChild(item.wrapIntoElement(result_doc)); } } return result; } public Element processSendMail(Element request) { // Create a new (empty) result message Document result_doc = XMLConverter.newDOM(); Element result = result_doc.createElement(GSXML.RESPONSE_ELEM); // Get the parameters of the request Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER); if (param_list == null) { logger.error("BerryBasket Error: SendMail request had no paramList."); return result; // Return the empty result } HashMap params = GSXML.extractParams(param_list, false); String to = (String) params.get(ADDRESS_PARAM); String subject = (String) params.get(SUBJECT_PARAM); String content = (String) params.get(CONTENT_PARAM); String cc = (String) params.get(CC_PARAM); String bcc = (String) params.get(BCC_PARAM); String mailhost = GlobalProperties.getProperty("mail.smtp.host"); username = GlobalProperties.getProperty("mail.smtp.username"); password = GlobalProperties.getProperty("mail.smtp.password"); String from = GlobalProperties.getProperty("mail.from"); String port = GlobalProperties.getProperty("mail.smtp.port"); String mail_security = GlobalProperties.getProperty("mail.security"); String mailer = "msgsend"; try { Properties props = System.getProperties(); //Setup smtp host and from address // XXX - could use Session.getTransport() and Transport.connect() // XXX - assume we're using SMTP if (mailhost != null && !mailhost.trim().equals("")) { props.put("mail.smtp.host", mailhost); } else { props.put("mail.smtp.host", "localhost"); } if (from != null && !from.trim().equals("")) { props.put("mail.from", from); } if (port != null && !port.trim().equals("")) { props.put("mail.smtp.port", port); } if (mail_security != null) { mail_security = mail_security.trim(); if (mail_security.equals("ssl")) { props.put("mail.smtp.ssl.enable", "true"); } else if (mail_security.equals("tls")) { props.put("mail.smtp.starttls.enable", "true"); } else if (mail_security.equals("")) { logger.error("unknown security protocol "+mail_security +", should be ssl or tls"); } } // this doesn't seem to matter having this when // username and password are empty props.put("mail.smtp.auth", "true"); //setup username and password to the smtp server if (username == null || username.trim().equals("")) username = ""; if (password == null || password.trim().equals("")) password = ""; Authenticator auth = new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } }; Session session = Session.getInstance(props, auth); Message msg = new MimeMessage(session); msg.setFrom(); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false)); if (cc != null) { msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc, false)); } if (bcc != null) { msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(bcc, false)); } msg.setSubject(subject); msg.setText(content.replaceAll("-------", "&")); msg.setHeader("X-Mailer", mailer); msg.setSentDate(new Date()); // send the thing off Transport.send(msg); logger.info("\nMail was sent successfully."); result.appendChild(result_doc.createTextNode("Mail was sent successfully.")); } catch (Exception e) { logger.error("Error sending mail!"); e.printStackTrace(); result.appendChild(result_doc.createTextNode(e.getMessage())); } return result; } protected class Item { public String collection; public String docid; public HashMap metadata; public Item(String coll, String id) { this.collection = coll; this.docid = id; this.metadata = new HashMap(); } public boolean equals(Object o) { if (!(o instanceof Item)) { return false; } Item item = (Item) o; String id = collection + ":" + docid; String idin = item.collection + ":" + item.docid; return id.equals(idin); } public Element wrapIntoElement(Document doc) { Element itemElement = doc.createElement("item"); itemElement.setAttribute("name", docid); itemElement.setAttribute("collection", collection); Set metas = metadata.keySet(); Iterator i = metas.iterator(); while (i.hasNext()) { String meta_name = i.next(); itemElement.setAttribute(meta_name, metadata.get(meta_name)); } return itemElement; } } private class UserTimer extends Timer implements ActionListener { String id = ""; public UserTimer(int delay, String id) { super(delay, (ActionListener) null); addActionListener(this); this.id = id; } public void actionPerformed(ActionEvent e) { userMap.remove(id); timerMap.remove(id); stop(); } } }