source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/BerryBasket.java@ 32453

Last change on this file since 32453 was 32453, checked in by kjdon, 6 years ago

replacing hard coded param names with static string variables. set up save params for those params we need to save to the session.

  • Property svn:keywords set to Author Date Id Revision
File size: 20.3 KB
Line 
1/*
2 * BerryBasket.java
3 * Copyright (C) 2006 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20package org.greenstone.gsdl3.service;
21
22import java.sql.Statement;
23import java.util.Hashtable;
24import java.util.HashMap;
25import java.util.ArrayList;
26import java.util.HashSet;
27import java.util.Iterator;
28import java.util.Set;
29
30import org.w3c.dom.Document;
31import org.w3c.dom.Element;
32import org.w3c.dom.NodeList;
33
34import org.greenstone.util.GlobalProperties;
35import org.greenstone.gsdl3.util.GSXML;
36import org.greenstone.gsdl3.util.GSPath;
37import org.greenstone.gsdl3.util.UserContext;
38import org.greenstone.gsdl3.util.XMLConverter;
39
40import java.io.Serializable;
41import java.net.InetAddress;
42import java.util.Properties;
43import java.util.Date;
44
45import javax.mail.*;
46import javax.mail.internet.*;
47
48import java.awt.event.ActionEvent;
49import java.awt.event.ActionListener;
50import javax.swing.Timer;
51
52import org.apache.log4j.*;
53
54public class BerryBasket extends ServiceRack
55{
56
57 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.BerryBasket.class.getName());
58
59 // the services on offer
60 // these strings must match what is found in the properties file
61 protected static final String ADD_ITEM_SERVICE = "AddItem";
62 protected static final String DISPLAY_ITEMS_SERVICE = "DisplayList";
63 protected static final String ITEM_NUM_SERVICE = "ItemNum";
64 protected static final String DELETE_ITEMS_SERVICE = "DeleteItems";
65 protected static final String SEND_MAIL_SERVICE = "SendMail";
66 protected static final String DELETE_ITEM_SERVICE = "DeleteItem";
67
68 // for AddItem
69 protected static final String ITEM_PARAM = "item";
70 // for DeleteItems
71 protected static final String ITEMS_PARAM = "items";
72 // for SendMail
73 protected static final String ADDRESS_PARAM = "address";
74 protected static final String SUBJECT_PARAM = "subject";
75 protected static final String CONTENT_PARAM = "content";
76 protected static final String CC_PARAM = "cc";
77 protected static final String BCC_PARAM = "bcc";
78
79
80 protected static final String delimiter = "|";
81 protected static final int delay = 1800000;
82
83 protected Hashtable<String, Hashtable<String, Hashtable<String, Item>>> userMap = null;
84 protected Hashtable<String, UserTimer> timerMap = null;
85 protected String username = "";
86 protected String password = "";
87
88 HashSet<String> meta_names = null;
89
90 /** constructor */
91 public BerryBasket()
92 {
93 userMap = new Hashtable<String, Hashtable<String, Hashtable<String, Item>>>();
94 timerMap = new Hashtable<String, UserTimer>();
95 }
96
97 private Hashtable<String, Hashtable<String, Item>> updateDocMap(Element request)
98 {
99
100 String id = request.getAttribute("uid");
101
102 if (userMap.containsKey(id))
103 {
104 if (timerMap.containsKey(id))
105 {
106 UserTimer timer = timerMap.get(id);
107 timer.restart();
108 }
109 return userMap.get(id);
110 }
111 else
112 {
113 UserTimer timer = new UserTimer(delay, id);
114 timerMap.put(id, timer);
115 timer.start();
116 Hashtable<String, Hashtable<String, Item>> newDocs = new Hashtable<String, Hashtable<String, Item>>();
117 userMap.put(id, newDocs);
118 return newDocs;
119 }
120 }
121
122 /** configure this service */
123 public boolean configure(Element info, Element extra_info)
124 {
125 logger.info("Configuring BerryBasket...");
126 this.config_info = info;
127
128 // set up short_service_info_ - for now just has name and type
129 Element add_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
130 add_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
131 add_service.setAttribute(GSXML.NAME_ATT, ADD_ITEM_SERVICE);
132 this.short_service_info.appendChild(add_service);
133
134 // set up short_service_info_ - for now just has name and type
135 Element disp_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
136 disp_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
137 disp_service.setAttribute(GSXML.NAME_ATT, DISPLAY_ITEMS_SERVICE);
138 this.short_service_info.appendChild(disp_service);
139
140 // set up short_service_info_ - for now just has name and type
141 Element num_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
142 num_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
143 num_service.setAttribute(GSXML.NAME_ATT, ITEM_NUM_SERVICE);
144 this.short_service_info.appendChild(num_service);
145
146 // set up short_service_info_ - for now just has name and type
147 Element delete_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
148 delete_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
149 delete_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEMS_SERVICE);
150 this.short_service_info.appendChild(delete_service);
151
152 // set up short_service_info_ - for now just has name and type
153 Element deleteone_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
154 deleteone_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
155 deleteone_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEM_SERVICE);
156 this.short_service_info.appendChild(deleteone_service);
157
158 // set up short_service_info_ - for now just has name and type
159 Element mail_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
160 mail_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
161 mail_service.setAttribute(GSXML.NAME_ATT, SEND_MAIL_SERVICE);
162 this.short_service_info.appendChild(mail_service);
163
164
165 // set up the metadata names - this is the list of metadata retrieved for each item in the berry basket.
166 meta_names = new HashSet<String>();
167 meta_names.add("Title"); // the default
168 meta_names.add("root_Title");
169 meta_names.add("Date");
170 meta_names.add("root_assocfilepath"); // these two needed for source linking
171 meta_names.add("root_srclinkFile");
172
173 // are there any custom ones in the config file?
174 Element meta_list_elem = (Element) GSXML.getChildByTagName(info, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
175 if (meta_list_elem !=null) {
176 NodeList meta_list = meta_list_elem.getElementsByTagName(GSXML.METADATA_ELEM);
177 for (int i = 0; i < meta_list.getLength(); i++) {
178
179 Element s = (Element) meta_list.item(i);
180 meta_names.add(s.getAttribute(GSXML.NAME_ATT));
181 }
182
183 }
184
185 // if any params should be saved in the session, add them to save_params here
186 // this.save_params.add(XXX_PARAM);
187 return true;
188
189 }
190
191 /** returns a specific service description */
192 protected Element getServiceDescription(Document doc, String service_id, String lang, String subset)
193 {
194
195 if (service_id.equals(ADD_ITEM_SERVICE))
196 {
197 Element add_service = doc.createElement(GSXML.SERVICE_ELEM);
198 add_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
199 add_service.setAttribute(GSXML.NAME_ATT, ADD_ITEM_SERVICE);
200 return add_service;
201 }
202 if (service_id.equals(DISPLAY_ITEMS_SERVICE))
203 {
204
205 Element disp_service = doc.createElement(GSXML.SERVICE_ELEM);
206 disp_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
207 disp_service.setAttribute(GSXML.NAME_ATT, DISPLAY_ITEMS_SERVICE);
208 return disp_service;
209 }
210
211 if (service_id.equals(ITEM_NUM_SERVICE))
212 {
213
214 Element num_service = doc.createElement(GSXML.SERVICE_ELEM);
215 num_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
216 num_service.setAttribute(GSXML.NAME_ATT, ITEM_NUM_SERVICE);
217 return num_service;
218 }
219
220 if (service_id.equals(DELETE_ITEMS_SERVICE))
221 {
222
223 Element del_service = doc.createElement(GSXML.SERVICE_ELEM);
224 del_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
225 del_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEMS_SERVICE);
226 return del_service;
227 }
228
229 if (service_id.equals(DELETE_ITEM_SERVICE))
230 {
231
232 Element delone_service = doc.createElement(GSXML.SERVICE_ELEM);
233 delone_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
234 delone_service.setAttribute(GSXML.NAME_ATT, DELETE_ITEM_SERVICE);
235 return delone_service;
236 }
237
238 if (service_id.equals(SEND_MAIL_SERVICE))
239 {
240
241 Element mail_service = doc.createElement(GSXML.SERVICE_ELEM);
242 mail_service.setAttribute(GSXML.TYPE_ATT, "gather"); // what??
243 mail_service.setAttribute(GSXML.NAME_ATT, SEND_MAIL_SERVICE);
244 return mail_service;
245 }
246
247 return null;
248 }
249
250 protected Element processAddItem(Element request)
251 {
252 Hashtable<String, Hashtable<String, Item>> docsMap = updateDocMap(request);
253
254 // Create a new (empty) result message
255 Document result_doc = XMLConverter.newDOM();
256 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
257
258 // Get the parameters of the request
259 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
260 if (param_list == null)
261 {
262 logger.error("BerryBasket Error: AddItem request had no paramList.");
263 return result; // Return the empty result
264 }
265
266 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
267
268 String item = (String) params.get(ITEM_PARAM);
269 String collection = "";
270 int pos = item.indexOf(":");
271 if (pos != -1)
272 {
273 collection = item.substring(0, pos);
274 item = item.substring(pos + 1);
275 }
276
277 if (docsMap.containsKey(collection))
278 {
279 Hashtable<String, Item> items = docsMap.get(collection);
280 if (!items.containsKey(item))
281 {
282 Item newItem = generateItem(collection, item);
283 items.put(item, newItem);
284 result.appendChild(newItem.wrapIntoElement(result_doc));
285 }
286 }
287 else
288 {
289 Hashtable<String, Item> items = new Hashtable<String, Item>();
290 Item newItem = generateItem(collection, item);
291 items.put(item, newItem);
292 docsMap.put(collection, items);
293 result.appendChild(newItem.wrapIntoElement(result_doc));
294 }
295
296 return result;
297 }
298
299 private Item generateItem(String collection, String id)
300 {
301
302 Item item = new Item(collection, id);
303 String to = GSPath.appendLink(collection, "DocumentMetadataRetrieve");
304 ArrayList<String> tmp = new ArrayList<String>();
305 tmp.add(id);
306
307 UserContext userContext = new UserContext();
308 userContext.setLanguage("en");
309 userContext.setUserID("dumy");
310 Element response = getDocumentMetadata(to, userContext, tmp.iterator());
311 Element doc_node = (Element) response.getElementsByTagName(GSXML.DOC_NODE_ELEM).item(0);
312
313 String node_id = doc_node.getAttribute(GSXML.NODE_ID_ATT);
314 Element metadata_list = (Element) doc_node.getElementsByTagName(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER).item(0);
315
316 NodeList meta_elems = metadata_list.getElementsByTagName(GSXML.METADATA_ELEM);
317 for (int i=0; i<meta_elems.getLength(); i++) {
318 Element m = (Element)meta_elems.item(i);
319 String name = m.getAttribute(GSXML.NAME_ATT);
320 item.metadata.put(name, GSXML.getNodeText(m).trim());
321 }
322 // check for root_title == title
323 if (item.metadata.get("root_Title").equals(item.metadata.get("Title"))) {
324 item.metadata.remove("root_Title");
325
326 }
327 return item;
328
329 }
330
331 protected Element processDeleteItems(Element request)
332 {
333 Hashtable<String, Hashtable<String, Item>> docsMap = updateDocMap(request);
334
335 // Create a new (empty) result message
336 Document result_doc = XMLConverter.newDOM();
337 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
338
339 // Get the parameters of the request
340 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
341
342 if (param_list == null)
343 {
344 logger.error("BerryBasket Error: DeleteItem request had no paramList.");
345 return result; // Return the empty result
346 }
347
348 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
349
350 String param = (String) params.get(ITEMS_PARAM);
351
352 if (param == null)
353 return result;
354
355 String[] items = param.split("\\|");
356
357 for (int i = 0; i < items.length; i++)
358 {
359 String item = items[i];
360 if (item.trim().length() == 0)
361 continue;
362 String collection = "";
363 int pos = item.indexOf(":");
364 if (pos != -1)
365 {
366 collection = item.substring(0, pos);
367 item = item.substring(pos + 1);
368 }
369
370 if (docsMap.containsKey(collection))
371 {
372 Hashtable itemMap = docsMap.get(collection);
373 if (itemMap.containsKey(item))
374 {
375 itemMap.remove(item);
376 }
377 if (itemMap.size() == 0)
378 {
379 docsMap.remove(collection);
380 }
381 }
382
383 }
384
385 return result;
386 }
387
388
389 protected Element processItemNum(Element request)
390 {
391 Hashtable<String, Hashtable<String, Item>> docsMap = updateDocMap(request);
392
393 // Create a new (empty) result message
394 Document result_doc = XMLConverter.newDOM();
395 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
396
397 int size = 0;
398 String ids = "";
399 Iterator<String> keys = docsMap.keySet().iterator();
400
401 while (keys.hasNext())
402 {
403 Hashtable items = docsMap.get(keys.next());
404 size += items.size();
405 Iterator values = items.values().iterator();
406 while (values.hasNext())
407 {
408 Item item = (Item) values.next();
409 result.appendChild(item.wrapIntoElement(result_doc));
410 }
411 }
412
413 Element selement = result_doc.createElement("size");
414 selement.setAttribute("value", size + "");
415 result.appendChild(selement);
416
417 return result;
418 }
419
420 private Element getDocumentMetadata(String to, UserContext userContext, Iterator<String> ids)
421 {
422
423 // Build a request to obtain some document metadata
424 Document doc = XMLConverter.newDOM();
425 Element dm_message = doc.createElement(GSXML.MESSAGE_ELEM);
426 Element dm_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, to, userContext);
427 dm_message.appendChild(dm_request);
428
429 // Create a parameter list to specify the required metadata information
430 Element param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
431
432 Element param = null;
433 Iterator<String> i = meta_names.iterator();
434 while (i.hasNext())
435 {
436 String name = i.next();
437 param = doc.createElement(GSXML.PARAM_ELEM);
438 param_list.appendChild(param);
439 param.setAttribute(GSXML.NAME_ATT, "metadata");
440 param.setAttribute(GSXML.VALUE_ATT, name);
441
442 }
443
444 dm_request.appendChild(param_list);
445
446 // create the doc node list for the metadata request
447 Element dm_doc_list = doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
448 dm_request.appendChild(dm_doc_list);
449
450 while (ids.hasNext())
451 {
452 // Add the documentNode to the list
453 Element dm_doc_node = doc.createElement(GSXML.DOC_NODE_ELEM);
454 dm_doc_list.appendChild(dm_doc_node);
455 dm_doc_node.setAttribute(GSXML.NODE_ID_ATT, ids.next());
456 }
457
458 return (Element) this.router.process(dm_message);
459
460 }
461
462 protected Element processDisplayList(Element request)
463 {
464 Hashtable<String, Hashtable<String, Item>> docsMap = updateDocMap(request);
465
466 // Create a new (empty) result message
467 Document result_doc = XMLConverter.newDOM();
468 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
469
470 Iterator<String> keys = docsMap.keySet().iterator();
471
472 while (keys.hasNext())
473 {
474 String collection = keys.next();
475 Hashtable items = docsMap.get(collection);
476 Iterator itemItr = items.values().iterator();
477
478 Element collectionNode = result_doc.createElement("berryList");
479 collectionNode.setAttribute("name", collection);
480 result.appendChild(collectionNode);
481
482 while (itemItr.hasNext())
483 {
484 Item item = (Item) itemItr.next();
485 collectionNode.appendChild(item.wrapIntoElement(result_doc));
486 }
487 }
488
489 return result;
490 }
491
492
493
494
495 public Element processSendMail(Element request)
496 {
497 // Create a new (empty) result message
498 Document result_doc = XMLConverter.newDOM();
499 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
500
501 // Get the parameters of the request
502 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
503
504 if (param_list == null)
505 {
506 logger.error("BerryBasket Error: SendMail request had no paramList.");
507 return result; // Return the empty result
508 }
509
510 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
511
512 String to = (String) params.get(ADDRESS_PARAM);
513 String subject = (String) params.get(SUBJECT_PARAM);
514 String content = (String) params.get(CONTENT_PARAM);
515 String cc = (String) params.get(CC_PARAM);
516 String bcc = (String) params.get(BCC_PARAM);
517
518 String mailhost = GlobalProperties.getProperty("mail.smtp.host");
519 username = GlobalProperties.getProperty("mail.smtp.username");
520 password = GlobalProperties.getProperty("mail.smtp.password");
521 String from = GlobalProperties.getProperty("mail.from");
522 String port = GlobalProperties.getProperty("mail.smtp.port");
523 String mail_security = GlobalProperties.getProperty("mail.security");
524 String mailer = "msgsend";
525
526 try
527 {
528
529 Properties props = System.getProperties();
530
531 //Setup smtp host and from address
532 // XXX - could use Session.getTransport() and Transport.connect()
533 // XXX - assume we're using SMTP
534 if (mailhost != null && !mailhost.trim().equals(""))
535 {
536 props.put("mail.smtp.host", mailhost);
537 }
538 else
539 {
540 props.put("mail.smtp.host", "localhost");
541 }
542 if (from != null && !from.trim().equals(""))
543 {
544 props.put("mail.from", from);
545 }
546
547
548 if (port != null && !port.trim().equals("")) {
549 props.put("mail.smtp.port", port);
550 }
551
552 if (mail_security != null) {
553 mail_security = mail_security.trim();
554 if (mail_security.equals("ssl")) {
555 props.put("mail.smtp.ssl.enable", "true");
556 } else if (mail_security.equals("tls")) {
557 props.put("mail.smtp.starttls.enable", "true");
558 }
559 else if (mail_security.equals("")) {
560 logger.error("unknown security protocol "+mail_security +", should be ssl or tls");
561 }
562 }
563
564 // this doesn't seem to matter having this when
565 // username and password are empty
566 props.put("mail.smtp.auth", "true");
567
568 //setup username and password to the smtp server
569
570 if (username == null || username.trim().equals(""))
571 username = "";
572 if (password == null || password.trim().equals(""))
573 password = "";
574
575 Authenticator auth = new Authenticator()
576 {
577 protected PasswordAuthentication getPasswordAuthentication()
578 {
579 return new PasswordAuthentication(username, password);
580 }
581 };
582
583 Session session = Session.getInstance(props, auth);
584
585 Message msg = new MimeMessage(session);
586 msg.setFrom();
587 msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false));
588 if (cc != null)
589 {
590 msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc, false));
591 }
592 if (bcc != null)
593 {
594 msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(bcc, false));
595 }
596 msg.setSubject(subject);
597 msg.setText(content.replaceAll("-------", "&"));
598 msg.setHeader("X-Mailer", mailer);
599 msg.setSentDate(new Date());
600
601 // send the thing off
602 Transport.send(msg);
603
604 logger.info("\nMail was sent successfully.");
605 result.appendChild(result_doc.createTextNode("Mail was sent successfully."));
606 }
607 catch (Exception e)
608 {
609 logger.error("Error sending mail!");
610 e.printStackTrace();
611 result.appendChild(result_doc.createTextNode(e.getMessage()));
612 }
613
614 return result;
615 }
616
617 protected class Item
618 {
619 public String collection;
620 public String docid;
621 public HashMap<String,String> metadata;
622
623 public Item(String coll, String id)
624 {
625 this.collection = coll;
626 this.docid = id;
627 this.metadata = new HashMap<String,String>();
628 }
629
630 public boolean equals(Object o)
631 {
632 if (!(o instanceof Item))
633 {
634 return false;
635 }
636 Item item = (Item) o;
637 String id = collection + ":" + docid;
638 String idin = item.collection + ":" + item.docid;
639 return id.equals(idin);
640
641 }
642
643 public Element wrapIntoElement(Document doc)
644 {
645 Element itemElement = doc.createElement("item");
646 itemElement.setAttribute("name", docid);
647 itemElement.setAttribute("collection", collection);
648
649 Set<String> metas = metadata.keySet();
650 Iterator<String> i = metas.iterator();
651 while (i.hasNext()) {
652 String meta_name = i.next();
653 itemElement.setAttribute(meta_name, metadata.get(meta_name));
654 }
655 return itemElement;
656 }
657 }
658
659 private class UserTimer extends Timer implements ActionListener
660 {
661 String id = "";
662
663 public UserTimer(int delay, String id)
664 {
665 super(delay, (ActionListener) null);
666 addActionListener(this);
667 this.id = id;
668 }
669
670 public void actionPerformed(ActionEvent e)
671 {
672 userMap.remove(id);
673 timerMap.remove(id);
674 stop();
675 }
676
677 }
678
679}
Note: See TracBrowser for help on using the repository browser.