Changeset 14210 for greenstone3/trunk/src/java
- Timestamp:
- 2007-06-29T13:26:36+12:00 (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
greenstone3/trunk/src/java/org/greenstone/gsdl3/core/MessageRouter.java
r13973 r14210 25 25 26 26 // 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; 27 import org.w3c.dom.Node; 28 import org.w3c.dom.NodeList; 29 import org.w3c.dom.Document; 30 import org.w3c.dom.Element; 31 31 import org.xml.sax.InputSource; 32 32 import javax.xml.parsers.*; … … 37 37 import java.io.StringReader; 38 38 import java.net.Authenticator; 39 import java.net.PasswordAuthentication; 39 import java.net.PasswordAuthentication; 40 40 import java.util.HashMap; 41 41 import java.util.Iterator; … … 45 45 46 46 /** 47 * The hub of a Greenstone system. 47 * The hub of a Greenstone system. 48 48 * 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 50 50 * service or external entity. 51 51 * 52 * contains a map of module objects - may be services, collections, comms 52 * contains a map of module objects - may be services, collections, comms 53 53 * objects talking to other MessageRouters etc. 54 54 * … … 63 63 */ 64 64 public 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; 65 92 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 } 67 287 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 941 974 } 942 975
Note:
See TracChangeset
for help on using the changeset viewer.