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

Last change on this file since 14399 was 14399, checked in by xiao, 17 years ago

modify the method configureServices so that if a service class is not found in package org.greenstone.gsdl3.service, try the service name alone in case the package is already specified in the name.

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