source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/XMLDocumentAction.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: 4.2 KB
Line 
1package org.greenstone.gsdl3.action;
2
3import org.greenstone.gsdl3.core.ModuleInterface;
4import org.greenstone.gsdl3.util.*;
5import org.greenstone.gsdl3.service.TEIRetrieve;
6// XML classes
7import org.w3c.dom.Node;
8import org.w3c.dom.NodeList;
9import org.w3c.dom.Text;
10import org.w3c.dom.Document;
11import org.w3c.dom.Element;
12
13import java.util.HashMap;
14import java.util.HashSet;
15import java.util.Vector;
16import java.util.Map;
17import java.util.Iterator;
18import java.io.File;
19import java.io.Serializable;
20
21/** action class for retrieving parts of XML documents */
22public class XMLDocumentAction extends Action
23{
24
25 /**
26 * process - processes a request.
27 */
28 public Node process(Node message_node)
29 {
30 Element message = this.converter.nodeToElement(message_node);
31 Document doc = message.getOwnerDocument();
32
33 // get the request - assume there is only one
34 Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
35
36 // create the return message
37 Element result = doc.createElement(GSXML.MESSAGE_ELEM);
38 Element page_response = doc.createElement(GSXML.RESPONSE_ELEM);
39 result.appendChild(page_response);
40
41 UserContext userContext = new UserContext(request);
42 addSiteMetadata(page_response, userContext);
43 addInterfaceOptions(page_response);
44
45 // extract the params from the cgi-request, and check that we have a coll specified
46 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
47 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
48
49 String collection = (String) params.get(GSParams.COLLECTION);
50 if (collection == null || collection.equals(""))
51 {
52 return result;
53 }
54 String doc_name = (String) params.get(GSParams.DOCUMENT);
55 if (doc_name == null || doc_name.equals(""))
56 {
57 return result;
58 }
59
60 // subaction used to decide if we are returning content or structure
61 String document_mode = request.getAttribute(GSXML.SUBACTION_ATT);
62 String to = null;
63 if (document_mode.equals("text"))
64 {
65 to = GSPath.appendLink(collection, "DocumentContentRetrieve");
66 }
67 else if (document_mode.equals("toc"))
68 {
69 to = GSPath.appendLink(collection, "DocumentStructureRetrieve");
70 }
71 else
72 { // the default is text
73 to = GSPath.appendLink(collection, "DocumentContentRetrieve");
74 }
75
76 // make the request to the collection
77 Element mr_message = doc.createElement(GSXML.MESSAGE_ELEM);
78
79 Element ret_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, to, userContext);
80 mr_message.appendChild(ret_request);
81
82 Element doc_list = doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
83 ret_request.appendChild(doc_list);
84 Element docelem = doc.createElement(GSXML.DOC_NODE_ELEM);
85 docelem.setAttribute(GSXML.NODE_ID_ATT, doc_name);
86 doc_list.appendChild(docelem);
87
88 // also add in a request for the Title metadata
89 to = GSPath.appendLink(collection, "DocumentMetadataRetrieve");
90 Element meta_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, to, userContext);
91 // copy the doc list
92 meta_request.appendChild(doc_list.cloneNode(true));
93 // add in a metadata param
94 Element param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
95 meta_request.appendChild(param_list);
96 Element param = GSXML.createParameter(doc, "metadata", "root_Title");
97 param_list.appendChild(param);
98
99 // add the request to the message
100 mr_message.appendChild(meta_request);
101
102 Element ret_response = (Element) this.mr.process(mr_message);
103 String[] links = { GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER, GSXML.DOC_NODE_ELEM };
104 String path = GSPath.createPath(links);
105 Element doc_node = (Element) doc.importNode(GSXML.getNodeByPath(ret_response, path), true);
106 page_response.appendChild(doc_node);
107
108 // get the metadata list
109 Element meta_response = (Element) ret_response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(1);
110 String[] mlinks = { GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER, GSXML.DOC_NODE_ELEM, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER };
111 path = GSPath.createPath(mlinks);
112
113 Element meta_list = (Element) GSXML.getNodeByPath(meta_response, path);
114 if (meta_list != null)
115 {
116 doc_node.appendChild(doc.importNode(meta_list, true));
117 }
118 return result;
119 }
120
121}
Note: See TracBrowser for help on using the repository browser.