Ignore:
Timestamp:
2007-06-29T13:26:36+12:00 (17 years ago)
Author:
xiao
Message:

accept a specific request from OAIReceptionist and return a list of oai-supported collections (modified in process()); add a method returning the site name bound to this message router (the OAIPMH service needs it thru ServiceRack.java).

File:
1 edited

Legend:

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

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