source: trunk/gsdl3/src/java/org/greenstone/gsdl3/service/ServiceModule.java@ 3235

Last change on this file since 3235 was 3235, checked in by say1, 22 years ago

added GNU headers to all java files. added @author and @version tags. added a fair number of javadoc comments (but not as many as I probably should).

  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/*
2 * ServiceModule.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.service;
20
21// greenstone classes
22import org.greenstone.gsdl3.util.*;
23import org.greenstone.gsdl3.core.*;
24
25// xml classes
26import org.w3c.dom.Node;
27import org.w3c.dom.Element;
28import org.w3c.dom.Document;
29import org.xml.sax.InputSource;
30import javax.xml.parsers.*;
31import org.apache.xpath.XPathAPI;
32
33// general java classes
34import java.io.Reader;
35import java.io.StringReader;
36import java.io.File;
37import java.util.HashMap;
38
39/**
40 * ServiceModule - abstract base class
41 *
42 * A ServiceModule provides Services to a collection/system.
43 * It may provide more than one Service. for eg
44 * MGGDBMServiceModule may support "DocRetrieve", "TextQuery", "MetadataRetrieve" services
45 *
46 * @author <a href="mailto:[email protected]">Katherine Don</a>
47 * @version $Revision: 3235 $
48 */
49public abstract class ServiceModule
50 implements ModuleInterface
51{
52 /** the absolute address of the site home */
53 protected String site_home_ =null;
54 /** the name of the collection directory that this service belongs to -
55 if any */
56 protected String collection_name_ = null;
57
58 /** some services can talk back to the message router */
59 protected ModuleInterface router_ = null;
60
61 /** a converter class to create Documents etc */
62 protected XMLConverter converter_ = null;
63
64 /** XML element for describe requests - the container doc */
65 protected Document doc_ = null;
66
67 /** XML element for describe requests - list of supported services */
68 protected Element short_service_info_ = null;
69
70 /** XML element for describe requests - map of service name to full
71 description */
72 protected HashMap service_info_map_ = null;
73
74 /** sets the collect name */
75 public void setCollectionName(String coll_name) {
76 collection_name_ = coll_name;
77 }
78
79 /** sets the site home */
80 public void setSiteHome(String site_home) {
81 site_home_ = site_home;
82 }
83
84 /** sets the message router */
85 public void setMessageRouter(ModuleInterface m) {
86 router_ = m;
87 }
88
89 /** the no-args constructor */
90 public ServiceModule() {
91 converter_ = new XMLConverter();
92 doc_ = converter_.newDOM();
93 short_service_info_ = doc_.createElement("serviceList");
94 service_info_map_ = new HashMap();
95 }
96
97 /**
98 * Configure the object. - default method for service modules
99 *
100 * reads either collection (if a collection name has been set), or system
101 * configuration file, and configures itself
102 * this calls configure(Element) with the XML element node from the config
103 * file.
104 * configure(Element) should be used if the config file has already been
105 * parsed. This method will work with any subclass.
106 *
107 * @return true if configure successful, false otherwise.
108 */
109 public boolean configure(){
110
111 if (site_home_==null) {
112 System.err.println("setSiteHome() must be called before configure()");
113 return false;
114 }
115
116 File config_file=null;
117 if (collection_name_ !=null) {
118
119 config_file = GSFile.collectionBuildConfigFile(site_home_, collection_name_);
120 }
121 else {
122 config_file = GSFile.siteConfigFile(site_home_);
123 }
124
125 if (config_file.exists() ) {
126
127 Document doc = converter_.getDOM(config_file);
128
129 try {
130 // get the service list and look for own service
131 // Note: XPathAPI is slow apparently
132 String xpath = "//ServiceModule[@name='"+this.getClass().getName()+"']";
133 System.out.println("xpath="+xpath);
134 Node n = XPathAPI.selectSingleNode(doc, xpath);
135 if (n !=null) {
136 return this.configure((Element)n);
137 }
138 } catch (Exception e) {
139 System.err.println("ServiceModule configure exception: "+e.getMessage());
140 return false;
141 }
142 }
143 System.err.println("ServiceModule error: unable to configure ServiceModule " + this.getClass().getName() );
144 return false;
145
146
147 }
148
149 /** The configure method that does the real work
150 *
151 * @param info the XML node <serviceModule name="XXX"/> with name equal
152 * to the class name (of the subclass)
153 *
154 * must initialise short_service_info_ and service_info_map_
155 * @return true if configured ok
156 * must be implemented in subclasses
157 */
158 abstract public boolean configure(Element info);
159
160 /**
161 * Process an XML document - convenience method that uses Strings rather than Nodes. just calls process(Node).
162 *
163 * @param xml_in the Document to process - a string
164 * @return the resultant document as a string - contains any error messages
165 * @see String
166 */
167 public String process(String xml_in) {
168
169 Document doc = converter_.getDOM(xml_in);
170
171 Node res = process(doc);
172 return converter_.getString(res);
173
174 }
175
176 /** process an XML request in DOM form
177 *
178 * @param xml_in the Element node containing the request
179 * should be <request> or maybe <multipleRequest>?? if more than one
180 * request coming at once
181 * @return an Element with the result XML
182 * @see Element
183 */
184 public Node process(Node xml_in) {
185
186 // check if request is Element or Document - we want to work
187 // with an Element
188 Element request=null;
189
190 short node_type = xml_in.getNodeType();
191 if (node_type == Node.DOCUMENT_NODE) {
192 request = ((Document)xml_in).getDocumentElement();
193 } else if (node_type == Node.ELEMENT_NODE) {
194 request = (Element)xml_in;
195 } else {
196 System.err.println("ServiceModule:process error: input should be an Element or Document!");
197 }
198
199 String req = request.getNodeName();
200 if (!req.equals("request")) {
201 System.err.println("ServiceModule:process - should have been passed a request element, instead was given a "+req+" element!");
202 return null;
203 }
204
205 String type = request.getAttribute("type");
206 String to = GSPath.getFirstLink(request.getAttribute("to"));
207 String info = request.getAttribute("info");
208 if (type.equals("describe")) { // process here, not by subclass
209 if (to.equals("")) { // to="", look at info
210 if (info.equals("serviceList")) {
211 return short_service_info_;
212 }
213 // else error in info field
214 System.err.println("ServiceModule describe request: error in 'info' field, info='"+info+"'.");
215 return null;
216 } else { // describe a particular service
217 if (service_info_map_.containsKey(to)) {
218 return (Element)service_info_map_.get(to);
219 }
220 // else error in to field
221 System.err.println("ServiceModule describe request: error in 'to' field, to='"+to+"'.");
222 return null;
223 }
224 } else { // other type of request, must be processed by the subclass -
225 // send to the service method
226 if (service_info_map_.containsKey(to)) {
227 return processService(to, request);
228 }
229 else {
230 // else error in to field
231 System.err.println("ServiceModule describe request: error in 'to' field, to='"+to+"'.");
232 return null;
233 }
234 }
235
236 }
237
238 /** process method for specific services - must be implemented by all
239 * subclasses
240 * should implement all services supported by the serviceModule except
241 * for describe, which is implemented by this base class
242 *
243 */
244 abstract protected Element processService(String service, Element request);
245
246
247}
Note: See TracBrowser for help on using the repository browser.