source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/DepositorAction.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:executable set to *
File size: 14.4 KB
Line 
1package org.greenstone.gsdl3.action;
2
3import java.io.BufferedWriter;
4import java.io.File;
5import java.io.FileWriter;
6import java.io.Serializable;
7import java.lang.reflect.Type;
8import java.util.ArrayList;
9import java.util.HashMap;
10import java.util.Iterator;
11import java.util.List;
12import java.util.Map;
13
14import javax.xml.parsers.DocumentBuilderFactory;
15import javax.xml.transform.Transformer;
16import javax.xml.transform.TransformerFactory;
17import javax.xml.transform.dom.DOMSource;
18import javax.xml.transform.stream.StreamResult;
19
20import org.apache.commons.io.FileUtils;
21import org.greenstone.gsdl3.util.DerbyWrapper;
22import org.greenstone.gsdl3.util.GSConstants;
23import org.greenstone.gsdl3.util.GSXML;
24import org.greenstone.gsdl3.util.GSXSLT;
25import org.greenstone.gsdl3.util.UserContext;
26import org.greenstone.util.GlobalProperties;
27import org.w3c.dom.Document;
28import org.w3c.dom.Element;
29import org.w3c.dom.Node;
30
31import com.google.gson.Gson;
32import com.google.gson.reflect.TypeToken;
33
34public class DepositorAction extends Action
35{
36 //Sub actions
37 private final String DE_RETRIEVE_WIZARD = "getwizard";
38 private final String DE_DEPOSIT_FILE = "depositfile";
39 private final String DE_CLEAR_CACHE = "clearcache";
40 private final String DE_CLEAR_DATABASE = "cleardatabase";
41
42 public Node process(Node message)
43 {
44 Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
45 Document doc = request.getOwnerDocument();
46
47 UserContext uc = new UserContext((Element) request);
48 String currentUsername = uc.getUsername();
49
50 Element responseMessage = doc.createElement(GSXML.MESSAGE_ELEM);
51 Element response = GSXML.createBasicResponse(doc, this.getClass().getSimpleName());
52 responseMessage.appendChild(response);
53
54 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
55 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
56
57 String collection = (String) params.get("c");
58
59 int pageNum = -1;
60 boolean pageNumParseFail = false;
61 try
62 {
63 pageNum = Integer.parseInt(((String) params.get("dePage")));
64 }
65 catch (Exception ex)
66 {
67 pageNumParseFail = true;
68 }
69
70 int prevPageNum = -1;
71 boolean prevPageNumFail = false;
72 try
73 {
74 prevPageNum = Integer.parseInt((String) params.get("currentPage"));
75 }
76 catch (Exception ex)
77 {
78 prevPageNumFail = true;
79 }
80
81 DerbyWrapper database = new DerbyWrapper(GlobalProperties.getGSDL3Home() + File.separatorChar + "etc" + File.separatorChar + "usersDB");
82 if (pageNumParseFail)
83 {
84 try
85 {
86 pageNum = Integer.parseInt(database.getUserData(currentUsername, "DE___" + collection + "___CACHED_PAGE"));
87 }
88 catch (Exception ex)
89 {
90 pageNum = 1;
91 }
92 }
93
94 int highestVisitedPage = -1;
95 String result = "";
96 int counter = 1;
97 while (result != null)
98 {
99 result = database.getUserData(currentUsername, "DE___" + collection + "___" + counter + "___VISITED_PAGE");
100 if (result != null)
101 {
102 counter++;
103 }
104 }
105 highestVisitedPage = counter - 1;
106 if (highestVisitedPage == 0)
107 {
108 highestVisitedPage = 1;
109 }
110
111 if (pageNum > highestVisitedPage + 1)
112 {
113 pageNum = highestVisitedPage + 1;
114 }
115
116 database.addUserData(currentUsername, "DE___" + collection + "___" + pageNum + "___VISITED_PAGE", "VISITED");
117
118 String subaction = ((Element) request).getAttribute(GSXML.SUBACTION_ATT);
119 if (subaction.toLowerCase().equals(DE_RETRIEVE_WIZARD))
120 {
121 //Save given metadata
122 StringBuilder saveString = new StringBuilder("[");
123 Iterator<String> paramIter = params.keySet().iterator();
124 while (paramIter.hasNext())
125 {
126 String paramName = paramIter.next();
127 if (paramName.startsWith("md___"))
128 {
129 Object paramValue = params.get(paramName);
130
131 if (paramValue instanceof String)
132 {
133 saveString.append("{name:\"" + paramName + "\", value:\"" + (String) paramValue + "\"},");
134 }
135 else if (paramValue instanceof HashMap)
136 {
137 HashMap<String, String> subMap = (HashMap<String, String>) paramValue;
138 Iterator<String> subKeyIter = subMap.keySet().iterator();
139 while (subKeyIter.hasNext())
140 {
141 String subName = subKeyIter.next();
142 saveString.append("{name:\"" + paramName + "." + subName + "\", value:\"" + subMap.get(subName) + "\"},");
143 }
144 }
145 }
146 }
147 if (saveString.length() > 2)
148 {
149 saveString.deleteCharAt(saveString.length() - 1);
150 saveString.append("]");
151
152 if (!prevPageNumFail)
153 {
154 database.addUserData(currentUsername, "DE___" + collection + "___" + prevPageNum + "___CACHED_VALUES", saveString.toString());
155 }
156 }
157
158 //Construct the xsl
159 Document compiledDepositorFile = null;
160 try
161 {
162 compiledDepositorFile = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
163 }
164 catch (Exception ex)
165 {
166 ex.printStackTrace();
167 }
168 Document depositorBaseFile = GSXSLT.mergedXSLTDocumentCascade("depositor/depositor.xsl", (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), (ArrayList<String>) this.config_params.get(GSConstants.BASE_INTERFACES), false);
169
170 Element numOfPagesElement = GSXML.getNamedElement(depositorBaseFile.getDocumentElement(), "xsl:variable", "name", "numOfPages");
171 int numberOfPages = Integer.parseInt(numOfPagesElement.getTextContent());
172
173 compiledDepositorFile.appendChild(compiledDepositorFile.importNode(depositorBaseFile.getDocumentElement(), true));
174
175 ArrayList<Document> pageDocs = new ArrayList<Document>();
176 ArrayList<String> pageNames = new ArrayList<String>();
177 for (int i = 1; i <= numberOfPages; i++)
178 {
179 Document page = GSXSLT.mergedXSLTDocumentCascade("depositor/de_page" + i + ".xsl", (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), (ArrayList<String>) this.config_params.get(GSConstants.BASE_INTERFACES), false);
180 pageDocs.add(page);
181
182 Element pageTitleElem = (Element) GSXML.getNamedElement(page.getDocumentElement(), "xsl:variable", "name", "title");
183 pageNames.add(pageTitleElem.getTextContent());
184
185 Element wizardPageElem = (Element) GSXML.getNamedElement(page.getDocumentElement(), "xsl:template", "name", "wizardPage");
186 wizardPageElem.setAttribute("name", "wizardPage" + i);
187 compiledDepositorFile.getDocumentElement().appendChild(compiledDepositorFile.importNode(wizardPageElem, true));
188 }
189
190 //Create the wizard bar
191 Element wizardBarTemplate = GSXML.getNamedElement(compiledDepositorFile.getDocumentElement(), "xsl:template", "name", "wizardBar");
192 Element wizardBar = compiledDepositorFile.createElement("ul");
193 wizardBar.setAttribute("id", "wizardBar");
194 wizardBarTemplate.appendChild(wizardBar);
195
196 for (int i = 0; i < pageNames.size(); i++)
197 {
198 String pageName = pageNames.get(i);
199 Element pageLi = compiledDepositorFile.createElement("li");
200 if (pageNum == i + 1)
201 {
202 pageLi.setAttribute("class", "wizardStepLink ui-state-active ui-corner-all");
203 }
204 else if (i + 1 > highestVisitedPage + 1 && i + 1 > pageNum + 1)
205 {
206 pageLi.setAttribute("class", "wizardStepLink ui-state-disabled ui-corner-all");
207 }
208 else
209 {
210 pageLi.setAttribute("class", "wizardStepLink ui-state-default ui-corner-all");
211 }
212 Element link = compiledDepositorFile.createElement("a");
213 pageLi.appendChild(link);
214
215 link.setAttribute(GSXML.HREF_ATT, "javascript:;");
216 link.setAttribute("page", "" + (i + 1));
217 link.appendChild(compiledDepositorFile.createTextNode(pageName));
218 wizardBar.appendChild(pageLi);
219 }
220
221 //Add a call-template call to the appropriate page in the xsl
222 Element mainDePageElem = GSXML.getNamedElement(compiledDepositorFile.getDocumentElement(), "xsl:template", "match", "/page");
223 Element wizardContainer = GSXML.getNamedElement(mainDePageElem, "div", "id", "wizardContainer");
224 Element formContainer = GSXML.getNamedElement(wizardContainer, "form", "name", "depositorform");
225 Element callToPage = compiledDepositorFile.createElement("xsl:call-template");
226 callToPage.setAttribute("name", "wizardPage" + pageNum);
227 formContainer.appendChild(callToPage);
228
229 Element cachedValueElement = doc.createElement("cachedValues");
230 response.appendChild(cachedValueElement);
231 try
232 {
233 for (int i = pageNum; i > 0; i--)
234 {
235 Element page = doc.createElement("pageCache");
236 page.setAttribute("pageNum", "" + i);
237 String cachedValues = database.getUserData(currentUsername, "DE___" + collection + "___" + i + "___CACHED_VALUES");
238 if (cachedValues != null)
239 {
240 page.appendChild(doc.createTextNode(cachedValues));
241 cachedValueElement.appendChild(page);
242 }
243 }
244 }
245 catch (Exception ex)
246 {
247 ex.printStackTrace();
248 }
249
250 try
251 {
252 Transformer transformer = TransformerFactory.newInstance().newTransformer();
253
254 File newFileDir = new File(GlobalProperties.getGSDL3Home() + File.separator + "sites" + File.separator + this.config_params.get(GSConstants.SITE_NAME) + File.separator + "collect" + File.separator + collection + File.separator + "transform" + File.separator + "depositor");
255 newFileDir.mkdirs();
256
257 File newFile = new File(newFileDir, File.separator + "compiledDepositor.xsl");
258
259 //initialize StreamResult with File object to save to file
260 StreamResult sresult = new StreamResult(new FileWriter(newFile));
261 DOMSource source = new DOMSource(compiledDepositorFile);
262 transformer.transform(source, sresult);
263 }
264 catch (Exception ex)
265 {
266 ex.printStackTrace();
267 }
268 database.closeDatabase();
269 }
270 else if (subaction.toLowerCase().equals(DE_DEPOSIT_FILE))
271 {
272 String fileToAdd = (String) params.get("fileToAdd");
273 File tempFile = new File(GlobalProperties.getGSDL3Home() + File.separator + "tmp" + File.separator + fileToAdd);
274 if (tempFile.exists())
275 {
276 File newFileLocationDir = new File(GlobalProperties.getGSDL3Home() + File.separator + "sites" + File.separator + this.config_params.get(GSConstants.SITE_NAME) + File.separator + "collect" + File.separator + collection + File.separator + "import" + File.separator + fileToAdd);
277 if (!newFileLocationDir.exists())
278 {
279 newFileLocationDir.mkdir();
280 }
281 File newFileLocation = new File(newFileLocationDir, fileToAdd);
282
283 try
284 {
285 FileUtils.copyFile(tempFile, newFileLocation);
286 }
287 catch (Exception ex)
288 {
289 ex.printStackTrace();
290 GSXML.addError(doc, responseMessage, "Failed to copy the deposited file into the collection.");
291 return responseMessage;
292 }
293
294 HashMap<String, String> metadataMap = new HashMap<String, String>();
295 for (int i = pageNum; i > 0; i--)
296 {
297 String cachedValues = database.getUserData(currentUsername, "DE___" + collection + "___" + i + "___CACHED_VALUES");
298 if (cachedValues != null)
299 {
300 Type type = new TypeToken<List<Map<String, String>>>()
301 {
302 }.getType();
303
304 Gson gson = new Gson();
305 List<Map<String, String>> metadataList = gson.fromJson(cachedValues, type);
306 for (Map<String, String> metadata : metadataList)
307 {
308 metadataMap.put(metadata.get("name"), metadata.get("value"));
309 }
310 }
311 }
312
313 String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!DOCTYPE DirectoryMetadata SYSTEM \"http://greenstone.org/dtd/DirectoryMetadata/1.0/DirectoryMetadata.dtd\"><DirectoryMetadata><FileSet>";
314 xmlString += "<FileName>.*</FileName><Description>";
315 for (String key : metadataMap.keySet())
316 {
317 xmlString += "<Metadata name=\"" + key.substring("MD___".length()) + "\" mode=\"accumulate\">" + metadataMap.get(key) + "</Metadata>";
318 }
319 xmlString += "</Description></FileSet></DirectoryMetadata>";
320
321 File metadataFile = new File(GlobalProperties.getGSDL3Home() + File.separator + "sites" + File.separator + this.config_params.get(GSConstants.SITE_NAME) + File.separator + "collect" + File.separator + collection + File.separator + "import" + File.separator + fileToAdd + File.separator + "metadata.xml");
322
323 try
324 {
325 BufferedWriter bw = new BufferedWriter(new FileWriter(metadataFile));
326 bw.write(xmlString);
327 bw.close();
328 }
329 catch (Exception ex)
330 {
331 ex.printStackTrace();
332 }
333
334 Element buildMessage = doc.createElement(GSXML.MESSAGE_ELEM);
335 Element buildRequest = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, "ImportCollection", uc);
336 buildMessage.appendChild(buildRequest);
337
338 Element paramListElem = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
339 buildRequest.appendChild(paramListElem);
340
341 Element collectionParam = doc.createElement(GSXML.PARAM_ELEM);
342 paramListElem.appendChild(collectionParam);
343 collectionParam.setAttribute(GSXML.NAME_ATT, GSXML.COLLECTION_ATT);
344 collectionParam.setAttribute(GSXML.VALUE_ATT, collection);
345
346 Element documentsParam = doc.createElement(GSXML.PARAM_ELEM);
347 paramListElem.appendChild(documentsParam);
348 documentsParam.setAttribute(GSXML.NAME_ATT, "documents");
349 documentsParam.setAttribute(GSXML.VALUE_ATT, fileToAdd);
350
351 Element buildResponseMessage = (Element) this.mr.process(buildMessage);
352
353 response.appendChild(doc.importNode(buildResponseMessage, true));
354 }
355 }
356 else if (subaction.toLowerCase().equals(DE_CLEAR_CACHE))
357 {
358 database.clearUserDataWithPrefix(currentUsername, "DE___");
359 }
360 else if (subaction.toLowerCase().equals(DE_CLEAR_DATABASE))
361 {
362 database.clearUserData();
363 database.clearTrackerData();
364 }
365 else
366 {
367 Element depositorPage = doc.createElement("depositorPage");
368 response.appendChild(depositorPage);
369
370 Element collList = getCollectionsInSite(doc);
371 depositorPage.appendChild(doc.importNode(collList, true));
372 }
373
374 return responseMessage;
375 }
376
377 public Element getCollectionsInSite(Document doc)
378 {
379 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
380 Element request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, "", new UserContext());
381 message.appendChild(request);
382 Element responseMessage = (Element) this.mr.process(message);
383
384 Element response = (Element) GSXML.getChildByTagName(responseMessage, GSXML.RESPONSE_ELEM);
385 Element collectionList = (Element) GSXML.getChildByTagName(response, GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
386
387 return collectionList;
388 }
389}
Note: See TracBrowser for help on using the repository browser.