source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Construct.java@ 32892

Last change on this file since 32892 was 32892, checked in by ak19, 5 years ago

Part 1 of 2 commits to do with getting errorCallBack working on documentEditing for determining when changes have been saved or not to decided whether editableInitStates can finally be overwritten with current (saved) values.

  • Property svn:keywords set to Author Date Id Revision
File size: 43.7 KB
Line 
1/*
2 * GS2Construct.java
3 * Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.service;
20
21import java.io.BufferedWriter;
22import java.io.File;
23import java.io.FileWriter;
24import java.io.Serializable;
25import java.util.Collections;
26import java.util.Iterator;
27import java.util.Map.Entry;
28import java.util.HashMap;
29import java.util.Map;
30import java.util.Set;
31import java.util.regex.Matcher;
32import java.util.regex.Pattern;
33
34import org.apache.log4j.Logger;
35import org.greenstone.gsdl3.build.GS2PerlConstructor;
36import org.greenstone.gsdl3.build.GS2PerlListener;
37import org.greenstone.gsdl3.util.GSFile;
38import org.greenstone.gsdl3.util.GSParams;
39import org.greenstone.gsdl3.util.GSPath;
40import org.greenstone.gsdl3.util.GSStatus;
41import org.greenstone.gsdl3.util.GSXML;
42import org.greenstone.gsdl3.util.OID;
43import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
44import org.greenstone.gsdl3.util.UserContext;
45import org.greenstone.gsdl3.util.XMLConverter;
46
47// https://developer.android.com/reference/org/json/JSONObject.html
48// https://developer.android.com/reference/org/json/JSONArray.html
49import org.json.JSONArray;
50import org.json.JSONException;
51import org.json.JSONObject;
52
53
54import org.w3c.dom.Document;
55import org.w3c.dom.Element;
56import org.w3c.dom.Node;
57import org.w3c.dom.Text;
58
59/**
60 * A Services class for building collections provides a wrapper around the old
61 * perl scripts
62 *
63 * @author Katherine Don
64 */
65public class GS2Construct extends ServiceRack
66{
67
68 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2Construct.class.getName());
69
70 // default error message
71 private static final String NO_PERMISSIONS_ERROR = "This user does not have the required permissions to perform this action.";
72
73 // services offered
74 private static final String NEW_SERVICE = "NewCollection";
75 private static final String ADD_DOC_SERVICE = "AddDocument";
76 private static final String IMPORT_SERVICE = "ImportCollection";
77 private static final String BUILD_SERVICE = "BuildCollection";
78 private static final String ACTIVATE_SERVICE = "ActivateCollection";
79 private static final String BUILD_AND_ACTIVATE_SERVICE = "BuildAndActivateCollection";
80 private static final String DELETE_SERVICE = "DeleteCollection";
81 private static final String RELOAD_SERVICE = "ReloadCollection";
82 private static final String MODIFY_METADATA_SERVICE = "ModifyMetadata"; // set or remove metadata
83
84
85 // params used
86 private static final String COL_PARAM = "collection";
87 private static final String NEW_COL_TITLE_PARAM = "collTitle";
88 private static final String NEW_COL_ABOUT_PARAM = "collAbout";
89 private static final String CREATOR_PARAM = "creator";
90 private static final String NEW_FILE_PARAM = "newfile";
91 private static final String PROCESS_ID_PARAM = GSParams.PROCESS_ID;
92 private static final String BUILDTYPE_PARAM = "buildType";
93 private static final String BUILDTYPE_MG = "mg";
94 private static final String BUILDTYPE_MGPP = "mgpp";
95
96 protected static String DATABASE_TYPE = null;
97 protected SimpleCollectionDatabase coll_db = null;
98
99 // the list of the collections - store between some method calls
100 private String[] collection_list = null;
101
102 // set of listeners for any construction commands
103 protected Map<String, GS2PerlListener> listeners = null;
104 protected HashMap<String, Boolean> collectionOperationMap = new HashMap<String, Boolean>();
105
106 public GS2Construct()
107 {
108 this.listeners = Collections.synchronizedMap(new HashMap<String, GS2PerlListener>());
109 }
110
111 // in configure we set up any params that should be saved to the session. At this stage, assuming none should be saved.
112
113 /** returns a specific service description */
114 protected Element getServiceDescription(Document doc, String service, String lang, String subset)
115 {
116
117 Element description = doc.createElement(GSXML.SERVICE_ELEM);
118 description.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
119 description.setAttribute(GSXML.NAME_ATT, service);
120 if (subset == null || subset.equals(GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER))
121 {
122 description.appendChild(GSXML.createDisplayTextElement(doc, GSXML.DISPLAY_TEXT_NAME, getTextString(service + ".name", lang)));
123 description.appendChild(GSXML.createDisplayTextElement(doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(service + ".description", lang)));
124 description.appendChild(GSXML.createDisplayTextElement(doc, GSXML.DISPLAY_TEXT_SUBMIT, getTextString(service + ".submit", lang)));
125 }
126 if (subset == null || subset.equals(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER))
127 {
128 Element param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
129 description.appendChild(param_list);
130
131 if (service.equals(NEW_SERVICE))
132 {
133
134 Element param = GSXML.createParameterDescription(doc, NEW_COL_TITLE_PARAM, getTextString("param." + NEW_COL_TITLE_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
135 param_list.appendChild(param);
136 param = GSXML.createParameterDescription(doc, CREATOR_PARAM, getTextString("param." + CREATOR_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
137 param_list.appendChild(param);
138 param = GSXML.createParameterDescription(doc, NEW_COL_ABOUT_PARAM, getTextString("param." + NEW_COL_ABOUT_PARAM, lang), GSXML.PARAM_TYPE_TEXT, null, null, null);
139 param_list.appendChild(param);
140 String[] types = { BUILDTYPE_MGPP, BUILDTYPE_MG };
141 String[] type_texts = { getTextString("param." + BUILDTYPE_PARAM + "." + BUILDTYPE_MGPP, lang), getTextString("param." + BUILDTYPE_PARAM + "." + BUILDTYPE_MG, lang) };
142
143 param = GSXML.createParameterDescription(doc, BUILDTYPE_PARAM, getTextString("param." + BUILDTYPE_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, BUILDTYPE_MGPP, types, type_texts);
144 param_list.appendChild(param);
145 }
146 else if (service.equals(ACTIVATE_SERVICE) || service.equals(IMPORT_SERVICE) || service.equals(BUILD_SERVICE) || service.equals(RELOAD_SERVICE) || service.equals(DELETE_SERVICE) || service.equals(MODIFY_METADATA_SERVICE))
147 {
148
149 this.collection_list = getCollectionList();
150 Element param = GSXML.createParameterDescription(doc, COL_PARAM, getTextString("param." + COL_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, null, this.collection_list, this.collection_list);
151 param_list.appendChild(param);
152 }
153 else
154 {
155 // invalid service name
156 return null;
157 }
158 }
159 return description;
160 }
161
162 // each service must have a method "process<New service name>"
163
164 protected Element processNewCollection(Element request)
165 {
166 if (!userHasCollectionEditPermissions(request)) {
167 return errorResponse("processNewCollection", NO_PERMISSIONS_ERROR);
168 }
169 return runCommand(request, GS2PerlConstructor.NEW);
170 }
171
172 /** TODO:implement this */
173 protected Element processAddDocument(Element request)
174 {
175 if (!userHasCollectionEditPermissions(request)) {
176 return errorResponse("processAddDocument", NO_PERMISSIONS_ERROR);
177 }
178
179 Document result_doc = XMLConverter.newDOM();
180 // decode the file name, add it to the import directory
181 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
182 Element response = result_doc.createElement(GSXML.RESPONSE_ELEM);
183 response.setAttribute(GSXML.FROM_ATT, name);
184 Element status = result_doc.createElement(GSXML.STATUS_ELEM);
185 response.appendChild(status);
186 //String lang = request.getAttribute(GSXML.LANG_ATT);
187 //String request_type = request.getAttribute(GSXML.TYPE_ATT);
188 Text t = result_doc.createTextNode("AddDocument: not implemented yet");
189 status.appendChild(t);
190 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
191 return response;
192 }
193
194 protected Element processBuildAndActivateCollection(Element request)
195 {
196 // check permissions
197 if (!userHasCollectionEditPermissions(request)) {
198 return errorResponse("processBuildAndActivateCollection", NO_PERMISSIONS_ERROR);
199 }
200
201
202 waitUntilReady(request);
203 Element buildResponse = processBuildCollection(request);
204 if (buildResponse.getElementsByTagName(GSXML.ERROR_ELEM).getLength() > 0)
205 {
206 signalReady(request);
207 return buildResponse;
208 }
209
210 Element statusElem = (Element) buildResponse.getElementsByTagName(GSXML.STATUS_ELEM).item(0);
211 String id = statusElem.getAttribute("pid");
212
213 GS2PerlListener currentListener = this.listeners.get(id);
214 int statusCode = currentListener.getStatus();
215 while (!GSStatus.isCompleted(statusCode))
216 {
217 // wait for the process, and keep checking the status code
218 // there is probably a better way to do this.
219 try
220 {
221 Thread.currentThread().sleep(100);
222 }
223 catch (Exception e)
224 { // ignore
225 }
226 statusCode = currentListener.getStatus();
227 }
228
229 Element activateResponse = processActivateCollection(request);
230 signalReady(request);
231 return activateResponse;
232 }
233
234 protected Element processImportCollection(Element request)
235 {
236 if (!userHasCollectionEditPermissions(request)) {
237 return errorResponse("processImportCollection", NO_PERMISSIONS_ERROR);
238 }
239
240 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
241 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
242
243 if (params == null)
244 {
245 return null;
246 }
247
248 //If we have been requested to only build certain documents then we need to create a manifest file
249 String documentsParam = (String) params.get("documents");
250 if (documentsParam != null && !documentsParam.equals(""))
251 {
252 String s = File.separator;
253 String manifestFolderPath = this.site_home + s + "collect" + s + params.get(COL_PARAM) + s + "manifests";
254 String manifestFilePath = manifestFolderPath + File.separator + "tempManifest.xml";
255
256 File manifestFolderFile = new File(manifestFolderPath);
257 if (!manifestFolderFile.exists())
258 {
259 manifestFolderFile.mkdirs();
260 }
261
262 File manifestFile = new File(manifestFilePath);
263 if (!manifestFile.exists())
264 {
265 try
266 {
267 manifestFile.createNewFile();
268 }
269 catch (Exception ex)
270 {
271 ex.printStackTrace();
272 return null; //Probably should return an actual error
273 }
274 }
275 String[] docList = documentsParam.split(",");
276
277 try
278 {
279 BufferedWriter bw = new BufferedWriter(new FileWriter(manifestFile));
280 bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
281 bw.write("<Manifest>\n");
282 bw.write(" <Index>\n");
283 for (int j = 0; j < docList.length; j++)
284 {
285 bw.write(" <Filename>" + docList[j] + "</Filename>\n");
286 }
287 bw.write(" </Index>\n");
288 bw.write("</Manifest>\n");
289 bw.close();
290 }
291 catch (Exception ex)
292 {
293 ex.printStackTrace();
294 return null; //Probably should return an actual error
295 }
296 }
297
298 return runCommand(request, GS2PerlConstructor.IMPORT);
299 }
300
301 protected Element processBuildCollection(Element request)
302 {
303 if (!userHasCollectionEditPermissions(request)) {
304 return errorResponse("processBuildCollection", NO_PERMISSIONS_ERROR);
305 }
306
307 return runCommand(request, GS2PerlConstructor.BUILD);
308 }
309
310 protected Element processModifyMetadata(Element request)
311 {
312
313 // There are two types of operations whereby metadata gets modified:
314 // - document including document-meta editing: user needs document editing powers
315 // - adding user comments: user just needs an account and needs to be logged in
316 // We handle both cases in this service.
317
318 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
319 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
320
321 String metaserver_command = (String) params.get("a"); // e.g. set-archives-metadata or set-metadata-array
322 boolean supportsSettingMultipleMeta = metaserver_command.equals("set-metadata-array") ? true : false;
323 String json_str = (String) params.get("json"); // String or null if no param named "json"
324
325 String[] docids = null;
326
327
328 if (userHasCollectionEditPermissions(request, params)) { // means user can modify ANY metadata
329
330 // if dealing with an array of meta, then parse out the docids from the json
331 if(supportsSettingMultipleMeta) {
332 docids = getDocIdsWithOptFilter(json_str, null);
333 } // else set-meta operation on single metadata field of single doc,
334 // and docid will be obtained in runCommand() where it's needed
335
336 } else {
337 // check if user logged in
338 // shouldn't be able to do any meta modification if not logged in
339
340 UserContext context = new UserContext(request);
341 if (context.getUsername().equals("")) {
342
343 return errorResponse("processModifyMetadata", "Cannot modify any metadata when not logged in.");
344 } else { // User is logged in at least, see whether they can do any restricted set-meta ops
345 // that are open to regular users (those without permissions to edit this collection).
346 // For now, there's only one restricted set-meta operation open to any logged in users
347 // who don't otherwise have editing permissions for the collection: adding user comments.
348
349 boolean isAddingUserComments = false;
350 Pattern allowedMetaFieldsPattern = Pattern.compile("^(username|usertimestamp|usercomment)$");
351 if(supportsSettingMultipleMeta) {
352
353 docids = getDocIdsWithOptFilter(json_str, allowedMetaFieldsPattern);
354 if(docids != null) {
355 isAddingUserComments = true;
356 }
357 } else {
358 String metaname = (String) params.get("metaname");
359 if(isAllowedToSetMeta(metaname, allowedMetaFieldsPattern)) {
360 isAddingUserComments = true;
361 }
362 }
363
364 if(!isAddingUserComments) { // logged in user is attempting to set meta outside restricted set,
365 // In this case, they're attempting to set meta not related to user comments
366 return errorResponse("processModifyMetadata", NO_PERMISSIONS_ERROR);
367 }
368 }
369 }
370
371 // wait until we can reserve the collection for processing
372 waitUntilReady(request);
373
374
375 // process
376 Element response = runCommand(request, GS2PerlConstructor.MODIFY_METADATA_SERVER, docids);
377
378 if (response.getElementsByTagName(GSXML.ERROR_ELEM).getLength() <= 0) // if no errors, wait for process to finish
379 {
380 Element statusElem = (Element) response.getElementsByTagName(GSXML.STATUS_ELEM).item(0);
381 String id = statusElem.getAttribute("pid");
382
383 GS2PerlListener currentListener = this.listeners.get(id);
384 int statusCode = currentListener.getStatus();
385 while (!GSStatus.isCompleted(statusCode))
386 {
387 // wait for the process, and keep checking the status code
388 // there is probably a better way to do this.
389 try
390 {
391 Thread.currentThread().sleep(100);
392 }
393 catch (Exception e)
394 { // ignore
395 }
396 statusCode = currentListener.getStatus();
397 }
398 }
399
400 Element statusElem = (Element) response.getElementsByTagName(GSXML.STATUS_ELEM).item(0);
401 String statusString = GSXML.getNodeText(statusElem);
402 statusString += " and monitored until done.";
403 // check for errors
404 int status_code = Integer.parseInt(statusElem.getAttribute(GSXML.STATUS_ERROR_CODE_ATT));
405 if (GSStatus.isError(status_code)) {
406 logger.info("Got error status code: " + status_code);
407 statusString += "But got error status code: " + status_code;
408 } else { // check for Construction event errors
409 String id = statusElem.getAttribute("pid");
410 GS2PerlListener currentListener = this.listeners.get(id);
411 status_code = currentListener.getStatus();
412 if (GSStatus.isError(status_code))
413 {
414 logger.info("xxxx Got construction event error. Error status code: " + status_code);
415 statusString += "But got construction event error, status code: " + status_code;
416 // add the rest of the messages to the statusElem node
417 statusString += "\n" + currentListener.getUpdate();
418 statusElem.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(currentListener.getStatus()));
419 }
420 }
421 // can finally set statusString
422 GSXML.setNodeText(statusElem, statusString);
423
424 // release hold on collection
425 signalReady(request);
426 return response;
427
428 }
429
430 protected Element processActivateCollection(Element request)
431 {
432
433 if (!userHasCollectionEditPermissions(request)) {
434 return errorResponse("processActivateCollection", NO_PERMISSIONS_ERROR);
435 }
436
437 // this activates the collection on disk. but now we need to tell
438 // the MR about it. but we have to wait until the process is finished.
439 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
440 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
441 String coll_name = (String) params.get(COL_PARAM);
442 String lang = request.getAttribute(GSXML.LANG_ATT);
443
444 UserContext userContext = new UserContext(request);
445 String request_type = request.getAttribute(GSXML.TYPE_ATT);
446
447 // now we de-activate the collection before running activate.pl, and then re-activate at end
448 // So activate.pl only does the moving, no activation. This way will prevent java from launching
449 // perl, exiting and then leaving dangling file handles (on index/text/col.gdb) in perl.
450 if (!request_type.equals(GSXML.REQUEST_TYPE_STATUS)) {
451 systemRequest("delete", coll_name, null, userContext); // deactivate collection
452 }
453
454 Element response = runCommand(request, GS2PerlConstructor.ACTIVATE); // if request is for STATUS, then this won't run activate.pl
455
456 Element status = (Element) GSXML.getChildByTagName(response, GSXML.STATUS_ELEM);
457
458 // check for finished
459 int status_code = Integer.parseInt(status.getAttribute(GSXML.STATUS_ERROR_CODE_ATT));
460 if (GSStatus.isCompleted(status_code) && GSStatus.isError(status_code))
461 {
462 // we shouldn't carry out the next bit, just return the response
463 return response;
464 }
465 String id = status.getAttribute(GSXML.STATUS_PROCESS_ID_ATT);
466 GS2PerlListener listener = this.listeners.get(id);
467 if (listener == null)
468 {
469 logger.error("somethings gone wrong, couldn't find the listener");
470 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
471 return response;
472 }
473
474 while (!GSStatus.isCompleted(status_code))
475 {
476 // wait for the process, and keep checking the status code
477 // there is probably a better way to do this.
478 try
479 {
480 Thread.currentThread().sleep(100);
481 }
482 catch (Exception e)
483 { // ignore
484 }
485 status_code = listener.getStatus();
486 }
487
488 // add the rest of the messages to the status node
489 Text t = status.getOwnerDocument().createTextNode("\n" + listener.getUpdate());
490 status.appendChild(t);
491 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(listener.getStatus()));
492 if (GSStatus.isError(status_code))
493 {
494 return response; // without doing the next bit
495 }
496
497 t = status.getOwnerDocument().createTextNode("\n");
498 status.appendChild(t);
499 // once have got here, we assume
500 // the first bit proceeded successfully, now reload the collection (sends a collection reactivation request)
501 systemRequest("reload", coll_name, status, userContext); // this will append more messages to the status, and overwrite the error code att
502 return response;
503
504 }
505
506 protected Element processDeleteCollection(Element request)
507 {
508 if (!userHasCollectionEditPermissions(request)) {
509 return errorResponse("processDeleteCollection", NO_PERMISSIONS_ERROR);
510 }
511
512 Document result_doc = XMLConverter.newDOM();
513 // the response to send back
514 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
515 Element response = result_doc.createElement(GSXML.RESPONSE_ELEM);
516 response.setAttribute(GSXML.FROM_ATT, name);
517 Element status = result_doc.createElement(GSXML.STATUS_ELEM);
518 response.appendChild(status);
519 Text t = null; // the text node for the error/success message
520 String lang = request.getAttribute(GSXML.LANG_ATT);
521 String request_type = request.getAttribute(GSXML.TYPE_ATT);
522
523 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
524 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
525
526 boolean get_status_only = false;
527 if (request_type.equals(GSXML.REQUEST_TYPE_STATUS))
528 {
529 get_status_only = true;
530 }
531 if (get_status_only)
532 {
533 // at the moment, delete is synchronous. but it may take ages so should do the command in another thread maybe? in which case we will want to ask for status
534 logger.error("had a status request for delete - this shouldn't happen!!");
535 //t = result_doc.createTextNode("");
536 //status.appendChild(t);
537 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
538 return response;
539 }
540 String coll_name = (String) params.get(COL_PARAM);
541 String[] args = { coll_name };
542 File coll_dir = new File(GSFile.collectionBaseDir(this.site_home, coll_name));
543 // check that the coll is there in the first place
544 if (!coll_dir.exists())
545 {
546 t = result_doc.createTextNode(getTextString("delete.exists_error", lang, args));
547 status.appendChild(t);
548 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
549 return response;
550 }
551
552 // try to delete the directory
553 if (!GSFile.deleteFile(coll_dir))
554 {
555 t = result_doc.createTextNode(getTextString("delete.delete_error", lang, args));
556 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
557 status.appendChild(t);
558 return response;
559 }
560
561 UserContext userContext = new UserContext(request);
562
563 systemRequest("delete", coll_name, status, userContext);
564 return response;
565 }
566
567 protected Element processReloadCollection(Element request)
568 {
569 if (!userHasCollectionEditPermissions(request)) {
570 return errorResponse("processReloadCollection", NO_PERMISSIONS_ERROR);
571 }
572
573 Document result_doc = XMLConverter.newDOM();
574 // the response to send back
575 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
576 Element response = result_doc.createElement(GSXML.RESPONSE_ELEM);
577 response.setAttribute(GSXML.FROM_ATT, name);
578 Element status = result_doc.createElement(GSXML.STATUS_ELEM);
579 response.appendChild(status);
580 Text t = null; // the text node for the error/success message
581
582 String lang = request.getAttribute(GSXML.LANG_ATT);
583 String request_type = request.getAttribute(GSXML.TYPE_ATT);
584
585 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
586 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
587
588 boolean get_status_only = false;
589 if (request_type.equals(GSXML.REQUEST_TYPE_STATUS))
590 {
591 get_status_only = true;
592 }
593 if (get_status_only)
594 {
595 // reload is synchronous - this makes no sense
596 logger.error("had a status request for reload - this shouldn't happen!!");
597 //t = result_doc.createTextNode("");
598 //status.appendChild(t);
599 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
600 return response;
601 }
602
603 String coll_name = (String) params.get(COL_PARAM);
604
605 UserContext userContext = new UserContext(request);
606
607 systemRequest("reload", coll_name, status, userContext);
608 return response;
609
610 }
611
612 /**
613 * send a configure request to the message router action name should be
614 * "delete" or "reload" response will be put into the status element
615 */
616 protected void systemRequest(String operation, String coll_name, Element status, UserContext userContext)
617 {
618 // send the request to the MR
619 Document doc = XMLConverter.newDOM();
620 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
621 Element request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_SYSTEM, "", userContext);
622 message.appendChild(request);
623 Element command = doc.createElement(GSXML.SYSTEM_ELEM);
624 request.appendChild(command);
625 command.setAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT, GSXML.COLLECTION_ELEM);
626 command.setAttribute(GSXML.SYSTEM_MODULE_NAME_ATT, coll_name);
627
628 if (operation.equals("delete"))
629 {
630 command.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_DEACTIVATE);
631 }
632 else if (operation.equals("reload"))
633 {
634 command.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_ACTIVATE);
635 }
636 else
637 {
638 logger.error("invalid action name passed to systemRequest:" + operation);
639 return;
640 }
641 request.appendChild(command);
642 Node response = this.router.process(message); // at the moment, get no info in response so ignore it
643 Text t;
644 String[] args = { coll_name };
645
646 if (status != null)
647 {
648 if (response == null)
649 {
650 t = status.getOwnerDocument().createTextNode(getTextString(operation + ".configure_error", userContext.getLanguage(), args));
651 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
652 status.appendChild(t);
653 return;
654 }
655
656 // if we got here, we have succeeded!
657 t = status.getOwnerDocument().createTextNode(getTextString(operation + ".success", userContext.getLanguage(), args));
658 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.SUCCESS));
659 status.appendChild(t);
660 }
661 }
662
663 /**
664 * configure the service module for now, all services have type=build - need
665 * to think about this
666 */
667 public boolean configure(Element info, Element extra_info)
668 {
669 if (!super.configure(info, extra_info))
670 {
671 return false;
672 }
673
674 logger.info("configuring GS2Construct");
675
676 Element e = null;
677 // hard code in the services for now
678
679 // set up short_service_info_ - for now just has name and type
680
681 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
682 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
683 e.setAttribute(GSXML.NAME_ATT, NEW_SERVICE);
684 this.short_service_info.appendChild(e);
685
686 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
687 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
688 e.setAttribute(GSXML.NAME_ATT, IMPORT_SERVICE);
689 this.short_service_info.appendChild(e);
690
691 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
692 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
693 e.setAttribute(GSXML.NAME_ATT, BUILD_SERVICE);
694 this.short_service_info.appendChild(e);
695
696 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
697 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
698 e.setAttribute(GSXML.NAME_ATT, ACTIVATE_SERVICE);
699 this.short_service_info.appendChild(e);
700
701 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
702 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
703 e.setAttribute(GSXML.NAME_ATT, BUILD_AND_ACTIVATE_SERVICE);
704 this.short_service_info.appendChild(e);
705
706 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
707 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
708 e.setAttribute(GSXML.NAME_ATT, DELETE_SERVICE);
709 this.short_service_info.appendChild(e);
710
711 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
712 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
713 e.setAttribute(GSXML.NAME_ATT, RELOAD_SERVICE);
714 this.short_service_info.appendChild(e);
715
716 //e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
717 //e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
718 //e.setAttribute(GSXML.NAME_ATT, ADD_DOC_SERVICE);
719 //this.short_service_info.appendChild(e);
720
721 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
722 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
723 e.setAttribute(GSXML.NAME_ATT, MODIFY_METADATA_SERVICE);
724 this.short_service_info.appendChild(e);
725
726 return true;
727 }
728
729 protected Element runCommand(Element request, int type) {
730 return runCommand(request, type, null);
731 }
732
733 /** returns a response element */
734 protected Element runCommand(Element request, int type, String[] docids)
735 {
736 Document result_doc = XMLConverter.newDOM();
737 // the response to send back
738 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
739 Element response = result_doc.createElement(GSXML.RESPONSE_ELEM);
740 response.setAttribute(GSXML.FROM_ATT, name);
741 Element status = result_doc.createElement(GSXML.STATUS_ELEM);
742 response.appendChild(status);
743
744 String lang = request.getAttribute(GSXML.LANG_ATT);
745 String request_type = request.getAttribute(GSXML.TYPE_ATT);
746
747 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
748 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
749
750 boolean get_status_only = false;
751 if (request_type.equals(GSXML.REQUEST_TYPE_STATUS))
752 {
753 get_status_only = true;
754 }
755
756 // just check for status messages if that's all that's required
757 if (get_status_only)
758 {
759 String id = (String) params.get(PROCESS_ID_PARAM);
760 status.setAttribute(GSXML.STATUS_PROCESS_ID_ATT, id);
761 GS2PerlListener listener = this.listeners.get(id);
762 if (listener == null)
763 {
764 Text t = result_doc.createTextNode(getTextString("general.process_id_error", lang));
765 status.appendChild(t);
766 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
767 }
768 else
769 {
770 Text t = result_doc.createTextNode(listener.getUpdate());
771 status.appendChild(t);
772 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(listener.getStatus()));
773 // check that we actually should be removing the listener here
774 if (listener.isFinished())
775 { // remove this listener - its job is done
776 this.listeners.remove(id); // not working
777 }
778 }
779 return response;
780
781 }
782
783 // do the actual command
784 String coll_name = null;
785 if (type == GS2PerlConstructor.NEW)
786 {
787 String coll_title = (String) params.get(NEW_COL_TITLE_PARAM);
788 coll_name = createNewCollName(coll_title);
789 }
790 else
791 {
792 coll_name = (String) params.get(COL_PARAM);
793 }
794
795 // makes a paramList of the relevant params
796 Element other_params = extractOtherParams(params, type);
797
798 //create the constructor to do the work
799 GS2PerlConstructor constructor = new GS2PerlConstructor("perl_build");
800 if (!constructor.configure())
801 {
802 Text t = result_doc.createTextNode(getTextString("general.configure_constructor_error", lang));
803 status.appendChild(t);
804 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
805 return response;
806 }
807
808 constructor.setSiteHome(this.site_home);
809 constructor.setLibraryName(this.library_name);
810 constructor.setCollectionName(coll_name);
811 constructor.setActionType(type);
812 constructor.setProcessParams(other_params);
813 if (type == GS2PerlConstructor.IMPORT)
814 {
815 constructor.setManifestFile(this.site_home + File.separator + "collect" + File.separator + params.get(COL_PARAM) + File.separator + "manifests" + File.separator + "tempManifest.xml");
816 }
817 else if (type == GS2PerlConstructor.MODIFY_METADATA_SERVER) {
818 StringBuffer querystring = new StringBuffer();
819
820 // convert params into a single string again?
821 Set<Map.Entry<String, Serializable>> entries = params.entrySet();
822 Iterator<Map.Entry<String, Serializable>> i = entries.iterator();
823
824 String oid = null;
825
826 while (i.hasNext()) {
827
828 Map.Entry<String, Serializable> entry = i.next();
829 String paramname = entry.getKey();
830 paramname = paramname.replace("s1.", ""); // replaces all occurrences
831 if (paramname.equals("collection")) {
832 paramname = "c";
833 }
834 if (paramname.equals("d")){
835 oid = (String) entry.getValue();
836 }
837
838 String paramvalue = (String) entry.getValue();
839
840 querystring.append(paramname + "=" + paramvalue);
841 if (i.hasNext()) {
842 querystring.append("&");
843 }
844 }
845
846 if(oid != null) { // if we have only one oid
847 markDocumentInFlatDatabase("R", coll_name, OID.getTop(oid));
848 } else if (docids != null) { // check if we are dealing with many doc ids, as cold in theory happen when set-metadata-array is called
849
850 for(int index = 0; index < docids.length; index++) {
851 String docid = docids[index];
852 markDocumentInFlatDatabase("R", coll_name, OID.getTop(docid));
853 }
854 } else {
855 String msg = getTextString("general.no_valid_docid_error", lang);
856 logger.error("*** " + msg);
857 Text t = result_doc.createTextNode(msg);
858 status.appendChild(t);
859 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
860 return response;
861 }
862
863 constructor.setQueryString(querystring.toString());
864 }
865
866 GS2PerlListener listener = new GS2PerlListener();
867 constructor.addListener(listener);
868 constructor.start();
869
870 String id = newID();
871 this.listeners.put(id, listener);
872
873 status.setAttribute(GSXML.STATUS_PROCESS_ID_ATT, id);
874 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ACCEPTED));
875 Text t = result_doc.createTextNode(getTextString("general.process_start", lang));
876 status.appendChild(t);
877 return response;
878 }
879
880 //************************
881 // some helper functions
882 //************************
883
884 /** parse the collect directory and return a list of collection names */
885 protected String[] getCollectionList()
886 {
887
888 File collectDir = new File(GSFile.collectDir(this.site_home));
889 if (!collectDir.exists())
890 {
891 logger.error("couldn't find collect dir: " + collectDir.toString());
892 return null;
893 }
894 logger.info("GS2Construct: reading thru directory " + collectDir.getPath() + " to find collections.");
895 File[] contents = collectDir.listFiles();
896 int num_colls = 0;
897 for (int i = 0; i < contents.length; i++)
898 {
899 if (contents[i].isDirectory() && !contents[i].getName().startsWith("CVS"))
900 {
901 num_colls++;
902 }
903 }
904
905 String[] names = new String[num_colls];
906
907 for (int i = 0, j = 0; i < contents.length; i++)
908 {
909 if (contents[i].isDirectory())
910 {
911 String colName = contents[i].getName();
912 if (!colName.startsWith("CVS"))
913 {
914 names[j] = colName;
915 j++;
916 }
917
918 }
919 }
920
921 return names;
922
923 }
924
925 /** ids used for process id */
926 private int current_id = 0;
927
928 private String newID()
929 {
930 current_id++;
931 return Integer.toString(current_id);
932 }
933
934 /** creates a new short name from the collection title */
935 protected String createNewCollName(String coll_title)
936 {
937
938 String base_name = null;
939 // take the first 6 letters
940 if (coll_title.length() < 6)
941 {
942 base_name = coll_title;
943 }
944 else
945 {
946 base_name = coll_title.substring(0, 6);
947 }
948 File coll_dir = new File(GSFile.collectionBaseDir(this.site_home, base_name));
949 if (!coll_dir.exists())
950 { // this name is ok - not used yet
951 return base_name;
952 }
953
954 // now we have to make a new name until we get a good one
955 // try name1, name2 name3 etc
956 int i = 0;
957 while (coll_dir.exists())
958 {
959 i++;
960 coll_dir = new File(GSFile.collectionBaseDir(this.site_home, base_name + Integer.toString(i)));
961 }
962 return base_name + Integer.toString(i);
963
964 }
965
966 /**
967 * takes the params from the request (in the HashMap) and extracts any that
968 * need to be passed to the constructor and puts them into a paramList
969 * element
970 */
971 protected Element extractOtherParams(HashMap<String, Serializable> params, int type)
972 {
973 Document doc = XMLConverter.newDOM();
974 Element param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
975 if (type == GS2PerlConstructor.NEW)
976 {
977 Element param = doc.createElement(GSXML.PARAM_ELEM);
978 param.setAttribute(GSXML.NAME_ATT, "creator");
979 param.setAttribute(GSXML.VALUE_ATT, (String) params.get(CREATOR_PARAM));
980
981 param_list.appendChild(param);
982 param = doc.createElement(GSXML.PARAM_ELEM);
983 param.setAttribute(GSXML.NAME_ATT, "about");
984 param.setAttribute(GSXML.VALUE_ATT, (String) params.get(NEW_COL_ABOUT_PARAM));
985 param_list.appendChild(param);
986 param = doc.createElement(GSXML.PARAM_ELEM);
987 param.setAttribute(GSXML.NAME_ATT, "title");
988 param.setAttribute(GSXML.VALUE_ATT, (String) params.get(NEW_COL_TITLE_PARAM));
989 param_list.appendChild(param);
990 param = doc.createElement(GSXML.PARAM_ELEM);
991 param.setAttribute(GSXML.NAME_ATT, "buildtype");
992 param.setAttribute(GSXML.VALUE_ATT, (String) params.get(BUILDTYPE_PARAM));
993 param_list.appendChild(param);
994 return param_list;
995 }
996
997 // other ones dont have params yet
998 return null;
999 }
1000
1001 protected void waitUntilReady(Element request)
1002 {
1003 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
1004 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
1005
1006 String collection = (String) params.get(COL_PARAM);
1007
1008 if (checkCollectionIsNotBusy(collection))
1009 {
1010 return;
1011 }
1012
1013 while (!checkCollectionIsNotBusy(collection)) // When the collection ceases to be busy, we place a hold on it
1014 {
1015 try
1016 {
1017 Thread.currentThread().sleep(1000);
1018 }
1019 catch (Exception ex)
1020 {
1021 ex.printStackTrace();
1022 }
1023 }
1024 }
1025
1026 protected void signalReady(Element request)
1027 {
1028 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
1029 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
1030
1031 String collection = (String) params.get(COL_PARAM);
1032
1033 collectionOperationMap.remove(collection);
1034 }
1035
1036 // If collection is NOT busy, then reserve it
1037 protected synchronized boolean checkCollectionIsNotBusy(String collection)
1038 {
1039 if (collectionOperationMap.get(collection) == null)
1040 {
1041 collectionOperationMap.put(collection, true);
1042 return true;
1043 }
1044 return false;
1045 }
1046
1047 protected boolean isAllowedToSetMeta(String metaname, Pattern allowedMetaFieldsPattern)
1048 {
1049 if(allowedMetaFieldsPattern == null) { // null when user has edit permissions, so they can set any meta
1050 ///logger.info("### User has permissions to set any meta.");
1051 return true;
1052 }
1053 if(metaname == null) {
1054 ///logger.info("### Can't check null metaname against pattern");
1055 return false;
1056 }
1057
1058 Matcher m = allowedMetaFieldsPattern.matcher(metaname);
1059 if(!m.matches()) {
1060 ///logger.info("### metaname: " + metaname + " doesn't match allowed allowed fields: " + allowedMetaFieldsPattern.toString());
1061 return false;
1062 } else {
1063 return true;
1064 }
1065 }
1066
1067 protected String[] getDocIdsWithOptFilter(String json_str, Pattern filterFields) // boolean strictOrPermissible
1068 {
1069 if(json_str == null) {
1070 logger.error("### Shouldn't be happening: null json string");
1071 return null;
1072 }
1073
1074 String[] docids = null;
1075
1076 // check that the name of each metadata being set matches the pattern filterFields.
1077 // The presence of any other meta means something other than adding user comments is being attempted,
1078 // which is invalid
1079 try {
1080
1081 JSONArray docInfoList = new JSONArray(json_str);
1082 docids = new String[docInfoList.length()];
1083 for(int index = 0; index < docInfoList.length(); index++) {
1084 JSONObject docInfo = docInfoList.getJSONObject(index);
1085 if(docInfo.has("metatable")) { // should exist for metadata arrays
1086
1087 docids[index] = docInfo.getString("docid"); // should exist if metatable existed
1088
1089 ///logger.info("@@@ Found docid: " + docids[index]);
1090
1091 JSONArray metatable = docInfo.getJSONArray("metatable");
1092 for(int i = 0; i < metatable.length(); i++) {
1093 JSONObject meta = metatable.getJSONObject(i);
1094
1095 String metaname = meta.getString("metaname");
1096 ///logger.info("### metaname: " + metaname);
1097
1098 if(!isAllowedToSetMeta(metaname, filterFields)) {
1099 return null;
1100 }
1101 }
1102 }
1103 }
1104 } catch(JSONException jsonex) {
1105 logger.error("Exception when parsing json string: " + json_str);
1106 logger.error(jsonex);
1107
1108 }
1109
1110 // if we're here, then it means that the JSON only asked for username|usercomment|usertimestamp meta
1111 // meaning that the setmeta operation was a valid user comment operation.
1112 // In that case, we have a docid for which we need to add a user comment
1113 // set-metadata-array can take more docids, but doesn't happen for a user comment. And one comment
1114 // is added at a time, but 3 meta fields are set for each comment: username, usercomment and timestamp
1115 // hence the use of set-meta-array.
1116 return docids;
1117
1118 }
1119
1120 protected Element errorResponse(String serviceName, String errorMsg) {
1121 Document result_doc = XMLConverter.newDOM();
1122 Element result = GSXML.createBasicResponse(result_doc, serviceName);
1123 GSXML.addError(result, errorMsg);
1124 return result;
1125 }
1126
1127 /** Copy from DebugService.userHasEditPermissions
1128 This function checks that the user is logged in and that the user
1129 is in the right group to edit the collection */
1130 protected boolean userHasCollectionEditPermissions(Element request) {
1131 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
1132 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
1133
1134 return userHasCollectionEditPermissions(request, params);
1135
1136 }
1137
1138 protected boolean userHasCollectionEditPermissions(Element request, HashMap<String, Serializable> params) {
1139 String collection = (String) params.get(COL_PARAM); // could be null on newcoll operation
1140
1141
1142 UserContext context = new UserContext(request);
1143 if(collection == null) {
1144 return !context.getUsername().equals("");
1145 }
1146
1147 /*
1148 // FOR DEBUGGING
1149 Set<Map.Entry<String, Serializable>> entries = params.entrySet();
1150 Iterator<Map.Entry<String, Serializable>> i = entries.iterator();
1151
1152 StringBuffer parametersLine = new StringBuffer();
1153 while (i.hasNext()) {
1154
1155 Map.Entry<String, Serializable> entry = i.next();
1156 String paramname = entry.getKey();
1157 String paramvalue = (String) entry.getValue();
1158
1159 parametersLine.append("\t" + paramname + ": " + paramvalue + "\n");
1160 }
1161
1162 logger.info("XXXXXXXXXXXXX PARAMETERS:\n" + parametersLine);
1163 */
1164
1165 for (String group : context.getGroups()) {
1166 // administrator always has permission
1167 if (group.equals("administrator")) {
1168 return true;
1169 }
1170 // all-collections-editor can edit any collection
1171 if (!collection.equals("")) {
1172 if (group.equals("all-collections-editor")) {
1173 return true;
1174 }
1175 if (group.equals(collection+"-collection-editor")) {
1176 return true;
1177 }
1178 }
1179 }
1180 // haven't found a group with edit permissions
1181 return false;
1182
1183 }
1184 protected void markDocumentInFlatDatabase(String mark, String collection, String oid) {
1185
1186 Document msg_doc = XMLConverter.newDOM();
1187 Element message = msg_doc.createElement(GSXML.MESSAGE_ELEM);
1188 UserContext userContext = new UserContext();
1189 Element query_request = GSXML.createBasicRequest(msg_doc, GSXML.REQUEST_TYPE_DESCRIBE , collection, userContext);
1190 message.appendChild(query_request);
1191 Element result = (Element) this.router.process(message);
1192 Element resp_elem = (Element) GSXML.getChildByTagName(result, GSXML.RESPONSE_ELEM);
1193 Element coll_elem = (Element) GSXML.getChildByTagName(resp_elem, GSXML.COLLECTION_ELEM);
1194 String dbtype = coll_elem.getAttribute(GSXML.DB_TYPE_ATT);
1195
1196 SimpleCollectionDatabase coll_db = new SimpleCollectionDatabase(dbtype);
1197 if (!coll_db.databaseOK())
1198 {
1199 logger.error("Couldn't create the collection database of type " + dbtype);
1200 return;
1201 }
1202
1203 // Open database for reading. It may not exist if collection is pre-built without archives (such as demo collections)
1204 String coll_db_file = GSFile.archivesDatabaseFile(this.site_home, collection, dbtype);
1205 if (!coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ))
1206 {
1207 logger.error("Could not open collection archives database. Database doesn't exist or else somebody's already using it?");
1208 return;
1209 }
1210 // now we know we have an archives folder
1211 String old_value = coll_db.getValue(oid);
1212 String new_value = "<index-status>" + mark;
1213 if(old_value == null) {
1214 logger.error("### null old_value in flat DB for oid " + oid);
1215 } else {
1216 new_value = old_value.replace("<index-status>B", "<index-status>" + mark);
1217 logger.info("### Replacing db entry for oid " + oid + " which has old_value " + old_value);
1218 logger.info("### with new value " + new_value);
1219
1220 }
1221 // Close database for reading
1222 coll_db.closeDatabase();
1223
1224 if (!coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.WRITE))
1225 {
1226 logger.error("Could not open collection archives database. Somebody already using this database!");
1227 return;
1228 }
1229
1230 coll_db.setValue(oid, new_value);
1231
1232 coll_db.closeDatabase();
1233 }
1234}
Note: See TracBrowser for help on using the repository browser.