source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/build/GS2PerlConstructor.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: 15.0 KB
Line 
1package org.greenstone.gsdl3.build;
2
3// greenstome classes
4import org.greenstone.gsdl3.util.*;
5import org.greenstone.util.Misc;
6import org.greenstone.util.GlobalProperties;
7
8// xml classes
9import org.w3c.dom.Element;
10import org.w3c.dom.NodeList;
11
12//general java classes
13import java.io.BufferedReader;
14import java.io.BufferedWriter;
15import java.io.FileWriter;
16import java.io.InputStreamReader;
17import java.io.File;
18import java.util.ArrayList;
19import java.util.Vector;
20
21import org.apache.log4j.*;
22
23/**
24 * CollectionConstructor class for greenstone 2 compatible building it uses the
25 * perl scripts to do the building stuff
26 */
27public class GS2PerlConstructor extends CollectionConstructor
28{
29 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.build.GS2PerlConstructor.class.getName());
30
31 public static final int NEW = 0;
32 public static final int IMPORT = 1;
33 public static final int BUILD = 2;
34 public static final int ACTIVATE = 3;
35 public static final int SET_METADATA_SERVER = 4;
36
37 /**
38 * gsdlhome for greenstone 2 - we use the perl modules and building scripts
39 * from there
40 */
41 protected String gsdl2home = null;
42 /** gsdlhome for gsdl3 - shouldn't need this eventually ?? */
43 protected String gsdl3home = null;
44 /** gsdlos for greenstone 2 */
45 protected String gsdlos = null;
46 /** the path environment variable */
47 protected String path = null;
48
49 public GS2PerlConstructor(String name)
50 {
51 super(name);
52 }
53
54 /** retrieves the necessary environment variables */
55 public boolean configure()
56 {
57 // try to get the environment variables
58 this.gsdl3home = GlobalProperties.getGSDL3Home();
59 this.gsdl2home = this.gsdl3home + File.separator + ".." + File.separator + "gs2build";
60 this.gsdlos = Misc.getGsdlOS();
61
62 this.path = System.getenv("PATH");
63
64 if (this.gsdl2home == null)
65 {
66 System.err.println("You must have gs2build installed, and GSDLHOME set for GS2Perl building to work!!");
67 return false;
68 }
69 if (this.gsdl3home == null || this.gsdlos == null)
70 {
71 System.err.println("You must have GSDL3HOME and GSDLOS set for GS2Perl building to work!!");
72 return false;
73 }
74 if (this.path == null)
75 {
76 System.err.println("You must have the PATH set for GS2Perl building to work!!");
77 return false;
78 }
79 return true;
80 }
81
82 public void run()
83 {
84 String msg;
85 ConstructionEvent evt;
86 if (this.process_type == -1)
87 {
88 msg = "Error: you must set the action type";
89 evt = new ConstructionEvent(this, GSStatus.ERROR, msg);
90 sendMessage(evt);
91 return;
92 }
93 if (this.site_home == null)
94 {
95 msg = "Error: you must set site_home";
96 evt = new ConstructionEvent(this, GSStatus.ERROR, msg);
97 sendMessage(evt);
98 return;
99 }
100 if (this.process_type != NEW && this.collection_name == null)
101 {
102 msg = "Error: you must set collection_name";
103 evt = new ConstructionEvent(this, GSStatus.ERROR, msg);
104 sendMessage(evt);
105 return;
106 }
107
108 switch (this.process_type)
109 {
110 case NEW:
111 newCollection();
112 break;
113 case IMPORT:
114 importCollection();
115 break;
116 case BUILD:
117 buildCollection();
118 break;
119 case ACTIVATE:
120 activateCollection();
121 break;
122 case SET_METADATA_SERVER:
123 setMetadataForCollection();
124 break;
125 default:
126 msg = "wrong type of action specified!";
127 evt = new ConstructionEvent(this, GSStatus.ERROR, msg);
128 sendMessage(evt);
129 break;
130 }
131 }
132
133 protected void newCollection()
134 {
135 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection construction: new collection."));
136 Vector<String> command = new Vector<String>();
137 command.add("gs2_mkcol.pl");
138 command.add("-site");
139 command.add(this.site_home);
140 command.add("-collectdir");
141 command.add(GSFile.collectDir(this.site_home));
142 command.addAll(extractParameters(this.process_params));
143 command.add(this.collection_name);
144 String[] command_str = {};
145 command_str = command.toArray(command_str);
146 if (runPerlCommand(command_str))
147 {
148 // success!! - need to send the final completed message
149 sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
150 } // else an error message has already been sent, do nothing
151
152 }
153
154 protected void importCollection()
155 {
156 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection construction: import collection."));
157 Vector<String> command = new Vector<String>();
158
159 String perlPath = GlobalProperties.getProperty("perl.path", "perl");
160 if (perlPath.charAt(perlPath.length() - 1) != File.separatorChar)
161 {
162 perlPath = perlPath + File.separator;
163 }
164
165 command.add(perlPath + "perl");
166 command.add("-S");
167 command.add(GlobalProperties.getGS2Build() + File.separator + "bin" + File.separator + "script" + File.separator + "import.pl");
168 if (this.manifest_file != null)
169 {
170 command.add("-keepold");
171 command.add("-manifest");
172 command.add(this.manifest_file);
173 }
174 command.add("-site");
175 command.add(this.site_name);
176 command.add("-collectdir");
177 command.add(GSFile.collectDir(this.site_home));
178 command.addAll(extractParameters(this.process_params));
179 command.add(this.collection_name);
180 String[] command_str = {};
181 command_str = command.toArray(command_str);
182
183 if (runPerlCommand(command_str))
184 {
185 // success!! - need to send the final completed message
186 sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
187 } // else an error message has already been sent, do nothing
188 }
189
190 protected void buildCollection()
191 {
192 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection construction: build collection."));
193 Vector<String> command = new Vector<String>();
194
195 String perlPath = GlobalProperties.getProperty("perl.path", "perl");
196 if (perlPath.charAt(perlPath.length() - 1) != File.separatorChar)
197 {
198 perlPath = perlPath + File.separator;
199 }
200
201 command.add(perlPath + "perl");
202 command.add("-S");
203 command.add(GlobalProperties.getGS2Build() + File.separator + "bin" + File.separator + "script" + File.separator + "buildcol.pl");
204 command.add("-site");
205 command.add(this.site_name);
206 command.add("-collectdir");
207 command.add(GSFile.collectDir(this.site_home));
208 command.add("-removeold"); // saves some seconds processing time when this flag's added in explicitly
209 command.addAll(extractParameters(this.process_params));
210 command.add(this.collection_name);
211
212 String[] command_str = {};
213 command_str = command.toArray(command_str);
214
215 if (runPerlCommand(command_str))
216 {
217 // success!! - need to send the final completed message
218 sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
219 }// else an error message has already been sent, do nothing
220 }
221
222 protected void activateCollection()
223 {
224 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection construction: activate collection."));
225
226 // first check that we have a building directory
227 // (don't want to bother running activate.pl otherwise)
228 File build_dir = new File(GSFile.collectionBuildDir(this.site_home, this.collection_name));
229 if (!build_dir.exists())
230 {
231 sendMessage(new ConstructionEvent(this, GSStatus.ERROR, "build dir doesn't exist!"));
232 return;
233 }
234
235 /*
236
237 // move building to index
238 File index_dir = new File(GSFile.collectionIndexDir(this.site_home, this.collection_name));
239 if (index_dir.exists())
240 {
241 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "deleting index directory"));
242 GSFile.deleteFile(index_dir);
243 if (index_dir.exists())
244 {
245 sendMessage(new ConstructionEvent(this, GSStatus.ERROR, "index directory still exists!"));
246 return;
247 }
248 }
249
250 GSFile.moveDirectory(build_dir, index_dir);
251 if (!index_dir.exists())
252 {
253 sendMessage(new ConstructionEvent(this, GSStatus.ERROR, "index dir wasn't created!"));
254 }
255
256 // success!! - need to send the final completed message
257 sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
258 */
259
260 // Running activate.pl instead of making java move building to index as above
261 // circumvents the issue of the jdbm .lg log file (managed by TransactionManager)
262 // in index dir not getting deleted at times. The perl code is able to delete this
263 // sucessfully consistently during testing, whereas java at times is unable to delete it.
264 Vector<String> command = new Vector<String>();
265
266 String perlPath = GlobalProperties.getProperty("perl.path", "perl");
267 if (perlPath.charAt(perlPath.length() - 1) != File.separatorChar)
268 {
269 perlPath = perlPath + File.separator;
270 }
271
272 command.add(perlPath + "perl");
273 command.add("-S");
274 command.add(GlobalProperties.getGS2Build() + File.separator + "bin" + File.separator + "script" + File.separator + "activate.pl");
275 command.add("-site");
276 command.add(this.site_name);
277 command.add("-collectdir");
278 command.add(GSFile.collectDir(this.site_home));
279 command.add("-removeold"); // saves some seconds processing time when this flag's added in explicitly
280 command.addAll(extractParameters(this.process_params));
281 command.add(this.collection_name);
282
283 String[] command_str = {};
284 command_str = command.toArray(command_str);
285
286 if (runPerlCommand(command_str))
287 {
288 // success!! - need to send the final completed message
289 sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
290 }// else an error message has already been sent, do nothing
291
292 }
293
294
295 protected void setMetadataForCollection()
296 {
297 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "Collection metadata: setMetadata for collection."));
298
299 Vector<String> command = new Vector<String>();
300
301 String perlPath = GlobalProperties.getProperty("perl.path", "perl");
302 if (perlPath.charAt(perlPath.length() - 1) != File.separatorChar)
303 {
304 perlPath = perlPath + File.separator;
305 }
306
307 String cgi_directory = GlobalProperties.getGSDL3Home() + File.separator + "WEB-INF" + File.separator + "cgi";
308 command.add(perlPath + "perl");
309 command.add("-S");
310 //command.add(GlobalProperties.getGSDL3Home() + File.separator + "WEB-INF" + File.separator + "cgi" + File.separator + "metadata-server.pl");
311 command.add(cgi_directory + File.separator + "metadata-server.pl");
312
313 // Need to set QUERY_STRING and REQUEST_METHOD=GET in environment
314 // http://www.cgi101.com/class/ch3/text.html
315 String[] envvars = {
316 "QUERY_STRING=" + this.query_string,
317 "REQUEST_METHOD=GET"
318 };
319
320 String[] command_str = {};
321 command_str = command.toArray(command_str);
322
323 // http://www.cgi101.com/class/ch3/text.html
324 // setenv QUERY_STRING and REQUEST_METHOD = GET.
325 if (runPerlCommand(command_str, envvars, new File(cgi_directory)))
326 //new File(GlobalProperties.getGSDL3Home() + File.separator + "WEB-INF" + File.separator + "cgi")))
327 {
328 // success!! - need to send the final completed message
329 sendProcessComplete(new ConstructionEvent(this, GSStatus.COMPLETED, ""));
330 }// else an error message has already been sent, do nothing
331
332 }
333
334 /** extracts all the args from the xml and returns them in a Vector */
335 protected Vector<String> extractParameters(Element param_list)
336 {
337
338 Vector<String> args = new Vector<String>();
339 if (param_list == null)
340 {
341 return args; // return an empty vector
342 }
343 NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
344
345 for (int i = 0; i < params.getLength(); i++)
346 {
347 Element p = (Element) params.item(i);
348 String name = p.getAttribute(GSXML.NAME_ATT);
349 String value = p.getAttribute(GSXML.VALUE_ATT);
350 if (!name.equals(""))
351 {
352 args.add("-" + name);
353 if (!value.equals(""))
354 {
355 args.add(value);
356 }
357 }
358 }
359
360 return args;
361 }
362
363 /** returns true if completed correctly, false otherwise */
364 protected boolean runPerlCommand(String[] command) {
365 return runPerlCommand(command, null, null);
366 }
367
368 protected boolean runPerlCommand(String[] command, String[] envvars, File dir)
369 {
370 int sepIndex = this.gsdl3home.lastIndexOf(File.separator);
371 String srcHome = this.gsdl3home.substring(0, sepIndex);
372
373 ArrayList<String> args = new ArrayList<String>();
374 args.add("GSDLHOME=" + this.gsdl2home);
375 args.add("GSDL3HOME=" + this.gsdl3home);
376 args.add("GSDL3SRCHOME=" + srcHome);
377 args.add("GSDLOS=" + this.gsdlos);
378 args.add("GSDL-RUN-SETUP=true");
379 args.add("PERL_PERTURB_KEYS=0");
380
381 if(envvars != null) {
382 for(int i = 0; i < envvars.length; i++) {
383 args.add(envvars[i]);
384 }
385 }
386
387 for (String a : System.getenv().keySet())
388 {
389 args.add(a + "=" + System.getenv(a));
390 }
391
392 String command_str = "";
393 for (int i = 0; i < command.length; i++)
394 {
395 command_str = command_str + command[i] + " ";
396 }
397
398 sendMessage(new ConstructionEvent(this, GSStatus.INFO, "command = " + command_str));
399 try
400 {
401 Runtime rt = Runtime.getRuntime();
402 sendProcessBegun(new ConstructionEvent(this, GSStatus.ACCEPTED, "starting"));
403 Process prcs = (dir == null)
404 ? rt.exec(command, args.toArray(new String[args.size()]))
405 : rt.exec(command, args.toArray(new String[args.size()]), dir);
406
407 InputStreamReader eisr = new InputStreamReader(prcs.getErrorStream());
408 InputStreamReader stdinisr = new InputStreamReader(prcs.getInputStream());
409 BufferedReader ebr = new BufferedReader(eisr);
410 BufferedReader stdinbr = new BufferedReader(stdinisr);
411 // Captures the std err of a program and pipes it into
412 // std in of java
413
414 File logDir = new File(GSFile.collectDir(this.site_home) + File.separator + this.collection_name + File.separator + "log");
415 if (!logDir.exists())
416 {
417 logDir.mkdir();
418 }
419
420 BufferedWriter bw = new BufferedWriter(new FileWriter(GSFile.collectDir(this.site_home) + File.separator + this.collection_name + File.separator + "log" + File.separator + "build_log." + (System.currentTimeMillis()) + ".txt"));
421 bw.write("Document Editor Build \n");
422
423 bw.write("Command = " + command_str + "\n");
424
425 String eline = null;
426 String stdinline = null;
427 while (((eline = ebr.readLine()) != null || (stdinline = stdinbr.readLine()) != null) && !this.cancel)
428 {
429 if (eline != null)
430 {
431 //System.err.println("ERROR: " + eline);
432 bw.write(eline + "\n");
433 sendProcessStatus(new ConstructionEvent(this, GSStatus.CONTINUING, eline));
434 }
435 if (stdinline != null)
436 {
437 //System.err.println("OUT: " + stdinline);
438 bw.write(stdinline + "\n");
439 sendProcessStatus(new ConstructionEvent(this, GSStatus.CONTINUING, stdinline));
440 }
441 }
442 bw.close();
443
444 if (!this.cancel)
445 {
446 // Now display final message based on exit value
447 prcs.waitFor();
448
449 if (prcs.exitValue() == 0)
450 {
451 //status = OK;
452 sendProcessStatus(new ConstructionEvent(this, GSStatus.CONTINUING, "Success"));
453
454 }
455 else
456 {
457 //status = ERROR;
458 sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Failure"));
459
460 return false;
461
462 }
463 }
464 else
465 {
466 // I need to somehow kill the child process. Unfortunately Thread.stop() and Process.destroy() both fail to do this. But now, thankx to the magic of Michaels 'close the stream suggestion', it works fine.
467 sendProcessStatus(new ConstructionEvent(this, GSStatus.HALTED, "killing the process"));
468 prcs.getOutputStream().close();
469 prcs.destroy();
470 //status = ERROR;
471 return false;
472 }
473 }
474 catch (Exception e)
475 {
476 e.printStackTrace();
477 sendProcessStatus(new ConstructionEvent(this, GSStatus.ERROR, "Exception occurred " + e.toString()));
478 }
479
480 // we're done, but we dont send a process complete message here cos there ight be stuff to do after this has finished.
481 return true;
482
483 }
484
485}
Note: See TracBrowser for help on using the repository browser.