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

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

modify to let it recognize the .svn directory (besides CVS) when activating the collections by name

  • Property svn:keywords set to Author Date Id Revision
File size: 36.3 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: 14262 $
58 * @see ModuleInterface
59 * @see Collection
60 * @see ServiceRack
61 * @see Communicator
62 *
63 */
64public 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;
92
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 }
287
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") && !colName.startsWith(".svn")) {
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
974}
975
976
Note: See TracBrowser for help on using the repository browser.