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

Last change on this file since 29869 was 29869, checked in by ak19, 9 years ago

First part of commit for ensuring the user is authenticated when running the scripts used by the online metadata editor. Running metaserver, BuildAndActivate and other GS2Construct.java commands should not be possible from a web browser.

  • Property svn:keywords set to Author Date Id Revision
File size: 32.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;
31
32import org.apache.log4j.Logger;
33import org.greenstone.gsdl3.build.GS2PerlConstructor;
34import org.greenstone.gsdl3.build.GS2PerlListener;
35import org.greenstone.gsdl3.util.GSFile;
36import org.greenstone.gsdl3.util.GSParams;
37import org.greenstone.gsdl3.util.GSPath;
38import org.greenstone.gsdl3.util.GSStatus;
39import org.greenstone.gsdl3.util.GSXML;
40import org.greenstone.gsdl3.util.UserContext;
41import org.greenstone.gsdl3.util.XMLConverter;
42
43import org.w3c.dom.Document;
44import org.w3c.dom.Element;
45import org.w3c.dom.Node;
46import org.w3c.dom.Text;
47
48/**
49 * A Services class for building collections provides a wrapper around the old
50 * perl scripts
51 *
52 * @author Katherine Don
53 */
54public class GS2Construct extends ServiceRack
55{
56
57 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.GS2Construct.class.getName());
58
59 // services offered
60 private static final String NEW_SERVICE = "NewCollection";
61 private static final String ADD_DOC_SERVICE = "AddDocument";
62 private static final String IMPORT_SERVICE = "ImportCollection";
63 private static final String BUILD_SERVICE = "BuildCollection";
64 private static final String ACTIVATE_SERVICE = "ActivateCollection";
65 private static final String BUILD_AND_ACTIVATE_SERVICE = "BuildAndActivateCollection";
66 private static final String DELETE_SERVICE = "DeleteCollection";
67 private static final String RELOAD_SERVICE = "ReloadCollection";
68 private static final String SET_METADATA_SERVICE = "SetMetadata";
69
70 // params used
71 private static final String COL_PARAM = "collection";
72 private static final String NEW_COL_TITLE_PARAM = "collTitle";
73 private static final String NEW_COL_ABOUT_PARAM = "collAbout";
74 private static final String CREATOR_PARAM = "creator";
75 private static final String NEW_FILE_PARAM = "newfile";
76 private static final String PROCESS_ID_PARAM = GSParams.PROCESS_ID;
77 private static final String BUILDTYPE_PARAM = "buildType";
78 private static final String BUILDTYPE_MG = "mg";
79 private static final String BUILDTYPE_MGPP = "mgpp";
80
81 // the list of the collections - store between some method calls
82 private String[] collection_list = null;
83
84 // set of listeners for any construction commands
85 protected Map<String, GS2PerlListener> listeners = null;
86 protected HashMap<String, Boolean> collectionOperationMap = new HashMap<String, Boolean>();
87
88 public GS2Construct()
89 {
90 this.listeners = Collections.synchronizedMap(new HashMap<String, GS2PerlListener>());
91 }
92
93 /** returns a specific service description */
94 protected Element getServiceDescription(Document doc, String service, String lang, String subset)
95 {
96
97 Element description = doc.createElement(GSXML.SERVICE_ELEM);
98 description.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
99 description.setAttribute(GSXML.NAME_ATT, service);
100 if (subset == null || subset.equals(GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER))
101 {
102 description.appendChild(GSXML.createDisplayTextElement(doc, GSXML.DISPLAY_TEXT_NAME, getTextString(service + ".name", lang)));
103 description.appendChild(GSXML.createDisplayTextElement(doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(service + ".description", lang)));
104 description.appendChild(GSXML.createDisplayTextElement(doc, GSXML.DISPLAY_TEXT_SUBMIT, getTextString(service + ".submit", lang)));
105 }
106 if (subset == null || subset.equals(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER))
107 {
108 Element param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
109 description.appendChild(param_list);
110
111 if (service.equals(NEW_SERVICE))
112 {
113
114 Element param = GSXML.createParameterDescription(doc, NEW_COL_TITLE_PARAM, getTextString("param." + NEW_COL_TITLE_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
115 param_list.appendChild(param);
116 param = GSXML.createParameterDescription(doc, CREATOR_PARAM, getTextString("param." + CREATOR_PARAM, lang), GSXML.PARAM_TYPE_STRING, null, null, null);
117 param_list.appendChild(param);
118 param = GSXML.createParameterDescription(doc, NEW_COL_ABOUT_PARAM, getTextString("param." + NEW_COL_ABOUT_PARAM, lang), GSXML.PARAM_TYPE_TEXT, null, null, null);
119 param_list.appendChild(param);
120 String[] types = { BUILDTYPE_MGPP, BUILDTYPE_MG };
121 String[] type_texts = { getTextString("param." + BUILDTYPE_PARAM + "." + BUILDTYPE_MGPP, lang), getTextString("param." + BUILDTYPE_PARAM + "." + BUILDTYPE_MG, lang) };
122
123 param = GSXML.createParameterDescription(doc, BUILDTYPE_PARAM, getTextString("param." + BUILDTYPE_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, BUILDTYPE_MGPP, types, type_texts);
124 param_list.appendChild(param);
125 }
126 else if (service.equals(ACTIVATE_SERVICE) || service.equals(IMPORT_SERVICE) || service.equals(BUILD_SERVICE) || service.equals(RELOAD_SERVICE) || service.equals(DELETE_SERVICE) || service.equals(SET_METADATA_SERVICE))
127 {
128
129 this.collection_list = getCollectionList();
130 Element param = GSXML.createParameterDescription(doc, COL_PARAM, getTextString("param." + COL_PARAM, lang), GSXML.PARAM_TYPE_ENUM_SINGLE, null, this.collection_list, this.collection_list);
131 param_list.appendChild(param);
132 }
133 else
134 {
135 // invalid service name
136 return null;
137 }
138 }
139 return description;
140 }
141
142 // each service must have a method "process<New service name>"
143
144 protected Element processNewCollection(Element request)
145 {
146 if (!userHasCollectionEditPermissions(request)) {
147 Document result_doc = XMLConverter.newDOM();
148 Element result = GSXML.createBasicResponse(result_doc, "processNewCollection");
149 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
150 return result;
151 }
152 return runCommand(request, GS2PerlConstructor.NEW);
153 }
154
155 /** TODO:implement this */
156 protected Element processAddDocument(Element request)
157 {
158 if (!userHasCollectionEditPermissions(request)) {
159 Document result_doc = XMLConverter.newDOM();
160 Element result = GSXML.createBasicResponse(result_doc, "processAddDocument");
161 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
162 return result;
163 }
164
165 Document result_doc = XMLConverter.newDOM();
166 // decode the file name, add it to the import directory
167 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
168 Element response = result_doc.createElement(GSXML.RESPONSE_ELEM);
169 response.setAttribute(GSXML.FROM_ATT, name);
170 Element status = result_doc.createElement(GSXML.STATUS_ELEM);
171 response.appendChild(status);
172 //String lang = request.getAttribute(GSXML.LANG_ATT);
173 //String request_type = request.getAttribute(GSXML.TYPE_ATT);
174 Text t = result_doc.createTextNode("AddDocument: not implemented yet");
175 status.appendChild(t);
176 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
177 return response;
178 }
179
180 protected Element processBuildAndActivateCollection(Element request)
181 {
182 // check permissions
183 if (!userHasCollectionEditPermissions(request)) {
184 Document result_doc = XMLConverter.newDOM();
185 Element result = GSXML.createBasicResponse(result_doc, "processBuildAndActivateCollection");
186 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
187 return result;
188 }
189
190 waitUntilReady(request);
191 Element buildResponse = processBuildCollection(request);
192 if (buildResponse.getElementsByTagName(GSXML.ERROR_ELEM).getLength() > 0)
193 {
194 return buildResponse;
195 }
196
197 Element statusElem = (Element) buildResponse.getElementsByTagName(GSXML.STATUS_ELEM).item(0);
198 String id = statusElem.getAttribute("pid");
199
200 GS2PerlListener currentListener = this.listeners.get(id);
201 int statusCode = currentListener.getStatus();
202 while (!GSStatus.isCompleted(statusCode))
203 {
204 // wait for the process, and keep checking the status code
205 // there is probably a better way to do this.
206 try
207 {
208 Thread.currentThread().sleep(100);
209 }
210 catch (Exception e)
211 { // ignore
212 }
213 statusCode = currentListener.getStatus();
214 }
215
216 Element activateResponse = processActivateCollection(request);
217 signalReady(request);
218 return activateResponse;
219 }
220
221 protected Element processImportCollection(Element request)
222 {
223 if (!userHasCollectionEditPermissions(request)) {
224 Document result_doc = XMLConverter.newDOM();
225 Element result = GSXML.createBasicResponse(result_doc, "processImportCollection");
226 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
227 return result;
228 }
229
230 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
231 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
232
233 if (params == null)
234 {
235 return null;
236 }
237
238 //If we have been requested to only build certain documents then we need to create a manifest file
239 String documentsParam = (String) params.get("documents");
240 if (documentsParam != null && !documentsParam.equals(""))
241 {
242 String s = File.separator;
243 String manifestFolderPath = this.site_home + s + "collect" + s + params.get(COL_PARAM) + s + "manifests";
244 String manifestFilePath = manifestFolderPath + File.separator + "tempManifest.xml";
245
246 File manifestFolderFile = new File(manifestFolderPath);
247 if (!manifestFolderFile.exists())
248 {
249 manifestFolderFile.mkdirs();
250 }
251
252 File manifestFile = new File(manifestFilePath);
253 if (!manifestFile.exists())
254 {
255 try
256 {
257 manifestFile.createNewFile();
258 }
259 catch (Exception ex)
260 {
261 ex.printStackTrace();
262 return null; //Probably should return an actual error
263 }
264 }
265 String[] docList = documentsParam.split(",");
266
267 try
268 {
269 BufferedWriter bw = new BufferedWriter(new FileWriter(manifestFile));
270 bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
271 bw.write("<Manifest>\n");
272 bw.write(" <Index>\n");
273 for (int j = 0; j < docList.length; j++)
274 {
275 bw.write(" <Filename>" + docList[j] + "</Filename>\n");
276 }
277 bw.write(" </Index>\n");
278 bw.write("</Manifest>\n");
279 bw.close();
280 }
281 catch (Exception ex)
282 {
283 ex.printStackTrace();
284 return null; //Probably should return an actual error
285 }
286 }
287
288 return runCommand(request, GS2PerlConstructor.IMPORT);
289 }
290
291 protected Element processBuildCollection(Element request)
292 {
293 if (!userHasCollectionEditPermissions(request)) {
294 Document result_doc = XMLConverter.newDOM();
295 Element result = GSXML.createBasicResponse(result_doc, "processBuildCollection");
296 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
297 return result;
298 }
299
300 return runCommand(request, GS2PerlConstructor.BUILD);
301 }
302
303 protected Element processSetMetadata(Element request)
304 {
305 if (!userHasCollectionEditPermissions(request)) {
306 Document result_doc = XMLConverter.newDOM();
307 Element result = GSXML.createBasicResponse(result_doc, "processSetMetadata");
308 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
309 return result;
310 }
311
312 return runCommand(request, GS2PerlConstructor.SET_METADATA_SERVER);
313 }
314
315 protected Element processActivateCollection(Element request)
316 {
317
318 if (!userHasCollectionEditPermissions(request)) {
319 Document result_doc = XMLConverter.newDOM();
320 Element result = GSXML.createBasicResponse(result_doc, "processActivateCollection");
321 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
322 return result;
323 }
324
325 // this activates the collection on disk. but now we need to tell
326 // the MR about it. but we have to wait until the process is finished.
327 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
328 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
329 String coll_name = (String) params.get(COL_PARAM);
330 String lang = request.getAttribute(GSXML.LANG_ATT);
331
332 Element response = runCommand(request, GS2PerlConstructor.ACTIVATE);
333 Element status = (Element) GSXML.getChildByTagName(response, GSXML.STATUS_ELEM);
334
335 String request_type = request.getAttribute(GSXML.TYPE_ATT);
336 if (request_type.equals(GSXML.REQUEST_TYPE_STATUS))
337 {
338 return response;
339 }
340
341 UserContext userContext = new UserContext(request);
342 systemRequest("delete", coll_name, null, userContext);
343
344 // check for finished
345 int status_code = Integer.parseInt(status.getAttribute(GSXML.STATUS_ERROR_CODE_ATT));
346 if (GSStatus.isCompleted(status_code) && GSStatus.isError(status_code))
347 {
348 // we shouldn't carry out the next bit, just return the response
349 return response;
350 }
351 String id = status.getAttribute(GSXML.STATUS_PROCESS_ID_ATT);
352 GS2PerlListener listener = this.listeners.get(id);
353 if (listener == null)
354 {
355 logger.error("somethings gone wrong, couldn't find the listener");
356 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
357 return response;
358 }
359
360 while (!GSStatus.isCompleted(status_code))
361 {
362 // wait for the process, and keep checking the status code
363 // there is probably a better way to do this.
364 try
365 {
366 Thread.currentThread().sleep(100);
367 }
368 catch (Exception e)
369 { // ignore
370 }
371 status_code = listener.getStatus();
372 }
373
374 // add the rest of the messages to the status node
375 Text t = status.getOwnerDocument().createTextNode("\n" + listener.getUpdate());
376 status.appendChild(t);
377 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(listener.getStatus()));
378 if (GSStatus.isError(status_code))
379 {
380 return response; // without doing the next bit
381 }
382
383 t = status.getOwnerDocument().createTextNode("\n");
384 status.appendChild(t);
385 // once have got here, we assume
386 // the first bit proceeded successfully, now reload the collection
387 systemRequest("reload", coll_name, status, userContext); // this will append more messages to the status, and overwrite the error code att
388 return response;
389
390 }
391
392 protected Element processDeleteCollection(Element request)
393 {
394 if (!userHasCollectionEditPermissions(request)) {
395 Document result_doc = XMLConverter.newDOM();
396 Element result = GSXML.createBasicResponse(result_doc, "processDeleteCollection");
397 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
398 return result;
399 }
400
401 Document result_doc = XMLConverter.newDOM();
402 // the response to send back
403 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
404 Element response = result_doc.createElement(GSXML.RESPONSE_ELEM);
405 response.setAttribute(GSXML.FROM_ATT, name);
406 Element status = result_doc.createElement(GSXML.STATUS_ELEM);
407 response.appendChild(status);
408 Text t = null; // the text node for the error/success message
409 String lang = request.getAttribute(GSXML.LANG_ATT);
410 String request_type = request.getAttribute(GSXML.TYPE_ATT);
411
412 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
413 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
414
415 boolean get_status_only = false;
416 if (request_type.equals(GSXML.REQUEST_TYPE_STATUS))
417 {
418 get_status_only = true;
419 }
420 if (get_status_only)
421 {
422 // 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
423 logger.error("had a status request for delete - this shouldn't happen!!");
424 //t = result_doc.createTextNode("");
425 //status.appendChild(t);
426 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
427 return response;
428 }
429 String coll_name = (String) params.get(COL_PARAM);
430 String[] args = { coll_name };
431 File coll_dir = new File(GSFile.collectionBaseDir(this.site_home, coll_name));
432 // check that the coll is there in the first place
433 if (!coll_dir.exists())
434 {
435 t = result_doc.createTextNode(getTextString("delete.exists_error", lang, args));
436 status.appendChild(t);
437 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
438 return response;
439 }
440
441 // try to delete the directory
442 if (!GSFile.deleteFile(coll_dir))
443 {
444 t = result_doc.createTextNode(getTextString("delete.delete_error", lang, args));
445 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
446 status.appendChild(t);
447 return response;
448 }
449
450 UserContext userContext = new UserContext(request);
451
452 systemRequest("delete", coll_name, status, userContext);
453 return response;
454 }
455
456 protected Element processReloadCollection(Element request)
457 {
458 if (!userHasCollectionEditPermissions(request)) {
459 Document result_doc = XMLConverter.newDOM();
460 Element result = GSXML.createBasicResponse(result_doc, "processReloadCollection");
461 GSXML.addError(result, "This user does not have the required permissions to perform this action.");
462 return result;
463 }
464
465 Document result_doc = XMLConverter.newDOM();
466 // the response to send back
467 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
468 Element response = result_doc.createElement(GSXML.RESPONSE_ELEM);
469 response.setAttribute(GSXML.FROM_ATT, name);
470 Element status = result_doc.createElement(GSXML.STATUS_ELEM);
471 response.appendChild(status);
472 Text t = null; // the text node for the error/success message
473
474 String lang = request.getAttribute(GSXML.LANG_ATT);
475 String request_type = request.getAttribute(GSXML.TYPE_ATT);
476
477 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
478 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
479
480 boolean get_status_only = false;
481 if (request_type.equals(GSXML.REQUEST_TYPE_STATUS))
482 {
483 get_status_only = true;
484 }
485 if (get_status_only)
486 {
487 // reload is synchronous - this makes no sense
488 logger.error("had a status request for reload - this shouldn't happen!!");
489 //t = result_doc.createTextNode("");
490 //status.appendChild(t);
491 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
492 return response;
493 }
494
495 String coll_name = (String) params.get(COL_PARAM);
496
497 UserContext userContext = new UserContext(request);
498
499 systemRequest("reload", coll_name, status, userContext);
500 return response;
501
502 }
503
504 /**
505 * send a configure request to the message router action name should be
506 * "delete" or "reload" response will be put into the status element
507 */
508 protected void systemRequest(String operation, String coll_name, Element status, UserContext userContext)
509 {
510 // send the request to the MR
511 Document doc = XMLConverter.newDOM();
512 Element message = doc.createElement(GSXML.MESSAGE_ELEM);
513 Element request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_SYSTEM, "", userContext);
514 message.appendChild(request);
515 Element command = doc.createElement(GSXML.SYSTEM_ELEM);
516 request.appendChild(command);
517 command.setAttribute(GSXML.SYSTEM_MODULE_TYPE_ATT, GSXML.COLLECTION_ELEM);
518 command.setAttribute(GSXML.SYSTEM_MODULE_NAME_ATT, coll_name);
519
520 if (operation.equals("delete"))
521 {
522 command.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_DEACTIVATE);
523 }
524 else if (operation.equals("reload"))
525 {
526 command.setAttribute(GSXML.TYPE_ATT, GSXML.SYSTEM_TYPE_ACTIVATE);
527 }
528 else
529 {
530 logger.error("invalid action name passed to systemRequest:" + operation);
531 return;
532 }
533 request.appendChild(command);
534 Node response = this.router.process(message); // at the moment, get no info in response so ignore it
535 Text t;
536 String[] args = { coll_name };
537
538 if (status != null)
539 {
540 if (response == null)
541 {
542 t = status.getOwnerDocument().createTextNode(getTextString(operation + ".configure_error", userContext.getLanguage(), args));
543 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
544 status.appendChild(t);
545 return;
546 }
547
548 // if we got here, we have succeeded!
549 t = status.getOwnerDocument().createTextNode(getTextString(operation + ".success", userContext.getLanguage(), args));
550 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.SUCCESS));
551 status.appendChild(t);
552 }
553 }
554
555 /**
556 * configure the service module for now, all services have type=build - need
557 * to think about this
558 */
559 public boolean configure(Element info, Element extra_info)
560 {
561 if (!super.configure(info, extra_info))
562 {
563 return false;
564 }
565
566 logger.info("configuring GS2Construct");
567
568 Element e = null;
569 // hard code in the services for now
570
571 // set up short_service_info_ - for now just has name and type
572
573 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
574 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
575 e.setAttribute(GSXML.NAME_ATT, NEW_SERVICE);
576 this.short_service_info.appendChild(e);
577
578 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
579 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
580 e.setAttribute(GSXML.NAME_ATT, IMPORT_SERVICE);
581 this.short_service_info.appendChild(e);
582
583 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
584 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
585 e.setAttribute(GSXML.NAME_ATT, BUILD_SERVICE);
586 this.short_service_info.appendChild(e);
587
588 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
589 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
590 e.setAttribute(GSXML.NAME_ATT, ACTIVATE_SERVICE);
591 this.short_service_info.appendChild(e);
592
593 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
594 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
595 e.setAttribute(GSXML.NAME_ATT, BUILD_AND_ACTIVATE_SERVICE);
596 this.short_service_info.appendChild(e);
597
598 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
599 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
600 e.setAttribute(GSXML.NAME_ATT, DELETE_SERVICE);
601 this.short_service_info.appendChild(e);
602
603 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
604 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
605 e.setAttribute(GSXML.NAME_ATT, RELOAD_SERVICE);
606 this.short_service_info.appendChild(e);
607
608 //e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
609 //e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
610 //e.setAttribute(GSXML.NAME_ATT, ADD_DOC_SERVICE);
611 //this.short_service_info.appendChild(e);
612
613 e = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
614 e.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
615 e.setAttribute(GSXML.NAME_ATT, SET_METADATA_SERVICE);
616 this.short_service_info.appendChild(e);
617
618 return true;
619 }
620
621 /** returns a response element */
622 protected Element runCommand(Element request, int type)
623 {
624 Document result_doc = XMLConverter.newDOM();
625 // the response to send back
626 String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
627 Element response = result_doc.createElement(GSXML.RESPONSE_ELEM);
628 response.setAttribute(GSXML.FROM_ATT, name);
629 Element status = result_doc.createElement(GSXML.STATUS_ELEM);
630 response.appendChild(status);
631
632 String lang = request.getAttribute(GSXML.LANG_ATT);
633 String request_type = request.getAttribute(GSXML.TYPE_ATT);
634
635 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
636 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
637
638 boolean get_status_only = false;
639 if (request_type.equals(GSXML.REQUEST_TYPE_STATUS))
640 {
641 get_status_only = true;
642 }
643
644 // just check for status messages if that's all that's required
645 if (get_status_only)
646 {
647 String id = (String) params.get(PROCESS_ID_PARAM);
648 status.setAttribute(GSXML.STATUS_PROCESS_ID_ATT, id);
649 GS2PerlListener listener = this.listeners.get(id);
650 if (listener == null)
651 {
652 Text t = result_doc.createTextNode(getTextString("general.process_id_error", lang));
653 status.appendChild(t);
654 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
655 }
656 else
657 {
658 Text t = result_doc.createTextNode(listener.getUpdate());
659 status.appendChild(t);
660 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(listener.getStatus()));
661 // check that we actually should be removing the listener here
662 if (listener.isFinished())
663 { // remove this listener - its job is done
664 this.listeners.remove(id); // not working
665 }
666 }
667 return response;
668
669 }
670
671 // do the actual command
672 String coll_name = null;
673 if (type == GS2PerlConstructor.NEW)
674 {
675 String coll_title = (String) params.get(NEW_COL_TITLE_PARAM);
676 coll_name = createNewCollName(coll_title);
677 }
678 else
679 {
680 coll_name = (String) params.get(COL_PARAM);
681 }
682
683 // makes a paramList of the relevant params
684 Element other_params = extractOtherParams(params, type);
685
686 //create the constructor to do the work
687 GS2PerlConstructor constructor = new GS2PerlConstructor("perl_build");
688 if (!constructor.configure())
689 {
690 Text t = result_doc.createTextNode(getTextString("general.configure_constructor_error", lang));
691 status.appendChild(t);
692 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
693 return response;
694 }
695
696 constructor.setSiteHome(this.site_home);
697 constructor.setCollectionName(coll_name);
698 constructor.setActionType(type);
699 constructor.setProcessParams(other_params);
700 if (type == GS2PerlConstructor.IMPORT)
701 {
702 constructor.setManifestFile(this.site_home + File.separator + "collect" + File.separator + params.get(COL_PARAM) + File.separator + "manifests" + File.separator + "tempManifest.xml");
703 }
704 else if (type == GS2PerlConstructor.SET_METADATA_SERVER) {
705 StringBuffer querystring = new StringBuffer();
706
707 // convert params into a single string again?
708 Set<Map.Entry<String, Serializable>> entries = params.entrySet();
709 Iterator<Map.Entry<String, Serializable>> i = entries.iterator();
710 while(i.hasNext()) {
711
712 Map.Entry<String, Serializable> entry = i.next();
713 String paramname = entry.getKey();
714 paramname = paramname.replace("s1.", ""); // replaces all occurrences
715 if(paramname.equals("collection")) {
716 paramname = "c";
717 }
718 String paramvalue = (String)entry.getValue();
719
720 querystring.append(paramname + "=" + paramvalue);
721 if(i.hasNext()) {
722 querystring.append("&");
723 }
724 }
725 constructor.setQueryString(querystring.toString());
726 }
727
728 GS2PerlListener listener = new GS2PerlListener();
729 constructor.addListener(listener);
730 constructor.start();
731
732 String id = newID();
733 this.listeners.put(id, listener);
734
735 status.setAttribute(GSXML.STATUS_PROCESS_ID_ATT, id);
736 status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ACCEPTED));
737 Text t = result_doc.createTextNode(getTextString("general.process_start", lang));
738 status.appendChild(t);
739 return response;
740 }
741
742 //************************
743 // some helper functions
744 //************************
745
746 /** parse the collect directory and return a list of collection names */
747 protected String[] getCollectionList()
748 {
749
750 File collectDir = new File(GSFile.collectDir(this.site_home));
751 if (!collectDir.exists())
752 {
753 logger.error("couldn't find collect dir: " + collectDir.toString());
754 return null;
755 }
756 logger.info("GS2Construct: reading thru directory " + collectDir.getPath() + " to find collections.");
757 File[] contents = collectDir.listFiles();
758 int num_colls = 0;
759 for (int i = 0; i < contents.length; i++)
760 {
761 if (contents[i].isDirectory() && !contents[i].getName().startsWith("CVS"))
762 {
763 num_colls++;
764 }
765 }
766
767 String[] names = new String[num_colls];
768
769 for (int i = 0, j = 0; i < contents.length; i++)
770 {
771 if (contents[i].isDirectory())
772 {
773 String colName = contents[i].getName();
774 if (!colName.startsWith("CVS"))
775 {
776 names[j] = colName;
777 j++;
778 }
779
780 }
781 }
782
783 return names;
784
785 }
786
787 /** ids used for process id */
788 private int current_id = 0;
789
790 private String newID()
791 {
792 current_id++;
793 return Integer.toString(current_id);
794 }
795
796 /** creates a new short name from the collection title */
797 protected String createNewCollName(String coll_title)
798 {
799
800 String base_name = null;
801 // take the first 6 letters
802 if (coll_title.length() < 6)
803 {
804 base_name = coll_title;
805 }
806 else
807 {
808 base_name = coll_title.substring(0, 6);
809 }
810 File coll_dir = new File(GSFile.collectionBaseDir(this.site_home, base_name));
811 if (!coll_dir.exists())
812 { // this name is ok - not used yet
813 return base_name;
814 }
815
816 // now we have to make a new name until we get a good one
817 // try name1, name2 name3 etc
818 int i = 0;
819 while (coll_dir.exists())
820 {
821 i++;
822 coll_dir = new File(GSFile.collectionBaseDir(this.site_home, base_name + Integer.toString(i)));
823 }
824 return base_name + Integer.toString(i);
825
826 }
827
828 /**
829 * takes the params from the request (in the HashMap) and extracts any that
830 * need to be passed to the constructor and puts them into a paramList
831 * element
832 */
833 protected Element extractOtherParams(HashMap<String, Serializable> params, int type)
834 {
835 Document doc = XMLConverter.newDOM();
836 Element param_list = doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
837 if (type == GS2PerlConstructor.NEW)
838 {
839 Element param = doc.createElement(GSXML.PARAM_ELEM);
840 param.setAttribute(GSXML.NAME_ATT, "creator");
841 param.setAttribute(GSXML.VALUE_ATT, (String) params.get(CREATOR_PARAM));
842
843 param_list.appendChild(param);
844 param = doc.createElement(GSXML.PARAM_ELEM);
845 param.setAttribute(GSXML.NAME_ATT, "about");
846 param.setAttribute(GSXML.VALUE_ATT, (String) params.get(NEW_COL_ABOUT_PARAM));
847 param_list.appendChild(param);
848 param = doc.createElement(GSXML.PARAM_ELEM);
849 param.setAttribute(GSXML.NAME_ATT, "title");
850 param.setAttribute(GSXML.VALUE_ATT, (String) params.get(NEW_COL_TITLE_PARAM));
851 param_list.appendChild(param);
852 param = doc.createElement(GSXML.PARAM_ELEM);
853 param.setAttribute(GSXML.NAME_ATT, "buildtype");
854 param.setAttribute(GSXML.VALUE_ATT, (String) params.get(BUILDTYPE_PARAM));
855 param_list.appendChild(param);
856 return param_list;
857 }
858
859 // other ones dont have params yet
860 return null;
861 }
862
863 protected void waitUntilReady(Element request)
864 {
865 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
866 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
867
868 String collection = (String) params.get(COL_PARAM);
869
870 if (checkCollectionIsNotBusy(collection))
871 {
872 return;
873 }
874
875 while (collectionOperationMap.get(collection) != null)
876 {
877 try
878 {
879 Thread.currentThread().sleep(1000);
880 }
881 catch (Exception ex)
882 {
883 ex.printStackTrace();
884 }
885 }
886 }
887
888 protected void signalReady(Element request)
889 {
890 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
891 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
892
893 String collection = (String) params.get(COL_PARAM);
894
895 collectionOperationMap.remove(collection);
896 }
897
898 protected synchronized boolean checkCollectionIsNotBusy(String collection)
899 {
900 if (collectionOperationMap.get(collection) == null)
901 {
902 collectionOperationMap.put(collection, true);
903 return true;
904 }
905 return false;
906 }
907
908
909 /** Copy from DebugService.userHasEditPermissions
910 This function checks that the user is logged in and that the user
911 is in the right group to edit the collection */
912 protected boolean userHasCollectionEditPermissions(Element request) {
913 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
914 HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
915 String collection = (String) params.get(COL_PARAM); // could be null on newcoll operation
916
917 UserContext context = new UserContext(request);
918 if(collection == null) {
919 return !context.getUsername().equals("");
920 }
921 for (String group : context.getGroups()) {
922 // administrator always has permission
923 if (group.equals("administrator")) {
924 return true;
925 }
926 // all-collections-editor can edit any collection
927 if (!collection.equals("")) {
928 if (group.equals("all-collections-editor")) {
929 return true;
930 }
931 if (group.equals(collection+"-collection-editor")) {
932 return true;
933 }
934 }
935 }
936 // haven't found a group with edit permissions
937 return false;
938
939 }
940}
Note: See TracBrowser for help on using the repository browser.