source: gs3-extensions/vm-manager/trunk/src/src/java/org/greenstone/gsdl3/action/VMManagerAction.java@ 38655

Last change on this file since 38655 was 38655, checked in by davidb, 4 months ago

Preliminary work on a VM Manager action, imprinted from DepositorAction

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