/* * ServiceRack.java * Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.greenstone.gsdl3.service; // greenstone classes import org.greenstone.gsdl3.util.*; import org.greenstone.gsdl3.core.*; // xml classes import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Element; import org.w3c.dom.Document; import org.xml.sax.InputSource; import javax.xml.parsers.*; import org.apache.xpath.XPathAPI; // general java classes import java.io.Reader; import java.io.StringReader; import java.io.File; import java.util.HashMap; import java.util.ResourceBundle; import java.util.Locale; import java.lang.reflect.Method; import org.apache.log4j.*; /** * ServiceRack - abstract base class for services * * A ServiceRack provides one or more Services. * This base class implements the process method. *Each service is invoked * by a method called process which takes one parameter - the xml request Element, and returns an XML response Element. * for example, the TextQuery service would be invoked by * processTextQuery(Element request) * * @author Katherine Don */ public abstract class ServiceRack implements ModuleInterface { static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.ServiceRack.class.getName()); /** the absolute address of the site home */ protected String site_home =null; /** the http address of the site home */ protected String site_http_address =null; protected String library_name = null; /** the name of the cluster (or collection) that this service belongs to - if any */ protected String cluster_name = null; /** some services can talk back to the message router */ protected MessageRouter router = null; /** a converter class to create Documents etc */ protected XMLConverter converter = null; /** the original config info - if need to store it */ protected Element config_info = null; /** XML element for describe requests - the container doc */ protected Document doc = null; /** XML element for describe requests - list of supported services - this is static */ protected Element short_service_info = null; /** XML element for stylesheet requests - map of service name to format elem */ protected HashMap format_info_map = null; /** A class loader that knows about the collection resources directory * can put properties files, dtds etc in here */ CollectionClassLoader class_loader = null; /** sets the cluster name */ public void setClusterName(String cluster_name) { this.cluster_name = cluster_name; } /** sets the collect name */ public void setCollectionName(String coll_name) { setClusterName(coll_name); } public void cleanUp() {} /** sets the site home */ public void setSiteHome(String site_home) { this.site_home = site_home; } /** sets the site http address */ public void setSiteAddress(String site_address) { this.site_http_address = site_address; } public void setLibraryName(String library_name) { this.library_name = library_name; } public String getLibraryName() { return this.library_name; } /** sets the message router */ public void setMessageRouter(MessageRouter m) { this.router = m; setLibraryName(m.getLibraryName()); } /** the no-args constructor */ public ServiceRack() { this.converter = new XMLConverter(); this.doc = this.converter.newDOM(); this.short_service_info = this.doc.createElement(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER); this.format_info_map = new HashMap(); } /** configure the service module * * @param info the XML node with name equal * to the class name (of the subclass) * * must configure short_service_info_ and service_info_map_ * @return true if configured ok * must be implemented in subclasses */ public boolean configure(Element info) { return configure(info, null); } public boolean configure(Element info, Element extra_info) { // set up the class loader this.class_loader = new CollectionClassLoader(this.getClass().getClassLoader(), this.site_home, this.cluster_name); return true; } /** * Process an XML document - convenience method that uses Strings rather than Elements. just calls process(Element). * * @param xml_in the Document to process - a string * @return the resultant document as a string - contains any error messages * @see String */ public String process(String xml_in) { Document doc = this.converter.getDOM(xml_in); if (doc == null) { logger.error("Couldn't parse request"); logger.error(xml_in); return null; } Node res = process(doc); return this.converter.getString(res); } /** process an XML request in DOM form * * @param message the Node node containing the request * should be * @return an Node with the result XML * @see Node/Element */ public Node process(Node message_node) { Element message = this.converter.nodeToElement(message_node); NodeList requests = message.getElementsByTagName(GSXML.REQUEST_ELEM); Document mess_doc = message.getOwnerDocument(); Element mainResult = this.doc.createElement(GSXML.MESSAGE_ELEM); if (requests.getLength()==0) { // no requests return mainResult; // empty message for now } for (int i=0; i