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

Last change on this file since 33220 was 33220, checked in by kjdon, 5 years ago

need to check for username being which it usually is if user not logged on. otherwise id gets set to empty string for everyone!

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