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

Last change on this file since 29318 was 28966, checked in by kjdon, 10 years ago

Lots of changes. Mainly to do with removing this.doc from everywhere. Document is not thread safe. Now we tend to create a new Document everytime we are starting a new page/message etc. in service this.desc_doc is available as teh document to create service info stuff. But it should only be used for this and not for other messages. newDOM is now static for XMLConverter. method param changes for some GSXML methods.

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