source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/GeneralAction.java@ 28382

Last change on this file since 28382 was 28382, checked in by davidb, 11 years ago

Elimination of the 'this.doc' field from the Action baseclass and the subclasses that rely on it. For Greenstone3 purposes it is unsafe to create this object in the constructor to the action and then store it for other methods to access. This is because the Greenstone 3 (and in particular calls to 'process' operate in a multi-threaded context, that is managed by the Servlet server (e.g. Tomcat by default). Calls to DOM methods are not guaranteed to be thread safe, this became apparent when we started looking in to an exception that was being thrown, and centred around use of the DOM method 'item(i)'. The change this commit makes is to remove 'this.doc' being stored as a field. A document is now created in the top level of a call to 'process()' and when a DOM reference is needed in a subsequent method an Element variable (typically passed in as a parameter to the method) is used (through 'Document doc = element.getOwnerDocument()') to gain access to the DOM

  • Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line 
1package org.greenstone.gsdl3.action;
2
3import java.io.File;
4import java.io.Serializable;
5import java.util.HashMap;
6
7import javax.xml.parsers.DocumentBuilder;
8import javax.xml.parsers.DocumentBuilderFactory;
9import javax.xml.transform.Result;
10import javax.xml.transform.Transformer;
11import javax.xml.transform.TransformerFactory;
12import javax.xml.transform.dom.DOMSource;
13import javax.xml.transform.stream.StreamResult;
14
15import org.greenstone.gsdl3.util.GSFile;
16import org.greenstone.gsdl3.util.GSParams;
17import org.greenstone.gsdl3.util.GSPath;
18import org.greenstone.gsdl3.util.GSXML;
19import org.greenstone.gsdl3.util.UserContext;
20import org.greenstone.util.GlobalProperties;
21import org.w3c.dom.Document;
22import org.w3c.dom.Element;
23import org.w3c.dom.Node;
24import org.w3c.dom.NodeList;
25
26public class GeneralAction extends Action
27{
28
29 /** process a request */
30 public Node process(Node message_node)
31 {
32 Element message = this.converter.nodeToElement(message_node);
33 Document doc = message.getOwnerDocument();
34
35 // the result
36 Element result = doc.createElement(GSXML.MESSAGE_ELEM);
37 Element page_response = doc.createElement(GSXML.RESPONSE_ELEM);
38 result.appendChild(page_response);
39
40 // assume only one request
41 Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
42 logger.debug(" request=" + this.converter.getString(request));
43
44 UserContext userContext = new UserContext(request);
45
46 // get the param list
47 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
48 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
49
50 if (params.get("configChangeName") != null && params.get("configChangeValue") != null)
51 {
52 String optionName = (String) params.get("configChangeName");
53 String optionValue = (String) params.get("configChangeValue");
54
55 changeConfig(optionName, optionValue);
56 }
57
58 String service_name = (String) params.get(GSParams.SERVICE);
59 String cluster_name = (String) params.get(GSParams.CLUSTER);
60 String response_only_p = (String) params.get(GSParams.RESPONSE_ONLY);
61 boolean response_only = false;
62 if (response_only_p != null)
63 {
64 response_only = (response_only_p.equals("1") ? true : false);
65 }
66 String request_type = (String) params.get(GSParams.REQUEST_TYPE);
67 // what is carried out depends on the request_type
68 // if rt=d, then a describe request is done,
69 // is rt=r, a request and then a describe request is done
70 // if rt=s, a status request is done.
71
72 // if ro=1, then this calls for a process only page - we do the request
73 // (rt should be r or s) and just give the response straight back
74 // without any page processing
75
76 // where to send requests
77 String to;
78 if (cluster_name != null)
79 {
80 to = GSPath.appendLink(cluster_name, service_name);
81 }
82 else
83 {
84 to = service_name;
85 }
86
87 if (request_type.equals("r") || request_type.equals("s") || request_type.equals("ro"))
88 {
89 //do the request
90 Element mr_query_message = doc.createElement(GSXML.MESSAGE_ELEM);
91 Element mr_query_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, to, userContext);
92
93 if (request_type.equals("s"))
94 {
95 mr_query_request.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_STATUS);
96 }
97
98 mr_query_message.appendChild(mr_query_request);
99
100 Element param_list = null;
101 // add in the service params - except the ones only used by the action
102 HashMap service_params = (HashMap) params.get("s1");
103 if (service_params != null)
104 {
105 param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
106 GSXML.addParametersToList(doc, param_list, service_params);
107 mr_query_request.appendChild(param_list);
108 }
109
110 Element userInformation = (Element) GSXML.getChildByTagName(request, GSXML.USER_INFORMATION_ELEM);
111 if (userInformation != null)
112 {
113 mr_query_request.appendChild(doc.importNode(userInformation, true));
114 }
115 mr_query_request.setAttribute("remoteAddress", request.getAttribute("remoteAddress"));
116
117 Element mr_query_response = (Element) this.mr.process(mr_query_message);
118 Element result_response = (Element) GSXML.getChildByTagName(mr_query_response, GSXML.RESPONSE_ELEM);
119
120 if (response_only)
121 {
122 // just send the reponse as is
123 addSiteMetadata(result_response, userContext);
124 addInterfaceOptions(result_response);
125 return result_response;
126 }
127 if (result_response != null)
128 {
129 // else append the contents of the response to the page
130 GSXML.copyAllChildren(page_response, result_response);
131 }
132 }
133
134 // another part of the page is the service description
135
136 // request the service info for the selected service - should be cached
137 Element mr_info_message = doc.createElement(GSXML.MESSAGE_ELEM);
138 Element mr_info_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, to, userContext);
139 mr_info_message.appendChild(mr_info_request);
140 Element mr_info_response = (Element) this.mr.process(mr_info_message);
141
142 String path = GSXML.RESPONSE_ELEM;
143 path = GSPath.appendLink(path, GSXML.SERVICE_ELEM);
144
145 Node desNode = GSXML.getNodeByPath(mr_info_response, path);
146 if (desNode != null)
147 {
148 page_response.appendChild((Element) doc.importNode(desNode, true));
149 }
150
151 addSiteMetadata(page_response, userContext);
152 addInterfaceOptions(page_response);
153
154 return result;
155 }
156
157 protected void changeConfig(String optionName, String optionValue)
158 {
159 if (this.config_params.get(optionName) != null)
160 {
161 this.config_params.put(optionName, optionValue);
162
163 File interfaceConfigFile = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get("interface_name"))));
164
165 Document interfaceXML = null;
166 try
167 {
168 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
169 DocumentBuilder db = dbf.newDocumentBuilder();
170 interfaceXML = db.parse(interfaceConfigFile);
171 Element topElement = interfaceXML.getDocumentElement();
172 Element optionListElem = (Element) GSXML.getChildByTagName(topElement, "optionList");
173
174 NodeList optionList = optionListElem.getElementsByTagName("option");
175
176 for (int i = 0; i < optionList.getLength(); i++)
177 {
178 Element currentOption = (Element) optionList.item(i);
179 if (currentOption.getAttribute(GSXML.NAME_ATT) != null && currentOption.getAttribute(GSXML.NAME_ATT).equals(optionName))
180 {
181 currentOption.setAttribute(GSXML.VALUE_ATT, optionValue);
182 }
183 }
184
185 DOMSource source = new DOMSource(interfaceXML);
186 Result xmlresult = new StreamResult(interfaceConfigFile);
187
188 Transformer transformer = TransformerFactory.newInstance().newTransformer();
189 transformer.transform(source, xmlresult);
190 }
191 catch (Exception ex)
192 {
193 ex.printStackTrace();
194 }
195 }
196 else
197 {
198 logger.error("Could not set param \"" + optionName + "\" to \"" + optionValue + "\" because that option does not exist.");
199 }
200 }
201}
Note: See TracBrowser for help on using the repository browser.