Changeset 25746


Ignore:
Timestamp:
2012-06-05T15:37:14+12:00 (12 years ago)
Author:
sjm84
Message:

Reformatted this file

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/MessageRouter.java

    r25727 r25746  
    4949/**
    5050 * The hub of a Greenstone system.
    51  *
     51 * 
    5252 * Accepts XML requests (via process method of ModuleInterface) and routes them
    5353 * to the appropriate collection or service or external entity.
    54  *
     54 * 
    5555 * contains a map of module objects - may be services, collections, comms
    5656 * objects talking to other MessageRouters etc.
    57  *
    58  *
     57 * 
     58 * 
    5959 * @author Katherine Don
    6060 * @version $Revision$
     
    6363 * @see ServiceRack
    6464 * @see Communicator
    65  *
    66  * Since some service classes are moved into a separate directory in order for
    67  * 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 they
    69  * 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.
    7070 */
    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  
     71public 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
    11811414}
    1182 
    1183 
Note: See TracChangeset for help on using the changeset viewer.