source: greenstone3/branches/customizingGreenstone3/src/java/org/greenstone/gsdl3/core/MessageRouter.java@ 14713

Last change on this file since 14713 was 14534, checked in by qq6, 17 years ago

set up the library name

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