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