source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/MessageRouter.java@ 29308

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

commented out debug response print statement

  • Property svn:keywords set to Author Date Id Revision
File size: 41.3 KB
Line 
1/*
2 * MessageRouter.java
3 * Copyright (C) 2002 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 */
19package org.greenstone.gsdl3.core;
20
21import java.io.File;
22import java.net.Authenticator;
23import java.net.PasswordAuthentication;
24import java.util.HashMap;
25import java.util.Map;
26import java.util.Iterator;
27
28import org.apache.commons.lang3.StringUtils;
29import org.apache.log4j.Logger;
30import org.greenstone.gsdl3.collection.Collection;
31import org.greenstone.gsdl3.collection.ServiceCluster;
32import org.greenstone.gsdl3.comms.Communicator;
33import org.greenstone.gsdl3.comms.SOAPCommunicator;
34import org.greenstone.gsdl3.service.ServiceRack;
35import org.greenstone.gsdl3.util.GSFile;
36import org.greenstone.gsdl3.util.GSPath;
37import org.greenstone.gsdl3.util.GSXML;
38import org.greenstone.gsdl3.util.UserContext;
39import org.greenstone.gsdl3.util.XMLConverter;
40import org.greenstone.util.GlobalProperties;
41import org.w3c.dom.Document;
42import org.w3c.dom.Element;
43import org.w3c.dom.Node;
44import org.w3c.dom.NodeList;
45
46/**
47 * The hub of a Greenstone system.
48 *
49 * Accepts XML requests (via process method of ModuleInterface) and routes them
50 * to the appropriate collection or service or external entity.
51 *
52 * contains a map of module objects - may be services, collections, comms
53 * objects talking to other MessageRouters etc.
54 *
55 *
56 * Since some service classes are moved into a separate directory in order
57 * for them to be checked out from a different repository, we modify the
58 * configureServices method to search some of the classes in other place if
59 * they are not found in the service directory.
60 */
61public class MessageRouter implements ModuleInterface
62{
63
64 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.MessageRouter.class.getName());
65
66 /** the (directory) name of the site */
67 protected String site_name = null;
68 /** site home - the home directory for the site */
69 protected String site_home = null;
70 /** the http address for this site */
71 protected String site_http_address = null;
72
73 protected String library_name = null;
74
75 /** map of names to Module objects */
76 protected HashMap<String, ModuleInterface> module_map = null;
77
78 /** the full description of this site */
79
80 // should these things be separated into local and remote??
81
82 /** the original xml config element */
83 public Element config_info = null;
84
85 /** list of collections that can be reached */
86 protected Element collection_list = null;
87 /** list of collections that are loaded but are private */
88 protected Element private_collection_list = null;
89 /** list of service clusters that can be reached */
90 protected Element cluster_list = null;
91 /** list of single services that can be reached */
92 protected Element service_list = null;
93 /** list of external sites that can be reached */
94 protected Element site_list = null;
95 /** list of metadata for the site */
96 protected Element metadata_list = null;
97
98 //***************************************************************
99 // public methods
100 //***************************************************************
101
102 /** constructor */
103 public MessageRouter()
104 {
105 }
106
107 public void cleanUp()
108 {
109 cleanUpModuleMapEntire();
110 }
111
112 /** site_name must be set before configure is called */
113 public void setSiteName(String site_name)
114 {
115 this.site_name = site_name;
116 }
117
118 public String getSiteName()
119 {
120 return this.site_name;
121 }
122
123 /** library_name must be set before configure is called */
124 public void setLibraryName(String library_name)
125 {
126 this.library_name = library_name;
127 }
128
129 public String getLibraryName()
130 {
131 return this.library_name;
132 }
133
134 /**
135 * configures the system
136 *
137 * looks in site_home/collect for collections, reads config file
138 * site_home/siteConfig.xml
139 *
140 */
141 public boolean configure()
142 {
143
144 logger.info("configuring the Message Router");
145
146 if (this.site_name == null)
147 {
148 logger.error(" You must set site_name before calling configure");
149 return false;
150 }
151 this.site_home = GSFile.siteHome(GlobalProperties.getGSDL3Home(), this.site_name);
152 String web_address = GlobalProperties.getGSDL3WebAddress();
153 if (web_address.equals("")) {
154 this.site_http_address = "sites/"+this.site_name;
155 } else {
156 this.site_http_address = web_address + "/sites/" + this.site_name;
157 }
158 // are we behind a firewall?? - is there a better place to set up the proxy?
159 String host = GlobalProperties.getProperty("proxy.host");
160 String port = GlobalProperties.getProperty("proxy.port");
161 final String user = GlobalProperties.getProperty("proxy.user");
162 final String passwd = GlobalProperties.getProperty("proxy.password");
163
164 if (host != null && !host.equals("") && port != null && !port.equals(""))
165 {
166 System.setProperty("http.proxyType", "4");
167 System.setProperty("http.proxyHost", host);
168 System.setProperty("http.proxyPort", port);
169 System.setProperty("http.proxySet", "true");
170 // have we got a user/password?
171 if (user != null && !user.equals("") && passwd != null && !passwd.equals(""))
172 {
173 try
174 {
175 // set up the authenticator
176 Authenticator.setDefault(new Authenticator()
177 {
178 protected PasswordAuthentication getPasswordAuthentication()
179 {
180 return new PasswordAuthentication(user, new String(passwd).toCharArray());
181 }
182 });
183
184 }
185 catch (Exception e)
186 {
187 logger.error("MessageRouter Error: couldn't set up an authenticator the proxy");
188
189 }
190 }
191 }
192
193 this.module_map = new HashMap<String, ModuleInterface>();
194
195 // This stuff may be done at a reconfigure also
196 return configureLocalSite();
197
198 }
199
200 /**
201 * Process an XML request - as a String
202 *
203 * @param xml_in
204 * the request to process
205 * @return the response - contains any error messages
206 * @see String
207 */
208 public String process(String xml_in)
209 {
210
211 Document doc = XMLConverter.getDOM(xml_in);
212
213 Node result = process(doc);
214 return XMLConverter.getString(result);
215 }
216
217 /**
218 * Process an XML request - as a DOM Element
219 *
220 * @param xml_in
221 * the message to process - should be <message>
222 * @return the response - contains any error messages
223 * @see Element
224 */
225 public Node process(Node message_node)
226 {
227
228 Document doc = XMLConverter.newDOM();
229 Element message = GSXML.nodeToElement(message_node);
230
231 // check that its a correct message tag
232 if (!message.getTagName().equals(GSXML.MESSAGE_ELEM))
233 {
234 logger.error(" Invalid message. GSDL message should start with <" + GSXML.MESSAGE_ELEM + ">, instead it starts with:" + message.getTagName() + ".");
235 return null;
236 }
237
238 NodeList requests = message.getElementsByTagName(GSXML.REQUEST_ELEM);
239
240 Element mainResult = doc.createElement(GSXML.MESSAGE_ELEM);
241
242 // empty request
243 if (requests.getLength() == 0)
244 {
245 logger.error("empty request");
246 return mainResult;
247 }
248
249 // for now, just process each request one by one, and append the results to mainResult
250 // Note: if you add an element to another node in the same document, it
251 // gets removed from where it was. This changes the node list - you cant iterate over the node list in a normal manner if you are moving elements out of it
252 int num_requests = requests.getLength();
253 for (int i = 0; i < num_requests; i++)
254 {
255 Node result = null;
256 Element req = (Element) requests.item(i);
257 if (req == null)
258 {
259 logger.error("request " + i + " is null");
260 continue;
261 }
262 String path = req.getAttribute(GSXML.TO_ATT); // returns "" if no att of this name
263 if (path.equals(""))
264 {
265 // its a message for the message router
266 String type_att = req.getAttribute(GSXML.TYPE_ATT);
267 if (type_att.equals(GSXML.REQUEST_TYPE_MESSAGING))
268 {
269 // its a messaging request - modifies the requests/responses
270 result = modifyMessages(req, message, mainResult);
271 }
272 else
273 {
274 // standard request
275 result = processMessage(req);
276 }
277
278 if (result != null)
279 {
280 mainResult.appendChild(doc.importNode(result, true));
281 }
282 }
283 else
284 {
285 // The message needs to go to another module. The same message can
286 // be passed to multiple modules - they will be in a comma
287 // separated list in the 'to' attribute
288 String[] modules = StringUtils.split(path, ",");
289
290 for (String this_mod : modules)
291 {
292 // why can't we do this outside the loop??
293 Element mess = doc.createElement(GSXML.MESSAGE_ELEM);
294 Element copied_request = (Element) doc.importNode(req, true);
295 mess.appendChild(copied_request);
296
297 // find the module to pass it on to
298 // need to put the request into a message element
299 String obj = GSPath.getFirstLink(this_mod);
300
301 if (this.module_map.containsKey(obj))
302 {
303 copied_request.setAttribute(GSXML.TO_ATT, this_mod);
304 result = this.module_map.get(obj).process(mess);
305
306 if (result != null)
307 {
308 // append the contents of the message to the mainResult - there will only be one response at this stage
309 Node res = GSXML.getChildByTagName(result, GSXML.RESPONSE_ELEM);
310 if (res != null)
311 {
312 mainResult.appendChild(doc.importNode(res, true));
313 }
314 }
315 else
316 {
317 // add in a place holder response
318 Element response = doc.createElement(GSXML.RESPONSE_ELEM);
319 response.setAttribute(GSXML.FROM_ATT, this_mod);
320 mainResult.appendChild(response);
321 logger.error("MessageRouter Error: request had null result!");
322 }
323 }
324 else
325 {
326 logger.error("MessageRouter Error: request has illegal module name in:\n" + XMLConverter.getString(req));
327 }
328 }
329 }
330
331 } // for each request
332
333 // logger.debug("MR returned response");
334 //logger.debug(XMLConverter.getString(mainResult));
335
336 return mainResult;
337 }
338
339 public Element getCollectionList()
340 {
341 return collection_list;
342 }
343
344 public Element getPrivateCollectionList()
345 {
346 return private_collection_list;
347 }
348
349 public HashMap<String, ModuleInterface> getModuleMap()
350 {
351 return module_map;
352 }
353
354 // ********************************************************************
355 // auxiliary configure and cleanup methods
356 // *******************************************************************
357
358 /**
359 * Calls clean up on all modules referenced in the module_map and removes
360 * them .
361 */
362 protected void cleanUpModuleMapEntire()
363 {
364 if (this.module_map != null)
365 {
366 Iterator<ModuleInterface> i = this.module_map.values().iterator();
367 while (i.hasNext())
368 {
369 ModuleInterface i_next = i.next();
370
371 i_next.cleanUp();
372 i.remove();
373 }
374 }
375 }
376
377 /**
378 * Goes through the children of list, and for each local/site-specific name
379 * attribute, calls cleanUp on the module and removes it from the module_map
380 * and removes it from the list
381 */
382 protected void cleanUpModuleMapSubset(Element list, String remote_site)
383 {
384 logger.error(XMLConverter.getString(list));
385 NodeList elements = list.getChildNodes(); // we are assuming no extraneous nodes
386 for (int i = elements.getLength() - 1; i >= 0; i--)
387 {
388 Element item = (Element) elements.item(i);
389 String name = item.getAttribute(GSXML.NAME_ATT);
390 String potential_site_name = GSPath.getFirstLink(name);
391 if (remote_site != null)
392 {
393 if (remote_site.equals(potential_site_name))
394 {
395 list.removeChild(item);
396 }
397 }
398 else
399 {
400 if (name.equals(potential_site_name))
401 {// there was no site
402 list.removeChild(item);
403 ModuleInterface m = this.module_map.remove(name);
404 m.cleanUp(); // clean up any open files/connections etc
405 m = null;
406 }
407 }
408 }
409 logger.error(XMLConverter.getString(list));
410 }
411
412 /**
413 * removes all site modules from module_map, and any stored info about this
414 * sites collections and services
415 */
416 protected void cleanUpAllExternalSiteInfo()
417 {
418
419 NodeList site_nodes = this.site_list.getChildNodes();
420 for (int i = site_nodes.getLength() - 1; i >= 0; i--)
421 {
422 Element item = (Element) site_nodes.item(i);
423 String name = item.getAttribute(GSXML.NAME_ATT);
424 // will remove the node from site_list
425 deactivateModule(GSXML.SITE_ELEM, name);
426 }
427
428 }
429
430 /**
431 * read thru own site config file - create services and connect to sites
432 */
433 protected boolean configureLocalSite()
434 {
435
436 // this may be a reconfigure, so clean up the old moduleMap
437 cleanUpModuleMapEntire();
438
439 File configFile = new File(GSFile.siteConfigFile(this.site_home));
440
441 if (!configFile.exists())
442 {
443 logger.error(" site config file: " + configFile.getPath() + " not found!");
444 return false;
445 }
446
447 Document config_doc = XMLConverter.getDOM(configFile);
448 if (config_doc == null)
449 {
450 logger.error(" couldn't parse site config file: " + configFile.getPath());
451 return false;
452 }
453
454 this.config_info = config_doc.getDocumentElement();
455
456 // load up the services: serviceRackList
457 Document doc = XMLConverter.newDOM();
458 this.service_list = doc.createElement(GSXML.SERVICE_ELEM + GSXML.LIST_MODIFIER);
459 Element service_rack_list_elem = (Element) GSXML.getChildByTagName(config_info, GSXML.SERVICE_CLASS_ELEM + GSXML.LIST_MODIFIER);
460 configureServices(service_rack_list_elem);
461
462 // load up the service clusters
463 this.cluster_list = doc.createElement(GSXML.CLUSTER_ELEM + GSXML.LIST_MODIFIER);
464 Element cluster_list_elem = (Element) GSXML.getChildByTagName(config_info, GSXML.CLUSTER_ELEM + GSXML.LIST_MODIFIER);
465 configureClusters(cluster_list_elem);
466
467 // load up the collections
468 this.collection_list = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
469 this.private_collection_list = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
470 configureCollections();
471
472 // load up the external sites - this also adds their services/clusters/collections to the other lists - so must be done last
473 this.site_list = doc.createElement(GSXML.SITE_ELEM + GSXML.LIST_MODIFIER);
474 Element site_list_elem = (Element) GSXML.getChildByTagName(config_info, GSXML.SITE_ELEM + GSXML.LIST_MODIFIER);
475 configureExternalSites(site_list_elem);
476
477 // load up the site metadata
478 this.metadata_list = doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
479 Element metadata_list_elem = (Element) GSXML.getChildByTagName(config_info, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
480 loadMetadata(metadata_list_elem);
481
482 return true;
483
484 }
485
486 protected boolean configureServices(Element service_rack_list)
487 {
488
489 // load up the individual services
490 logger.info("loading service modules...");
491
492 if (service_rack_list == null)
493 {
494 logger.info("... none to be loaded");
495 return true;
496 }
497
498 NodeList service_racks = service_rack_list.getElementsByTagName(GSXML.SERVICE_CLASS_ELEM);
499 if (service_racks.getLength() == 0)
500 {
501 logger.info("... none to be loaded");
502 return true;
503 }
504 Document doc = XMLConverter.newDOM();
505 Element service_message = doc.createElement(GSXML.MESSAGE_ELEM);
506 Element service_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, "", new UserContext());
507 service_message.appendChild(service_request);
508
509 for (int i = 0; i < service_racks.getLength(); i++)
510 {
511 Element n = (Element) service_racks.item(i);
512 String service_name = n.getAttribute(GSXML.NAME_ATT);
513 logger.info("..." + service_name);
514
515 Class service_class = null;
516 try
517 {
518 service_class = Class.forName("org.greenstone.gsdl3.service." + service_name);
519 }
520 catch (ClassNotFoundException e)
521 {
522 try
523 {
524 //try the service_name alone in case the package name is already specified
525 service_class = Class.forName(service_name);
526 }
527 catch (ClassNotFoundException ae)
528 {
529 logger.info(ae.getMessage());
530 }
531 }
532 try
533 {
534 ServiceRack s = (ServiceRack) service_class.newInstance();
535 s.setSiteHome(this.site_home);
536 s.setSiteAddress(this.site_http_address);
537 s.setLibraryName(this.library_name);
538 s.setMessageRouter(this);
539 // pass the XML node to the service for service configuration
540 if (!s.configure(n, null))
541 {
542 logger.error("couldn't configure ServiceRack " + service_name);
543 continue;
544 }
545
546 // find out the supported services for this service module
547 Element service_response = (Element) s.process(service_message);
548 NodeList services = service_response.getElementsByTagName(GSXML.SERVICE_ELEM);
549 if (services.getLength() == 0)
550 {
551 logger.error("MessageRouter configure error: serviceRack " + service_name + " has no services!");
552 }
553 else
554 {
555 Document service_list_doc = this.service_list.getOwnerDocument();
556 for (int j = 0; j < services.getLength(); j++)
557 {
558 String service = ((Element) services.item(j)).getAttribute(GSXML.NAME_ATT);
559
560 this.module_map.put(service, s);
561
562 // add short info to service_list_ XML
563 this.service_list.appendChild(service_list_doc.importNode(services.item(j), true));
564 }
565 }
566 }
567 catch (Exception e)
568 {
569 logger.error("MessageRouter configure exception: in ServiceRack class specification: " + e.getMessage());
570 e.printStackTrace();
571 }
572 } // for each service module
573 return true;
574 }
575
576 protected boolean configureClusters(Element config_cluster_list)
577 {
578
579 // load up the service clusters
580 logger.info("loading service clusters ...");
581 if (config_cluster_list == null)
582 {
583 logger.info("... none to be loaded");
584 return true;
585 }
586 NodeList service_clusters = config_cluster_list.getElementsByTagName(GSXML.CLUSTER_ELEM);
587 if (service_clusters.getLength() == 0)
588 {
589 logger.info("... none to be loaded");
590 return true;
591 }
592
593 Document doc = this.cluster_list.getOwnerDocument();
594 for (int i = 0; i < service_clusters.getLength(); i++)
595 {
596 Element cluster = (Element) service_clusters.item(i);
597 String name = cluster.getAttribute(GSXML.NAME_ATT);
598 logger.info("..." + name);
599 ServiceCluster sc = new ServiceCluster();
600 sc.setSiteHome(this.site_home);
601 sc.setSiteAddress(this.site_http_address);
602 sc.setClusterName(name);
603 sc.setMessageRouter(this);
604 if (!sc.configure(cluster))
605 {
606 logger.error("couldn't configure ServiceCluster " + name);
607 continue;
608 }
609
610 this.module_map.put(name, sc); // this replaces the old one if there was one already present
611 //add short info to cluster list
612 Element e = doc.createElement(GSXML.CLUSTER_ELEM);
613 e.setAttribute(GSXML.NAME_ATT, name);
614 this.cluster_list.appendChild(e);
615
616 }
617 return true;
618 }
619
620 /**
621 * looks through the collect directory and activates any collections it
622 * finds. If this is a reconfigure, clean up must be done first before
623 * calling this
624 */
625 protected boolean configureCollections()
626 {
627
628 // read thru the collect directory and activate all the valid collections
629 File collectDir = new File(GSFile.collectDir(this.site_home));
630 if (collectDir.exists())
631 {
632 logger.info("Reading thru directory " + collectDir.getPath() + " to find collections.");
633 File[] contents = collectDir.listFiles();
634 for (int i = 0; i < contents.length; i++)
635 {
636 if (contents[i].isDirectory())
637 {
638
639 String colName = contents[i].getName();
640 if (!colName.startsWith("CVS") && !colName.startsWith(".svn"))
641 {
642 activateCollectionByName(colName);
643 }
644 }
645 }
646 } // collectDir
647 return true;
648 }
649
650 // testing whether a collection (or more generally, a module) is active
651 protected boolean pingModule(String name)
652 {
653 // module (including collection) would have been added to module_map
654 // if activated, and removed from map if deactivated.
655 // The this.collection_list Element would contain the collection too,
656 // but the following check seems to be more generally useful
657 return this.module_map.containsKey(name);
658 }
659
660 /**
661 * creates and configures a new collection if this is done for a
662 * reconfigure, the collection should be deactivated first.
663 *
664 * @param col_name
665 * the name of the collection
666 * @return true if collection created ok
667 */
668 protected boolean activateCollectionByName(String col_name)
669 {
670
671 logger.info("Activating collection: " + col_name + ".");
672 Document doc = this.collection_list.getOwnerDocument();
673 // Look for the etc/collectionInit.xml file, and see what sort of Collection to load
674 Collection c = null;
675 File init_file = new File(GSFile.collectionInitFile(this.site_home, col_name));
676
677 if (init_file.exists())
678 {
679 Document init_doc = XMLConverter.getDOM(init_file);
680 if (init_doc != null)
681 {
682 Element init_elem = init_doc.getDocumentElement();
683 if (init_elem != null)
684 {
685 String coll_class_name = init_elem.getAttribute("class");
686 if (!coll_class_name.equals(""))
687 {
688 try
689 {
690 c = (Collection) Class.forName("org.greenstone.gsdl3.collection." + coll_class_name).newInstance();
691 }
692 catch (Exception e)
693 {
694 logger.info(" couldn't create a new collection, type " + coll_class_name + ", defaulting to class Collection");
695 }
696 }
697 }
698 }
699 }
700 if (c == null)
701 { // we haven't found another classname to use
702 c = new Collection();
703 }
704
705 c.setCollectionName(col_name);
706 c.setSiteHome(this.site_home);
707 c.setSiteAddress(this.site_http_address);
708 c.setMessageRouter(this);
709 if (c.configure())
710 {
711 logger.info("have just configured collection " + col_name);
712 // add to list of collections
713 this.module_map.put(col_name, c);
714 Element e = doc.createElement(GSXML.COLLECTION_ELEM);
715 e.setAttribute(GSXML.NAME_ATT, col_name);
716
717 if (c.isPublic())
718 {
719 // only public collections will appear on the home page
720 // add short description_ to collection_list_
721 this.collection_list.appendChild(e);
722 }
723 else
724 {
725 this.private_collection_list.appendChild(e);
726 }
727 return true;
728 }
729 else
730 {
731 logger.error("Couldn't configure collection: " + col_name + ".");
732 return false;
733 }
734 }
735
736 /**
737 * Goes through the siteList and activates each site found. If this is done
738 * for a reconfigure, a clean up must be done first ****HOW???
739 */
740 protected boolean configureExternalSites(Element config_site_list)
741 {
742
743 // load up the sites
744 logger.info("loading external sites...");
745 if (config_site_list == null)
746 {
747 logger.info("...none found");
748 return true;
749 }
750
751 NodeList sites = config_site_list.getElementsByTagName(GSXML.SITE_ELEM);
752 if (sites.getLength() == 0)
753 {
754 logger.info("...none found");
755 return true;
756 }
757
758 // this is a name to identify the current site in the Communicator
759 String local_site_name = config_site_list.getAttribute(GSXML.LOCAL_SITE_NAME_ATT);
760 if (local_site_name.equals(""))
761 {
762 local_site_name = site_name;
763 }
764
765 for (int i = 0; i < sites.getLength(); i++)
766 {
767 Element s = (Element) sites.item(i);
768 activateSite(s, local_site_name);
769 }
770 return true;
771 }
772
773 protected boolean activateSiteByName(String site_name)
774 {
775 logger.info("Activating site: " + site_name + ".");
776
777 File configFile = new File(GSFile.siteConfigFile(this.site_home));
778
779 if (!configFile.exists())
780 {
781 logger.error(" site config file: " + configFile.getPath() + " not found!");
782 return false;
783 }
784 Document config_doc = XMLConverter.getDOM(configFile);
785 if (config_doc == null)
786 {
787 logger.error(" couldn't parse site config file: " + configFile.getPath());
788 return false;
789 }
790 Element config_elem = config_doc.getDocumentElement();
791
792 Element config_site_list = (Element) GSXML.getChildByTagName(config_elem, GSXML.SITE_ELEM + GSXML.LIST_MODIFIER);
793 if (config_site_list == null)
794 {
795 logger.error("activateSite, no sites found");
796 return false;
797 }
798 // this is a name to identify the current site in the Communicator
799 String local_site_name = config_site_list.getAttribute("localSiteName");
800 if (local_site_name.equals(""))
801 {
802 local_site_name = site_name;
803 }
804
805 Element this_site_elem = GSXML.getNamedElement(config_site_list, GSXML.SITE_ELEM, GSXML.NAME_ATT, site_name);
806 if (this_site_elem == null)
807 {
808 logger.error("activateSite, site " + site_name + " not found");
809 return false;
810 }
811
812 return activateSite(this_site_elem, local_site_name);
813 }
814
815 protected boolean activateSite(Element site_elem, String local_site_name)
816 {
817
818 Communicator comm = null;
819 String type = site_elem.getAttribute(GSXML.TYPE_ATT);
820 String name = site_elem.getAttribute(GSXML.NAME_ATT);
821 if (type.equals(GSXML.COMM_TYPE_SOAP_JAVA))
822 {
823 logger.info("activating SOAP site " + name);
824 comm = new SOAPCommunicator();
825 if (comm.configure(site_elem))
826 {
827 comm.setLocalSiteName(local_site_name);
828
829 // add to map of modules
830 this.module_map.put(name, comm);
831 this.site_list.appendChild(this.site_list.getOwnerDocument().importNode(site_elem, true));
832 // need to get collection list and service
833 // list from here- if the site isn't up yet, the site will
834 // have to be added later
835 if (!getRemoteSiteInfo(comm, name))
836 {
837 logger.error(" couldn't get info from site");
838 }
839 }
840 else
841 {
842 logger.error(" couldn't configure site");
843 return false;
844 }
845
846 }
847 else
848 {
849 logger.error(" cant talk to server of type:" + type + ", so not making a connection to " + name);
850 return false;
851 }
852 return true;
853 }
854
855 /** Goes through the metadataList and loads each metadatum found */
856 protected boolean loadMetadata(Element config_metadata_list)
857 {
858
859 // load up the sites
860 logger.info("loading site metadata...");
861 if (config_metadata_list == null)
862 {
863 logger.info("...none found");
864 return true;
865 }
866
867 NodeList metadata = config_metadata_list.getElementsByTagName(GSXML.METADATA_ELEM);
868 if (metadata.getLength() == 0)
869 {
870 logger.info("...none found");
871 return true;
872 }
873
874 Document doc = this.metadata_list.getOwnerDocument();
875 for (int i = 0; i < metadata.getLength(); i++)
876 {
877 Element s = (Element) metadata.item(i);
878 this.metadata_list.appendChild(doc.importNode(s, true));
879 }
880 return true;
881 }
882
883 /**
884 * get site info from external site
885 *
886 * @param comm
887 * - the communicator object for the external site
888 * @param site_name
889 * - the name of the external site
890 * @return true if successful
891 */
892 protected boolean getRemoteSiteInfo(Communicator comm, String site_name)
893 {
894
895 logger.info(" getting info from site:" + site_name);
896 Document doc = XMLConverter.newDOM();
897 Element info_request = doc.createElement(GSXML.MESSAGE_ELEM);
898 Element req = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, "", new UserContext());
899 info_request.appendChild(req);
900
901 // process the message
902 Node info_response_node = comm.process(info_request);
903 Element info_response = GSXML.nodeToElement(info_response_node);
904
905 if (info_response == null)
906 {
907 return false;
908 }
909 // collection info
910 NodeList colls = info_response.getElementsByTagName(GSXML.COLLECTION_ELEM);
911 if (colls.getLength() > 0)
912 {
913 for (int i = 0; i < colls.getLength(); i++)
914 {
915 Element e = (Element) colls.item(i);
916 String col_name = e.getAttribute(GSXML.NAME_ATT);
917 // add the info to own coll list - may want to keep
918 // this separate in future - so can distinguish own and
919 // other collections ??
920 e.setAttribute(GSXML.NAME_ATT, GSPath.prependLink(col_name, site_name));
921 this.collection_list.appendChild(doc.importNode(e, true));
922 }
923 }
924
925 // service info
926 NodeList services = info_response.getElementsByTagName(GSXML.SERVICE_ELEM);
927 if (services.getLength() > 0)
928 {
929 for (int i = 0; i < services.getLength(); i++)
930 {
931 Element e = (Element) services.item(i);
932 String serv_name = e.getAttribute(GSXML.NAME_ATT);
933 e.setAttribute(GSXML.NAME_ATT, GSPath.prependLink(serv_name, site_name));
934 this.service_list.appendChild(doc.importNode(e, true));
935 }
936 }
937
938 // serviceCluster info
939 NodeList clusters = info_response.getElementsByTagName(GSXML.CLUSTER_ELEM);
940 if (clusters.getLength() > 0)
941 {
942 for (int i = 0; i < clusters.getLength(); i++)
943 {
944 Element e = (Element) clusters.item(i);
945 String clus_name = e.getAttribute(GSXML.NAME_ATT);
946 e.setAttribute(GSXML.NAME_ATT, GSPath.prependLink(clus_name, site_name));
947 this.cluster_list.appendChild(doc.importNode(e, true));
948 }
949 }
950 return true;
951 }
952
953 protected boolean activateServiceClusterByName(String cluster_name)
954 {
955 return false;
956
957 }
958
959 protected boolean activateServiceRackByName(String module_name)
960 {
961 return false;
962 }
963
964 protected boolean deactivateModule(String type, String name)
965 {
966
967 logger.info("deactivating " + type + " module: " + name);
968 if (this.module_map.containsKey(name))
969 {
970
971 logger.info("found the module");
972 ModuleInterface m = this.module_map.remove(name);
973 // also remove the xml bit from description list
974 if (type.equals(GSXML.COLLECTION_ELEM))
975 {
976 if (((Collection) m).isPublic())
977 {
978 Element this_col = GSXML.getNamedElement(this.collection_list, GSXML.COLLECTION_ELEM, GSXML.NAME_ATT, name);
979 if (this_col != null)
980 {
981 this.collection_list.removeChild(this_col);
982 }
983 }
984 else
985 {
986 // a private collection
987 Element this_col = GSXML.getNamedElement(this.private_collection_list, GSXML.COLLECTION_ELEM, GSXML.NAME_ATT, name);
988 if (this_col != null)
989 {
990 this.private_collection_list.removeChild(this_col);
991 }
992 }
993 }
994 else if (type.equals(GSXML.SERVICE_ELEM))
995 {
996 Element this_service = GSXML.getNamedElement(this.service_list, GSXML.SERVICE_ELEM, GSXML.NAME_ATT, name);
997 if (this_service != null)
998 {
999 this.service_list.removeChild(this_service);
1000 }
1001 }
1002 else if (type.equals(GSXML.CLUSTER_ELEM))
1003 {
1004 Element this_cluster = GSXML.getNamedElement(this.cluster_list, GSXML.CLUSTER_ELEM, GSXML.NAME_ATT, name);
1005 if (this_cluster != null)
1006 {
1007 this.cluster_list.removeChild(this_cluster);
1008 }
1009 }
1010 else if (type.equals(GSXML.SITE_ELEM))
1011 {
1012 Element this_site = GSXML.getNamedElement(this.site_list, GSXML.SITE_ELEM, GSXML.NAME_ATT, name);
1013 if (this_site != null)
1014 {
1015 this.site_list.removeChild(this_site);
1016
1017 // also remove this sites colls, services, clusters etc
1018 cleanUpModuleMapSubset(this.collection_list, name);
1019 cleanUpModuleMapSubset(this.cluster_list, name);
1020 cleanUpModuleMapSubset(this.service_list, name);
1021
1022 // can remote collections be in the private coll list ??
1023 }
1024 }
1025 else
1026 {
1027 logger.error("invalid module type: " + type + ", can't remove info about this module");
1028 }
1029
1030 m.cleanUp(); // clean up any open files/connections etc - can cause trouble on windows
1031 m = null;
1032 return true;
1033 }
1034 // else not deactivated
1035 logger.error(name + " module not found");
1036 return false;
1037
1038 }
1039
1040 //*****************************************************************
1041 // auxiliary process methods
1042 //*****************************************************************
1043
1044 /**
1045 * handles requests made to the MessageRouter itself
1046 *
1047 * @param req
1048 * - the request Element- <request>
1049 * @return the result Element - should be <response>
1050 */
1051 protected Element processMessage(Element req)
1052 {
1053
1054 // message for self, should be type=describe/configure at this stage
1055 Document doc = XMLConverter.newDOM();
1056 String type = req.getAttribute(GSXML.TYPE_ATT);
1057 Element response = doc.createElement(GSXML.RESPONSE_ELEM);
1058 response.setAttribute(GSXML.FROM_ATT, "");
1059 if (type.equals(GSXML.REQUEST_TYPE_DESCRIBE))
1060 {
1061 response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_DESCRIBE);
1062 // check the param list
1063 Element param_list = (Element) GSXML.getChildByTagName(req, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
1064 if (param_list == null)
1065 {
1066 response.appendChild(doc.importNode(this.collection_list, true));
1067 response.appendChild(doc.importNode(this.cluster_list, true));
1068 response.appendChild(doc.importNode(this.site_list, true));
1069 response.appendChild(doc.importNode(this.service_list, true));
1070 response.appendChild(doc.importNode(this.metadata_list, true));
1071 return response;
1072 }
1073
1074 NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
1075
1076 // go through the param list and see what components are wanted
1077 for (int i = 0; i < params.getLength(); i++)
1078 {
1079
1080 Element param = (Element) params.item(i);
1081 // Identify the structure information desired
1082 if (param.getAttribute(GSXML.NAME_ATT).equals(GSXML.SUBSET_PARAM))
1083 {
1084 String info = param.getAttribute(GSXML.VALUE_ATT);
1085 if (info.equals(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER))
1086 {
1087 response.appendChild(doc.importNode(this.collection_list, true));
1088 }
1089 else if (info.equals(GSXML.CLUSTER_ELEM + GSXML.LIST_MODIFIER))
1090 {
1091 response.appendChild(doc.importNode(this.cluster_list, true));
1092 }
1093 else if (info.equals(GSXML.SERVICE_ELEM + GSXML.LIST_MODIFIER))
1094 {
1095 response.appendChild(doc.importNode(this.service_list, true));
1096 }
1097 else if (info.equals(GSXML.SITE_ELEM + GSXML.LIST_MODIFIER))
1098 {
1099 response.appendChild(doc.importNode(this.site_list, true));
1100 }
1101 else if (info.equals(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER))
1102 {
1103 response.appendChild(doc.importNode(this.metadata_list, true));
1104 }
1105 }
1106 }
1107 return response;
1108
1109 }
1110
1111 if (type.equals(GSXML.REQUEST_TYPE_SYSTEM))
1112 {
1113
1114 // a list of system requests - should put any error messages
1115 // or success messages into response
1116 NodeList commands = req.getElementsByTagName(GSXML.SYSTEM_ELEM);
1117 Element site_config_elem = null;
1118 boolean success = false;
1119
1120 for (int i = 0; i < commands.getLength(); i++)
1121 {
1122 // all the commands should be Elements
1123 Element elem = (Element) commands.item(i);
1124 String action = elem.getAttribute(GSXML.TYPE_ATT);
1125
1126 if (action.equals(GSXML.SYSTEM_TYPE_PING))
1127 { // ?a=s&sa=ping or ?a=s&sa=ping(&st=collection)&sn=colname
1128
1129 String message = ""; // will be creating the same messages as in GS2's recept/pingaction.cpp
1130 String module_name = elem.getAttribute(GSXML.SYSTEM_MODULE_NAME_ATT);
1131 String module_type = elem.getAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT);
1132
1133 if (module_name.equals(""))
1134 { // server-level ping
1135 message = "Ping succeeded.";
1136 }
1137 else
1138 { // ping at collection level
1139 if (pingModule(module_name))
1140 {
1141 message = "Ping for " + module_name + " succeeded.";
1142 }
1143 else
1144 {
1145 message = "Ping for " + module_name + " did not succeed.";
1146 }
1147 }
1148 Element s = GSXML.createTextElement(doc, GSXML.STATUS_ELEM, message);
1149 response.appendChild(s);
1150 }
1151 //else if (action.equals(GSXML.SYSTEM_TYPE_ISPERSISTENT)) {
1152 // Element s = GSXML.createTextElement(doc, GSXML.STATUS_ELEM, "Persistent: true.");
1153 // response.appendChild(s);
1154 //}
1155 else if (action.equals(GSXML.SYSTEM_TYPE_CONFIGURE))
1156 {
1157 String subset = elem.getAttribute(GSXML.SYSTEM_SUBSET_ATT);
1158 if (subset.equals(""))
1159 {
1160 // need to reconfigure the MR
1161 this.configureLocalSite();
1162 Element s = GSXML.createTextElement(doc, GSXML.STATUS_ELEM, "MessageRouter reconfigured successfully");
1163 response.appendChild(s);
1164
1165 }
1166 else
1167 {
1168 // else it a specific request
1169 if (subset.equals(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER))
1170 {
1171 // get rid of all the old collection stuff (not counting remote ones) before activating all the new ones
1172 cleanUpModuleMapSubset(this.collection_list, null);
1173 cleanUpModuleMapSubset(this.private_collection_list, null);
1174 success = configureCollections();
1175 }
1176 else
1177 {
1178
1179 // need the site config file
1180 if (site_config_elem == null)
1181 {
1182
1183 File configFile = new File(GSFile.siteConfigFile(this.site_home));
1184 if (!configFile.exists())
1185 {
1186 logger.error(" site config file: " + configFile.getPath() + " not found!");
1187 continue;
1188 }
1189 Document site_config_doc = XMLConverter.getDOM(configFile);
1190 if (site_config_doc == null)
1191 {
1192 logger.error(" couldn't parse site config file: " + configFile.getPath());
1193 continue;
1194 }
1195 site_config_elem = site_config_doc.getDocumentElement();
1196 }
1197 if (subset.equals(GSXML.SERVICE_ELEM + GSXML.LIST_MODIFIER))
1198 {
1199 Element service_rack_list = (Element) GSXML.getChildByTagName(site_config_elem, GSXML.SERVICE_CLASS_ELEM + GSXML.LIST_MODIFIER);
1200 cleanUpModuleMapSubset(this.service_list, null);
1201 success = configureServices(service_rack_list);
1202 }
1203 else if (subset.equals(GSXML.CLUSTER_ELEM + GSXML.LIST_MODIFIER))
1204 {
1205 Element cluster_list = (Element) GSXML.getChildByTagName(site_config_elem, GSXML.CLUSTER_ELEM + GSXML.LIST_MODIFIER);
1206 cleanUpModuleMapSubset(this.cluster_list, null);
1207 success = configureClusters(cluster_list);
1208 }
1209 else if (subset.equals(GSXML.SITE_ELEM + GSXML.LIST_MODIFIER))
1210 {
1211 Element site_list = (Element) GSXML.getChildByTagName(site_config_elem, GSXML.SITE_ELEM + GSXML.LIST_MODIFIER);
1212 cleanUpAllExternalSiteInfo();
1213 success = configureExternalSites(site_list);
1214 }
1215 }
1216 String message = null;
1217 if (success)
1218 {
1219 message = subset + "reconfigured successfully";
1220 }
1221 else
1222 {
1223 message = "Error in reconfiguring " + subset;
1224 }
1225 Element s = GSXML.createTextElement(doc, GSXML.STATUS_ELEM, message);
1226 response.appendChild(s);
1227 }
1228
1229 }
1230 else
1231 {
1232 String module_name = elem.getAttribute(GSXML.SYSTEM_MODULE_NAME_ATT);
1233 String module_type = elem.getAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT);
1234
1235 if (action.equals(GSXML.SYSTEM_TYPE_DEACTIVATE))
1236 {
1237 success = deactivateModule(module_type, module_name);
1238 if (success)
1239 {
1240 Element s = GSXML.createTextElement(doc, GSXML.STATUS_ELEM, module_type + ": " + module_name + " deactivated", GSXML.SYSTEM_TYPE_DEACTIVATE, GSXML.SUCCESS);
1241 response.appendChild(s);
1242 }
1243 else
1244 {
1245 Element s = GSXML.createTextElement(doc, GSXML.STATUS_ELEM, module_type + ": " + module_name + " could not be deactivated", GSXML.SYSTEM_TYPE_DEACTIVATE, GSXML.ERROR);
1246 response.appendChild(s);
1247 }
1248
1249 }
1250 else if (action.equals(GSXML.SYSTEM_TYPE_ACTIVATE))
1251 {
1252 // we need to deactivate the module first, in case this is a
1253 // reconfigure
1254 deactivateModule(module_type, module_name);
1255 if (module_type.equals(GSXML.COLLECTION_ELEM))
1256 {
1257 success = activateCollectionByName(module_name);
1258 }
1259 else if (module_type.equals(GSXML.SITE_ELEM))
1260 {
1261 success = activateSiteByName(module_name);
1262 }
1263 else if (module_type.equals(GSXML.CLUSTER_ELEM))
1264 {
1265 success = activateServiceClusterByName(module_name);
1266 }
1267 if (success)
1268 {
1269 Element s = GSXML.createTextElement(doc, GSXML.STATUS_ELEM, module_type + ": " + module_name + " activated", GSXML.SYSTEM_TYPE_ACTIVATE, GSXML.SUCCESS);
1270 response.appendChild(s);
1271 }
1272 else
1273 {
1274 Element s = GSXML.createTextElement(doc, GSXML.STATUS_ELEM, module_type + ": " + module_name + " could not be activated", GSXML.SYSTEM_TYPE_ACTIVATE, GSXML.ERROR);
1275 response.appendChild(s);
1276 }
1277 }
1278 } // else not a configure action
1279 } // for all commands
1280 return response;
1281
1282 } // system type request
1283
1284 // if get here something has gone wrong
1285 String eol = System.getProperty("line.separator");
1286
1287 String mess = "Can't process request:" + eol + " " + XMLConverter.getString(req);
1288 logger.error(mess);
1289 return null;
1290
1291 }
1292
1293 //* Used to copy nodes from one message to another. E.g. copy a response node to the next request. Not sure if this is actually used anywhere yet... */
1294
1295 protected Element modifyMessages(Element request, Element message, Element result)
1296 {
1297 Document doc = XMLConverter.newDOM();
1298 Element response = doc.createElement(GSXML.RESPONSE_ELEM);
1299 response.setAttribute(GSXML.FROM_ATT, "");
1300 response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_MESSAGING);
1301
1302 NodeList commands = request.getElementsByTagName("command");
1303 if (commands == null)
1304 {
1305 logger.error("no commands, " + XMLConverter.getPrettyString(request));
1306 return response;
1307 }
1308 for (int i = 0; i < commands.getLength(); i++)
1309 {
1310 Element action = (Element) commands.item(i);
1311 String type = action.getAttribute(GSXML.TYPE_ATT);
1312 if (type.equals("copyNode"))
1313 {
1314 // copies the from node as a child of to node
1315 String from_path = action.getAttribute("from");
1316 String to_path = action.getAttribute("to");
1317 Element from_node = null;
1318 String from_node_root = GSPath.getFirstLink(from_path);
1319 if (from_node_root.startsWith(GSXML.REQUEST_ELEM))
1320 {
1321 from_node = message;
1322 }
1323 else if (from_node_root.startsWith(GSXML.RESPONSE_ELEM))
1324 {
1325 from_node = result;
1326 }
1327 if (from_node == null)
1328 {
1329 continue;
1330 }
1331 Element to_node = null;
1332 String to_node_root = GSPath.getFirstLink(to_path);
1333 if (to_node_root.startsWith(GSXML.REQUEST_ELEM))
1334 {
1335 to_node = message;
1336 }
1337 else if (to_node_root.startsWith(GSXML.RESPONSE_ELEM))
1338 {
1339 to_node = result;
1340 }
1341 if (to_node == null)
1342 {
1343 continue;
1344 }
1345 // now we know what node to copy where
1346 Node orig_node = GSXML.getNodeByPathIndexed(from_node, from_path);
1347 if (orig_node == null)
1348 {
1349 continue;
1350 }
1351 Node new_parent = GSXML.getNodeByPathIndexed(to_node, to_path);
1352 if (new_parent == null)
1353 {
1354 continue;
1355
1356 }
1357 new_parent.appendChild(to_node.getOwnerDocument().importNode(orig_node, true));
1358 }
1359
1360 else if (type.equals("copyChildren"))
1361 {
1362
1363 }
1364 } // for each command
1365 return response;
1366 }
1367
1368 // ****************************************************
1369 // other methods
1370 // ****************************************************
1371
1372}
Note: See TracBrowser for help on using the repository browser.