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

Last change on this file since 22085 was 22085, checked in by sjm84, 14 years ago

Created a util package from classes that could be useful outside of their original packages

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