source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/DepositorAction.java@ 33699

Last change on this file since 33699 was 33699, checked in by kjdon, 4 years ago

first stab at requiring a user to be logged in to use the depositor, and they must have the correct permissions to access a collection. TODO - for the collection list, only display the collections the user has access to??

  • Property svn:executable set to *
File size: 16.7 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.GSParams;
24import org.greenstone.gsdl3.util.GSXML;
25import org.greenstone.gsdl3.util.GSXSLT;
26import org.greenstone.gsdl3.util.UserContext;
27import org.greenstone.gsdl3.util.XMLConverter;
28import org.greenstone.util.GlobalProperties;
29import org.w3c.dom.Document;
30import org.w3c.dom.Element;
31import org.w3c.dom.Node;
32
33import com.google.gson.Gson;
34import com.google.gson.reflect.TypeToken;
35
36public class DepositorAction extends Action
37{
38 //Sub actions
39 private final String DE_RETRIEVE_WIZARD = "getwizard";
40 private final String DE_DEPOSIT_FILE = "depositfile";
41 private final String DE_CLEAR_CACHE = "clearcache";
42 private final String DE_CLEAR_DATABASE = "cleardatabase";
43
44 // cgi args
45 private final String DE_PAGE_ARG = "dePage";
46 private final String CURRENT_PAGE_ARG = "currentPage";
47 private final String FILE_TO_ADD_ARG = "fileToAdd";
48
49 public Node process(Node message)
50 {
51 Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
52 Document doc = request.getOwnerDocument();
53
54 UserContext uc = new UserContext((Element) request);
55
56 Element responseMessage = doc.createElement(GSXML.MESSAGE_ELEM);
57 Element response = GSXML.createBasicResponse(doc, this.getClass().getSimpleName());
58 responseMessage.appendChild(response);
59
60 addSiteMetadata(response, uc);
61 addInterfaceOptions(response);
62
63 // currently uc might have the wrong username.
64 // TODO - fix this once that is fixed
65 Element userInformation = (Element) GSXML.getChildByTagName(request, GSXML.USER_INFORMATION_ELEM);
66 if (userInformation != null)
67 {
68 String username = userInformation.getAttribute(GSXML.USERNAME_ATT);
69 if (!username.equals("")) {
70 uc.setUsername(username);
71 }
72 String groups = userInformation.getAttribute(GSXML.GROUPS_ATT);
73 if (!groups.equals("")) {
74 uc.setGroups(groups.split(","));
75 }
76 }
77
78 String currentUsername = uc.getUsername();
79
80 // logger.debug("username="+username+", groups = "+groups);
81 if (currentUsername == null || currentUsername.equals(""))
82 {
83
84 // TODO if user is not logged in, push to login page
85 request.setAttribute("subaction", "");
86 GSXML.addError(response, "You need to be logged in to use the depositor");
87 return responseMessage;
88 }
89
90 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
91 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
92
93 String collection = (String) params.get(GSParams.COLLECTION);
94
95 if (collection !=null && !collection.equals("")) {
96 if (!userHasCollectionEditPermissions(collection, uc)) {
97 // we need to reset back to empty subaction here
98 request.setAttribute("subaction", "");
99 logger.error("found collection "+collection+", need to check user groups");
100 GSXML.addError(response, "You are not in the right group to access this collection. Please log in as a different user.");
101 return responseMessage;
102
103 }
104 }
105 int pageNum = -1;
106 boolean pageNumParseFail = false;
107 try
108 {
109 pageNum = Integer.parseInt(((String) params.get(DE_PAGE_ARG)));
110 }
111 catch (Exception ex)
112 {
113 pageNumParseFail = true;
114 }
115
116 int prevPageNum = -1;
117 boolean prevPageNumFail = false;
118 try
119 {
120 prevPageNum = Integer.parseInt((String) params.get(CURRENT_PAGE_ARG));
121 }
122 catch (Exception ex)
123 {
124 prevPageNumFail = true;
125 }
126
127 DerbyWrapper database = new DerbyWrapper(GlobalProperties.getGSDL3Home() + File.separatorChar + "etc" + File.separatorChar + "usersDB");
128 if (pageNumParseFail)
129 {
130 try
131 {
132 pageNum = Integer.parseInt(database.getUserData(currentUsername, "DE___" + collection + "___CACHED_PAGE"));
133 }
134 catch (Exception ex)
135 {
136 pageNum = 1;
137 }
138 }
139
140 int highestVisitedPage = -1;
141 String result = "";
142 int counter = 1;
143 while (result != null)
144 {
145 result = database.getUserData(currentUsername, "DE___" + collection + "___" + counter + "___VISITED_PAGE");
146 if (result != null)
147 {
148 counter++;
149 }
150 }
151 highestVisitedPage = counter - 1;
152 if (highestVisitedPage == 0)
153 {
154 highestVisitedPage = 1;
155 }
156
157 if (pageNum > highestVisitedPage + 1)
158 {
159 pageNum = highestVisitedPage + 1;
160 }
161
162 database.addUserData(currentUsername, "DE___" + collection + "___" + pageNum + "___VISITED_PAGE", "VISITED");
163
164 String subaction = ((Element) request).getAttribute(GSXML.SUBACTION_ATT);
165 if (subaction.toLowerCase().equals(DE_RETRIEVE_WIZARD))
166 {
167 //Save given metadata
168 StringBuilder saveString = new StringBuilder("[");
169 Iterator<String> paramIter = params.keySet().iterator();
170 while (paramIter.hasNext())
171 {
172 String paramName = paramIter.next();
173 if (paramName.startsWith(GSParams.MD_PREFIX))
174 {
175 Object paramValue = params.get(paramName);
176
177 if (paramValue instanceof String)
178 {
179 saveString.append("{name:\"" + paramName + "\", value:\"" + (String) paramValue + "\"},");
180 }
181 else if (paramValue instanceof HashMap)
182 {
183 HashMap<String, String> subMap = (HashMap<String, String>) paramValue;
184 Iterator<String> subKeyIter = subMap.keySet().iterator();
185 while (subKeyIter.hasNext())
186 {
187 String subName = subKeyIter.next();
188 saveString.append("{name:\"" + paramName + "." + subName + "\", value:\"" + subMap.get(subName) + "\"},");
189 }
190 }
191 }
192 }
193 if (saveString.length() > 2)
194 {
195 saveString.deleteCharAt(saveString.length() - 1);
196 saveString.append("]");
197
198 if (!prevPageNumFail)
199 {
200 database.addUserData(currentUsername, "DE___" + collection + "___" + prevPageNum + "___CACHED_VALUES", saveString.toString());
201 }
202 }
203
204 //Construct the xsl
205 Document compiledDepositorFile = null;
206 try
207 {
208 compiledDepositorFile = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
209 }
210 catch (Exception ex)
211 {
212 ex.printStackTrace();
213 }
214 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);
215
216 Element numOfPagesElement = GSXML.getNamedElement(depositorBaseFile.getDocumentElement(), "xsl:variable", "name", "numOfPages");
217 int numberOfPages = Integer.parseInt(numOfPagesElement.getTextContent());
218
219 compiledDepositorFile.appendChild(compiledDepositorFile.importNode(depositorBaseFile.getDocumentElement(), true));
220
221 ArrayList<Document> pageDocs = new ArrayList<Document>();
222 ArrayList<String> pageNames = new ArrayList<String>();
223 for (int i = 1; i <= numberOfPages; i++)
224 {
225 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);
226 pageDocs.add(page);
227
228 Element pageTitleElem = (Element) GSXML.getNamedElement(page.getDocumentElement(), "xsl:variable", "name", "title");
229 pageNames.add(pageTitleElem.getTextContent());
230
231 Element wizardPageElem = (Element) GSXML.getNamedElement(page.getDocumentElement(), "xsl:template", "name", "wizardPage");
232 wizardPageElem.setAttribute("name", "wizardPage" + i);
233 compiledDepositorFile.getDocumentElement().appendChild(compiledDepositorFile.importNode(wizardPageElem, true));
234 }
235
236 //Create the wizard bar
237 Element wizardBarTemplate = GSXML.getNamedElement(compiledDepositorFile.getDocumentElement(), "xsl:template", "name", "wizardBar");
238 Element wizardBar = compiledDepositorFile.createElement("ul");
239 wizardBar.setAttribute("id", "wizardBar");
240 wizardBarTemplate.appendChild(wizardBar);
241
242 for (int i = 0; i < pageNames.size(); i++)
243 {
244 String pageName = pageNames.get(i);
245 Element pageLi = compiledDepositorFile.createElement("li");
246 if (pageNum == i + 1)
247 {
248 pageLi.setAttribute("class", "wizardStepLink ui-state-active ui-corner-all");
249 }
250 else if (i + 1 > highestVisitedPage + 1 && i + 1 > pageNum + 1)
251 {
252 pageLi.setAttribute("class", "wizardStepLink ui-state-disabled ui-corner-all");
253 }
254 else
255 {
256 pageLi.setAttribute("class", "wizardStepLink ui-state-default ui-corner-all");
257 }
258 Element link = compiledDepositorFile.createElement("a");
259 pageLi.appendChild(link);
260
261 link.setAttribute(GSXML.HREF_ATT, "javascript:;");
262 link.setAttribute("page", "" + (i + 1));
263 link.appendChild(compiledDepositorFile.createTextNode(pageName));
264 wizardBar.appendChild(pageLi);
265 }
266
267 //Add a call-template call to the appropriate page in the xsl
268 Element mainDePageElem = GSXML.getNamedElement(compiledDepositorFile.getDocumentElement(), "xsl:template", "match", "/page");
269 Element wizardContainer = GSXML.getNamedElement(mainDePageElem, "div", "id", "wizardContainer");
270 Element formContainer = GSXML.getNamedElement(wizardContainer, "form", "name", "depositorform");
271 Element callToPage = compiledDepositorFile.createElement("xsl:call-template");
272 callToPage.setAttribute("name", "wizardPage" + pageNum);
273 formContainer.appendChild(callToPage);
274
275 Element cachedValueElement = doc.createElement("cachedValues");
276 response.appendChild(cachedValueElement);
277 try
278 {
279 for (int i = pageNum; i > 0; i--)
280 {
281 Element page = doc.createElement("pageCache");
282 page.setAttribute("pageNum", "" + i);
283 String cachedValues = database.getUserData(currentUsername, "DE___" + collection + "___" + i + "___CACHED_VALUES");
284 if (cachedValues != null)
285 {
286 page.appendChild(doc.createTextNode(cachedValues));
287 cachedValueElement.appendChild(page);
288 }
289 }
290 }
291 catch (Exception ex)
292 {
293 ex.printStackTrace();
294 }
295
296 try
297 {
298 Transformer transformer = TransformerFactory.newInstance().newTransformer();
299
300 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");
301 newFileDir.mkdirs();
302
303 File newFile = new File(newFileDir, File.separator + "compiledDepositor.xsl");
304
305 //initialize StreamResult with File object to save to file
306 StreamResult sresult = new StreamResult(new FileWriter(newFile));
307 DOMSource source = new DOMSource(compiledDepositorFile);
308 transformer.transform(source, sresult);
309 }
310 catch (Exception ex)
311 {
312 ex.printStackTrace();
313 }
314 database.closeDatabase();
315 }
316 else if (subaction.toLowerCase().equals(DE_DEPOSIT_FILE))
317 {
318 String fileToAdd = (String) params.get(FILE_TO_ADD_ARG);
319 File tempFile = new File(GlobalProperties.getGSDL3Home() + File.separator + "tmp" + File.separator + fileToAdd);
320 if (tempFile.exists())
321 {
322 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);
323 if (!newFileLocationDir.exists())
324 {
325 newFileLocationDir.mkdir();
326 }
327 File newFileLocation = new File(newFileLocationDir, fileToAdd);
328
329 try
330 {
331 FileUtils.copyFile(tempFile, newFileLocation);
332 }
333 catch (Exception ex)
334 {
335 ex.printStackTrace();
336 GSXML.addError(responseMessage, "Failed to copy the deposited file into the collection.");
337 return responseMessage;
338 }
339
340 HashMap<String, String> metadataMap = new HashMap<String, String>();
341 for (int i = pageNum; i > 0; i--)
342 {
343 String cachedValues = database.getUserData(currentUsername, "DE___" + collection + "___" + i + "___CACHED_VALUES");
344 if (cachedValues != null)
345 {
346 Type type = new TypeToken<List<Map<String, String>>>()
347 {
348 }.getType();
349
350 Gson gson = new Gson();
351 List<Map<String, String>> metadataList = gson.fromJson(cachedValues, type);
352 for (Map<String, String> metadata : metadataList)
353 {
354 metadataMap.put(metadata.get("name"), metadata.get("value"));
355 }
356 }
357 }
358
359 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>";
360 xmlString += "<FileName>.*</FileName><Description>";
361 for (String key : metadataMap.keySet())
362 {
363 xmlString += "<Metadata name=\"" + key.substring("MD___".length()) + "\" mode=\"accumulate\">" + metadataMap.get(key) + "</Metadata>";
364 }
365 xmlString += "</Description></FileSet></DirectoryMetadata>";
366
367 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");
368
369 try
370 {
371 BufferedWriter bw = new BufferedWriter(new FileWriter(metadataFile));
372 bw.write(xmlString);
373 bw.close();
374 }
375 catch (Exception ex)
376 {
377 ex.printStackTrace();
378 }
379
380 Element buildMessage = doc.createElement(GSXML.MESSAGE_ELEM);
381 Element buildRequest = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_PROCESS, "ImportCollection", uc);
382 buildMessage.appendChild(buildRequest);
383
384 Element paramListElem = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
385 buildRequest.appendChild(paramListElem);
386
387 Element collectionParam = doc.createElement(GSXML.PARAM_ELEM);
388 paramListElem.appendChild(collectionParam);
389 collectionParam.setAttribute(GSXML.NAME_ATT, GSXML.COLLECTION_ATT);
390 collectionParam.setAttribute(GSXML.VALUE_ATT, collection);
391
392 Element documentsParam = doc.createElement(GSXML.PARAM_ELEM);
393 paramListElem.appendChild(documentsParam);
394 documentsParam.setAttribute(GSXML.NAME_ATT, "documents");
395 documentsParam.setAttribute(GSXML.VALUE_ATT, fileToAdd);
396
397 Element buildResponseMessage = (Element) this.mr.process(buildMessage);
398
399 response.appendChild(doc.importNode(buildResponseMessage, true));
400 }
401 }
402 else if (subaction.toLowerCase().equals(DE_CLEAR_CACHE))
403 {
404 database.clearUserDataWithPrefix(currentUsername, "DE___");
405 }
406 else if (subaction.toLowerCase().equals(DE_CLEAR_DATABASE))
407 {
408 database.clearUserData();
409 database.clearTrackerData();
410 }
411 else
412 {
413 Element depositorPage = doc.createElement("depositorPage");
414 response.appendChild(depositorPage);
415
416 Element collList = getCollectionsInSite(doc);
417 depositorPage.appendChild(doc.importNode(collList, true));
418 }
419
420 return responseMessage;
421 }
422
423 public Element getCollectionsInSite(Document doc)
424 {
425 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
426 Element request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, "", new UserContext());
427 message.appendChild(request);
428 Element responseMessage = (Element) this.mr.process(message);
429
430 Element response = (Element) GSXML.getChildByTagName(responseMessage, GSXML.RESPONSE_ELEM);
431 Element collectionList = (Element) GSXML.getChildByTagName(response, GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
432
433 return collectionList;
434 }
435
436 // collection must be non-null and non-empty
437 protected boolean userHasCollectionEditPermissions(String collection, UserContext user_context) {
438
439 for (String group : user_context.getGroups()) {
440 // administrator always has permission
441 if (group.equals("administrator")) {
442 return true;
443 }
444 // all-collections-editor can edit any collection
445
446 if (group.equals("all-collections-editor")) {
447 return true;
448 }
449 if (group.equals(collection+"-collection-editor")) {
450 return true;
451 }
452 }
453
454 // haven't found a group with edit permissions
455 return false;
456
457 }
458}
Note: See TracBrowser for help on using the repository browser.