source: trunk/gli/src/org/greenstone/gatherer/shell/GShell.java@ 10250

Last change on this file since 10250 was 10250, checked in by mdewsnip, 19 years ago

Moved all of the ZIP functions out of Utility and into a new ZipTools class.

  • Property svn:keywords set to Author Date Id Revision
File size: 28.2 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.shell;
38
39import java.io.*;
40import java.net.*;
41import java.util.ArrayList;
42import java.util.Enumeration;
43import java.util.regex.*;
44import javax.swing.*;
45import javax.swing.event.*;
46import javax.swing.tree.*;
47import org.greenstone.gatherer.Configuration;
48import org.greenstone.gatherer.DebugStream;
49import org.greenstone.gatherer.Dictionary;
50import org.greenstone.gatherer.Gatherer;
51import org.greenstone.gatherer.RemoteGreenstoneServer;
52import org.greenstone.gatherer.cdm.CollectionConfiguration;
53import org.greenstone.gatherer.cdm.CollectionDesignManager;
54import org.greenstone.gatherer.cdm.CollectionMetaManager;
55import org.greenstone.gatherer.cdm.CollectionMeta;
56import org.greenstone.gatherer.metadata.DocXMLFileManager;
57import org.greenstone.gatherer.util.StaticStrings;
58import org.greenstone.gatherer.util.Utility;
59import org.greenstone.gatherer.util.ZipTools;
60
61
62/** The <strong>GShell</strong> is reponsible for running a separately threaded process in the command shell. This is necessary for executing the Perl Scripts and also for other system related funcitonality.
63 */
64public class GShell
65 extends Thread {
66 /** A flag used to determine if this process has been asked to cancel. */
67 private boolean cancel = false;
68 /** The list of listeners associated with this class. */
69 private EventListenerList listeners = null;
70 /** The current status of this shell process. */
71 private int status = -1;
72 /** The type of message being sent. */
73 private int msg_type = -1;
74 /** The type of shell process. */
75 private int type = -1;
76 /** The caller of this process, and thus the class most interested in messages. */
77 private GShellListener caller = null;
78 /** The progress monitor associated with this process. */
79 private GShellProgressMonitor progress = null;
80 /** Arguments to be given to the process (including the executable you are calling. */
81 private String args[] = null;
82 /** Elements in process type enumeration. */
83 static final public int BUILD = 0;
84 static final public int IMPORT = 1;
85 static final public int NEW = 2;
86 static final public int EXPORTAS = 3;
87 static final public int CDIMAGE = 4;
88 static final public int CONVERT = 5;
89 static final public int EXPLODE = 6;
90
91 /** Elements in status type enumeration. */
92 static final public int ERROR = 0;
93 static final public int OK = 1;
94 static final public int CANCELLED = 2;
95
96 /** Elements in process type name enumeration. */
97 static public String GSHELL_BUILD = "gshell_build";
98 static public String GSHELL_IMPORT = "gshell_import";
99 static public String GSHELL_NEW = "gshell_new";
100 static public String GSHELL_EXPORTAS = "gshell_exportas";
101 static public String GSHELL_CDIMAGE = "gshell_cdimage";
102 static public String GSHELL_CONVERT = "gshell_convert";
103 static public String GSHELL_EXPLODE = "gshell_explode";
104
105 /** Determine if the given process is still executing. It does this by attempting to throw an exception - not the most efficient way, but the only one as far as I know
106 * @param process the Process to test
107 * @return true if it is still executing, false otherwise
108 */
109 static public boolean processRunning(Process process) {
110 boolean process_running = false;
111
112 try {
113 process.exitValue(); // This will throw an exception if the process hasn't ended yet.
114 }
115 catch(IllegalThreadStateException itse) {
116 process_running = true;
117 }
118 catch(Exception exception) {
119 DebugStream.printStackTrace(exception);
120 }
121 return process_running;
122 }
123
124 /** Constructor gatherer all the data required to create a new process, and emit meaningfull messages.
125 * @param args A <strong>String[]</strong> containing the arguments to the process thread, including the name of the executable.
126 * @param type An <strong>int</strong> that indicates what group of processes this process belongs to, as some are treated slightly differently (i.e an IMPORT type process is always followed by a BUILD one).
127 * @param msg_type As process threads may be background (like a makecol.pl call) or important processes in their own right (such as an IMPORT-BUILD) we must be able to set what level messages posted by this class will have by usings this <strong>int</strong>.
128 * @param caller The default <i>GShellListener</i> that is interested in the progress of this process.
129 * @param progress The <i>GShellProgressMonitor</i> associated with this process.
130 * @param name A <strong>String</strong> identifier given to the process, for convience and debug reasons.
131 */
132 public GShell(String args[], int type, int msg_type, GShellListener caller, GShellProgressMonitor progress, String name) {
133 super(name);
134 this.args = args;
135 this.msg_type = msg_type;
136 this.type = type;
137 this.caller = caller;
138 this.progress = progress;
139 this.status = 0;
140 // Lower this jobs priority
141 this.setPriority(Thread.MIN_PRIORITY);
142 listeners = new EventListenerList();
143 listeners.add(GShellListener.class, caller);
144 }
145 /** This method adds another shell listener to this process.
146 * @param listener The new <i>GShellListener</i>.
147 */
148 public void addGShellListener(GShellListener listener) {
149 listeners.add(GShellListener.class, listener);
150 }
151 /** This method removes a certain shell listener from this process.
152 * @param listener The <i>GShellListener</i> to be removed.
153 */
154 /* private void removeGShellListener(GShellListener listener) {
155 listeners.remove(GShellListener.class, listener);
156 } */
157
158
159
160 protected boolean got_stream_char(InputStreamReader isr, StringBuffer line_buffer,
161 BufferedOutputStream bos) throws IOException
162 {
163 // Hopefully this doesn't block if the process is trying to write to STDOUT/STDERR.
164
165 boolean input_status = false;
166
167 if(isr.ready()) {
168 input_status = true;
169 int c = isr.read();
170 if(c == '\n' || c == '\r') {
171 if(line_buffer.length() > 0) {
172 String line = line_buffer.toString();
173 DebugStream.println("* " + line + " *");
174 fireMessage(type, typeAsString(type) + "> " + line, status, bos);
175 line = null;
176 line_buffer = new StringBuffer();
177 }
178 }
179 else {
180 line_buffer.append((char)c);
181 }
182 }
183
184 return input_status;
185 }
186
187
188 protected StringBuffer get_stream_char(InputStreamReader isr, StringBuffer line_buffer,
189 BufferedOutputStream bos) throws IOException
190 {
191 int c = isr.read();
192 ///atherer.println("isr: '" + (char) c + "'");
193 if(c == '\n' || c == '\r') {
194 if(line_buffer.length() > 0) {
195 String line = line_buffer.toString();
196 // DebugStream.println("* " + line + " *");
197 fireMessage(type, typeAsString(type) + "> " + line, status, bos);
198 line_buffer = new StringBuffer();
199 }
200 }
201 else {
202 line_buffer.append((char)c);
203 }
204
205 return line_buffer;
206 }
207
208
209 protected int check_for_error(String line, StringBuffer error_list,
210 int error_count)
211 {
212 if (line.startsWith("ERROR:")) {
213 error_count++;
214 if (error_count<10) {
215 error_list.append(line);
216 }
217 else if (error_count==10) {
218 error_list.append("...\n");
219 }
220 }
221 return error_count;
222 }
223
224
225 protected void runRemote(String[] args, BufferedOutputStream bos)
226 {
227 System.err.println("The level of design processing needed is: " + CollectionDesignManager.getRebuildTypeRequired()); //Will add smart design processing
228 if(hasSignalledStop()) { return; }
229 int error_count = 0;
230 StringBuffer error_list = new StringBuffer();
231 try {
232 if (type == IMPORT) {
233 String col_name = args[args.length-1];
234 if (progress!=null) {
235 progress.messageOnProgressBar("Uploading data to server");
236 }
237
238 String collect_directory_path = Gatherer.getCollectDirectoryPath();
239
240 //Only upload the parts of the import folder (files/metadata) that has been changed.
241 //Or upload the lot if we are doing a complete rebuild.
242 if(Gatherer.c_man.getCollection().getFilesChanged() || !Gatherer.g_man.create_pane.isIncremental()) {
243 // zip up import folder, but exclude metadata
244 ZipTools.zipup(collect_directory_path, col_name, "import", this, "", ".*metadata\\.xml");
245
246 if(hasSignalledStop()) { return; }
247 // upload it to gsdl server
248 RemoteGreenstoneServer.upload_url_zip(col_name, "import", "files", this);
249
250 Gatherer.c_man.getCollection().setFilesChanged(false);
251 System.err.println("Finished uploading files");
252 }
253 if(Gatherer.c_man.getCollection().getMetadataChanged() || !Gatherer.g_man.create_pane.isIncremental()) {
254 // zip up metadata from import folder
255 ZipTools.zipup(collect_directory_path, col_name, "import", this, ".*metadata\\.xml", "");
256
257 if(hasSignalledStop()) { return; }
258 // upload it to gsdl server
259 RemoteGreenstoneServer.upload_url_zip(col_name, "import", "metadata", this);
260 Gatherer.c_man.getCollection().setMetadataChanged(false);
261 System.err.println("Finished uploading metadata.");
262 }
263
264 if(hasSignalledStop()) { return; }
265 // upload etc folder to server (need collect.cfg and any hfiles)
266 ZipTools.zipup(collect_directory_path, col_name, "etc", this, "", "");
267
268 if(hasSignalledStop()) { return; }
269 RemoteGreenstoneServer.upload_url_zip(col_name, "etc", "", this);
270
271 String collection_directory_path = Gatherer.c_man.getCollectionDirectoryPath(col_name);
272 File img_dir = new File(Gatherer.c_man.getCollectionImagesDirectoryPath());
273 if (img_dir.exists() && img_dir.list().length > 0) {
274 // upload images/ directory to server
275 if(hasSignalledStop()) { return; }
276 ZipTools.zipup(collect_directory_path, col_name, "images", this, "", "");
277
278 if(hasSignalledStop()) { return; }
279 RemoteGreenstoneServer.upload_url_zip(col_name, "images", "", this);
280
281 System.err.println("collect_directory_path: " + collect_directory_path);
282 System.err.println("col_name: " + col_name);
283 }
284
285 if(hasSignalledStop()) { return; }
286 // see if collection specific image needs uploading
287 CollectionMetaManager cmm
288 = CollectionDesignManager.collectionmeta_manager;
289
290 CollectionMeta icon_collection_collectionmeta
291 = cmm.getMetadatum(CollectionConfiguration.COLLECTIONMETADATA_ICONCOLLECTION_STR);
292 CollectionMeta icon_collection_small_collectionmeta
293 = cmm.getMetadatum(CollectionConfiguration.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR);
294
295 String ics_text = icon_collection_collectionmeta.getValue(CollectionMeta.TEXT);
296 String icsc_text = icon_collection_small_collectionmeta.getValue(CollectionMeta.TEXT);
297 if ((ics_text != null) && (ics_text != "")) {
298 // Stub code for detecting when collectoin image changed
299 // => need to upload images
300 // System.err.println("**** ics_text = " + ics_text);
301 }
302
303 if (progress!=null) {
304 progress.messageOnProgressBar("");
305 }
306 }
307
308 if(hasSignalledStop()) { return; }
309 String perl_cmd = args[0];
310 int perl_cmd_root = perl_cmd.lastIndexOf(File.separator);
311
312 if (perl_cmd_root > 0) {
313 String perl_cmd_cut = perl_cmd.substring(perl_cmd_root+1);
314 perl_cmd = perl_cmd_cut;
315 }
316
317 String cols_concat = null;
318 String launch = Gatherer.cgiBase + "launch";
319 launch = launch + "?cmd=" + perl_cmd;
320
321 for(int i = 1; i<args.length; i++) {
322
323 String arg = args[i];
324
325 if (arg.equals("-collectdir") || arg.equals("-importdir")
326 || arg.equals("-builddir")) {
327 // skip it
328 i++;
329 continue;
330 }
331
332 if(arg.startsWith(StaticStrings.MINUS_CHARACTER)) {
333 String name = arg.substring(1);
334 launch = launch + "&" + name + "=";
335 if (i+1<args.length-1) {
336 if (!args[i+1].startsWith(StaticStrings.MINUS_CHARACTER)) {
337 i++;
338 String val = URLEncoder.encode(args[i],"UTF-8");
339 launch = launch + val;
340 }
341 }
342 }
343 else {
344 if (cols_concat==null) {
345 cols_concat = arg;
346 }
347 else {
348 cols_concat = cols_concat + ":" + arg;
349 }
350 }
351 }
352
353 if (cols_concat!=null) {
354 launch = launch + "&c=" + cols_concat;
355 }
356
357 System.err.println("**** launch url = " + launch);
358 // fireMessage(type, Dictionary.get("GShell.Command") + ": " + launch, status, null); // ****
359
360 URL launch_url = new URL(launch);
361 URLConnection launch_connection = launch_url.openConnection();
362 InputStream stdis = launch_connection.getInputStream();
363 InputStreamReader stdisr = new InputStreamReader(stdis, "UTF-8");
364
365 BufferedReader stdbr = new BufferedReader(stdisr);
366
367 if (type == GShell.NEW) {
368 while(true) {
369 String line = stdbr.readLine();
370 if (line == null) { break; }
371 error_count = check_for_error(line,error_list,error_count);
372 }
373 }
374 else {
375 while(!hasSignalledStop()) {
376 String line = stdbr.readLine();
377 if (line == null) { break; }
378 error_count = check_for_error(line,error_list,error_count);
379 fireMessage(type, typeAsString(type) + "> " + line, status, bos);
380 }
381 }
382 stdbr.close();
383
384 if (error_count>0) {
385 status = ERROR;
386 System.err.println(error_list);
387 if (type != GShell.NEW) {
388 fireMessage(type, typeAsString(type) + "> " + error_list, status, null);
389 }
390 }
391 else if(hasSignalledStop()) {
392 //User pressed the cancel button.
393 //Status already set in hasSignalledStop method.
394 }
395 else {
396 status = OK;
397 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
398 }
399 }
400 // Exception
401 catch (Exception exception) {
402 System.err.println("Exception in GShell.runRemote() - unexpected");
403 DebugStream.printStackTrace(exception);
404 status = ERROR;
405 }
406 }
407
408
409 protected void runLocal(String[] args, BufferedOutputStream bos)
410 {
411 try {
412 String command = "";
413 for(int i = 0; i < args.length; i++) {
414 command = command + args[i] + " ";
415 }
416
417 DebugStream.println("Command: "+command);
418 ///ystem.err.println("Command: " + command);
419 fireMessage(type, Dictionary.get("GShell.Command") + ": " + command, status, null);
420
421 Runtime rt = Runtime.getRuntime();
422 Process prcs = rt.exec(args);
423
424 InputStreamReader eisr = new InputStreamReader( prcs.getErrorStream(), "UTF-8" );
425 InputStreamReader stdisr = new InputStreamReader( prcs.getInputStream(), "UTF-8" );
426
427 StringBuffer eline_buffer = new StringBuffer();
428 StringBuffer stdline_buffer = new StringBuffer();
429
430 while(type != GShell.NEW && processRunning(prcs) && !hasSignalledStop()) {
431 // Hopefully this doesn't block if the process is trying to write to STDOUT.
432 if((eisr!=null) && eisr.ready()) {
433 eline_buffer = get_stream_char(eisr,eline_buffer,bos);
434 }
435 // Hopefully this won't block if the process is trying to write to STDERR
436 else if(stdisr.ready()) {
437 stdline_buffer = get_stream_char(stdisr,stdline_buffer,bos);
438 }
439 else {
440 try {
441 sleep(100);
442 }
443 catch(Exception exception) {
444 }
445 }
446 }
447
448 if(!hasSignalledStop()) {
449 // Of course, just because the process is finished doesn't
450 // mean the incoming streams are empty. Unfortunately I've
451 // got no chance of preserving order, so I'll process the
452 // error stream first, then the out stream
453 while(eisr.ready()) {
454 eline_buffer = get_stream_char(eisr,eline_buffer,bos);
455 }
456
457 while(stdisr.ready()) {
458 stdline_buffer = get_stream_char(stdisr,stdline_buffer,bos);
459 }
460
461 // Ensure that any messages still remaining in the string buffers are fired off.
462 if(eline_buffer.length() > 0) {
463 String eline = eline_buffer.toString();
464 //DebugStream.println("Last bit of eline: " + eline);
465 fireMessage(type, typeAsString(type) + "> " + eline, status, bos);
466 eline = null;
467 }
468
469 if(stdline_buffer.length() > 0) {
470 String stdline = stdline_buffer.toString();
471 //DebugStream.println("Last bit of stdline: " + stdline);
472 fireMessage(type, typeAsString(type) + "> " + stdline, status, null);
473 stdline = null;
474 }
475 }
476 else {
477 System.err.println("We've been asked to stop.");
478 }
479
480
481 if(!hasSignalledStop()) {
482 // Now display final message based on exit value
483
484 prcs.waitFor();
485
486 if(prcs.exitValue() == 0) {
487 status = OK;
488 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
489 }
490 else {
491 status = ERROR;
492 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Failure"), status, null);
493 }
494
495 eisr.close();
496 stdisr.close();
497 }
498 else {
499 // I need to somehow kill the child process. Unfortunately
500 // Thread.stop() and Process.destroy() both fail to do
501 // this. But now, thankx to the magic of Michaels 'close the
502 // stream suggestion', it works fine (no it doesn't!)
503 prcs.getInputStream().close();
504 prcs.getErrorStream().close();
505 prcs.getOutputStream().close();
506 prcs.destroy();
507 status = CANCELLED;
508 }
509 }
510 // Exception
511 catch (Exception exception) {
512 DebugStream.println("Exception in GShell.runLocal() - unexpected");
513 DebugStream.printStackTrace(exception);
514 status = ERROR;
515 }
516 }
517
518
519
520 /** Any threaded class must include this method to allow the thread body to be run. */
521 public void run() {
522 String col_name = args[args.length-1];
523
524 // Determine if the user has asked for an outfile.
525 String out_name = null;
526 BufferedOutputStream bos = null;
527 if(type == IMPORT || type == BUILD) {
528 if(type == IMPORT) {
529 out_name = (String) Gatherer.c_man.getCollection().import_options.getValue("out");
530 }
531 else {
532 out_name = (String) Gatherer.c_man.getCollection().build_options.getValue("out");
533 }
534 if(out_name != null && out_name.length() > 0) {
535 try {
536 bos = new BufferedOutputStream(new FileOutputStream(new File(out_name), true));
537 }
538 catch (Exception error) {
539 DebugStream.printStackTrace(error);
540 }
541 }
542 }
543
544 // Issue a processBegun event
545 fireProcessBegun(type, status);
546 if (Gatherer.isGsdlRemote) {
547 runRemote(args,bos);
548 }
549 else {
550 runLocal(args,bos);
551 }
552
553 if(status == OK) {
554 if (type == NEW) {
555 if (Gatherer.isGsdlRemote) {
556 RemoteGreenstoneServer.download_url_zip(col_name, ".", this, "", "");
557 if (!hasSignalledStop()) {
558 ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
559 }
560 }
561 }
562 else if(type == IMPORT) {
563
564 // download the archives directory (if gsdl server is remote)
565 if (Gatherer.isGsdlRemote) {
566
567 if (progress!=null) {
568 progress.messageOnProgressBar("Downloading archive data from server");
569 }
570
571 Utility.delete(Gatherer.c_man.getCollectionArchivesDirectoryPath()); // remove current archives
572 //new File(Gatherer.c_man.getCollectionArchivesDirectoryPath()).mkdir(); //Make a clean dir
573 RemoteGreenstoneServer.download_url_zip(col_name, "archives", this, ".*doc\\.xml", "");
574 if (hasSignalledStop()) {
575 // Clean up, then exit
576 fireProcessComplete(type, status);
577 // Close bos
578 if(bos != null) {
579 try {
580 bos.close();
581 bos = null;
582 }
583 catch(Exception error) {
584 DebugStream.printStackTrace(error);
585 }
586 }
587 return;
588 }
589 ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
590
591 if (progress!=null) {
592 progress.messageOnProgressBar("");
593 }
594 }
595
596 // Refresh the DocXMLFileManager
597 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Start"), status, null);
598 DocXMLFileManager.clearDocXMLFiles();
599 DocXMLFileManager.loadDocXMLFiles(new File(Gatherer.c_man.getCollectionArchivesDirectoryPath()));
600 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Complete"), status, null);
601 }
602
603 else if(type == BUILD) {
604 // download the building directory (if gsdl server is remote)
605 if (Gatherer.isGsdlRemote) {
606 if (progress!=null) {
607 progress.messageOnProgressBar("Downloading index data from server");
608 }
609
610 File buildDir = new File(Gatherer.c_man.getCollectionBuildingDirectoryPath());
611 Utility.delete(buildDir); // remove current build dir
612 //Only need build.cfg
613 RemoteGreenstoneServer.download_url_zip(col_name, "building", this, ".*build\\.cfg", "");
614 if (!hasSignalledStop()) {
615 ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
616 }
617
618 if (progress!=null) {
619 progress.messageOnProgressBar("");
620 }
621 }
622 }
623 else if(type == CDIMAGE) {
624 // download exported files from tmp folder (if gsdl server is remote)
625 if (Gatherer.isGsdlRemote) {
626 if (progress!=null) {
627 progress.messageOnProgressBar("Downloading CD-ROM data from server");
628 }
629
630 //Export directory derrived from -cdname argument
631 //This needs to be exactly the same as derrived by exportcol.pl - perhaps it should be passed in as an argument?
632 String cd_dir = "exported_collections";
633 for(int i=0; i<args.length-1; i++) {
634 if(args[i] == "-cdname") {
635 //Remove all spaces
636 String cdName = args[i+1];
637 Pattern pattern = Pattern.compile("\\s");
638 Matcher matcher = pattern.matcher(cdName);
639 cd_dir = "exported_" + matcher.replaceAll("");
640 }
641 }
642 //DebugStream.println("cd_dir is: " + cd_dir);
643
644 String tmp_dir = Utility.TMP_DIR;
645 String user_tmp_dir = "/tmp";
646
647 //String username = System.getProperty("user.name");
648 //if ((username != null) && (username != "")) {
649 // user_cd_dir = username + File.separator + cd_dir;
650 //user_tmp_dir = user_tmp_dir + File.separator + username;
651 //}
652
653 String full_local_cd_dir = tmp_dir + cd_dir; //Need to tell user this!
654
655 Utility.delete(full_local_cd_dir); // remove current cd-rom dir, if it exists
656 RemoteGreenstoneServer.download_url_zip(user_tmp_dir,cd_dir,this,"","");
657
658 ZipTools.unzip(Configuration.gsdl_path, user_tmp_dir.substring(1));
659
660 if (progress!=null) {
661 System.err.println("Asking progress bar to be empty string");
662 progress.messageOnProgressBar("");
663 }
664
665 //The string needs to start with exportcol.pl> otherwise it won't be displayed in the final dialog
666 String message = "exportcol.pl>\nThese files have been copied from the server to " + full_local_cd_dir + " and are ready to written to CD-ROM";
667 fireMessage(type, message, status, bos); //Hopefully this works
668 System.err.println("Finished download of /tmp ...");
669 }
670
671 }
672 }
673
674 // We're done.
675 fireProcessComplete(type, status);
676 // Close bos
677 if(bos != null) {
678 try {
679 bos.close();
680 bos = null;
681 }
682 catch(Exception error) {
683 DebugStream.printStackTrace(error);
684 }
685 }
686 }
687 /** Method for firing a message to all interested listeners.
688 * @param type An <strong>int</strong> indicating the process type.
689 * @param message The message as a <strong>String</strong>.
690 * @param status An <strong>int</strong> specifying the current status of the process.
691 */
692 public void fireMessage(int type, String message, int status, BufferedOutputStream bos) {
693 GShellEvent event = new GShellEvent(this, 0, type, message, status);
694 // If there is a progress monitor attached, pass the event to it first. Note that we pass a queue of messages as the processing may cause one message to be split into several.
695 ArrayList message_queue = new ArrayList();
696 message_queue.add(event);
697 if(progress != null) {
698 progress.process(message_queue);
699 }
700 for(int j = 0; j < message_queue.size(); j++) {
701 GShellEvent current_event = (GShellEvent) message_queue.get(j);
702 // If the event hasn't been vetoed, pass it on to other listeners
703 if(!current_event.isVetoed()) {
704 Object[] concerned = listeners.getListenerList();
705 for(int i = 0; i < concerned.length ; i++) {
706 if(concerned[i] == GShellListener.class) {
707 ((GShellListener)concerned[i+1]).message(current_event);
708 }
709 }
710 concerned = null;
711 }
712 }
713 // And if we have a buffered output stream from error messages, send the message there
714 if(bos != null) {
715 try {
716 bos.write(message.getBytes(), 0, message.length());
717 }
718 catch(Exception exception) {
719 DebugStream.println("Exception in GShell.fireMessage() - unexpected");
720 DebugStream.printStackTrace(exception);
721 }
722 }
723 message_queue = null;
724 event = null;
725 }
726
727 /** Method for firing a process begun event which is called, strangly enough, when the process begins.
728 * @param type An <strong>int</strong> indicating the process type.
729 * @param status An <strong>int</strong> specifying the current status of the process.
730 */
731 protected void fireProcessBegun(int type, int status) {
732 // Start the progres monitor if available
733 if(progress != null) {
734 progress.start();
735 }
736 // Fire an event
737 GShellEvent event = new GShellEvent(this, 0, type, "", status);
738 Object[] concerned = listeners.getListenerList();
739 for(int i = 0; i < concerned.length ; i++) {
740 if(concerned[i] == GShellListener.class) {
741 ((GShellListener)concerned[i+1]).processBegun(event);
742 }
743 }
744 }
745
746
747 /** Method for firing a process complete event which is called, no surprise here, when the process ends.
748 * @param type An <strong>int</strong> indicating the process type.
749 * @param status An <strong>int</strong> specifying the current status of the process.
750 */
751 protected void fireProcessComplete(int type, int status) {
752 // Tidy up by stopping the progress bar. If it was cancelled then the cancel command has arrived via the progress bars and they don't need to be told again (it actually causes problems).
753 if(progress != null && status != CANCELLED) {
754 progress.stop();
755 }
756
757 // If we were cancelled, and we are lower details modes, fire off one last message.
758 if(status == CANCELLED && Configuration.getMode() <= Configuration.SYSTEMS_MODE) {
759 GShellEvent current_event = new GShellEvent(this, 0, type, Dictionary.get("GShell.Build.BuildCancelled"), status);
760 Object[] concerned = listeners.getListenerList();
761 for(int i = 0; i < concerned.length ; i++) {
762 if(concerned[i] == GShellListener.class) {
763 ((GShellListener)concerned[i+1]).message(current_event);
764 }
765 }
766 concerned = null;
767 }
768 // And firing off an event
769 GShellEvent event = new GShellEvent(this, 0, type, "", status);
770 Object[] concerned = listeners.getListenerList();
771 for(int i = 0; i < concerned.length ; i++) {
772 if(concerned[i] == GShellListener.class) {
773 ((GShellListener)concerned[i+1]).processComplete(event);
774 }
775 }
776 }
777
778 /** Method to determine if the user, via the progress monitor, has signalled stop.
779 * @return A <strong>boolean</strong> indicating if the user wanted to stop.
780 */
781 public boolean hasSignalledStop() {
782 boolean has_signalled_stop = false;
783 if(progress != null) {
784 has_signalled_stop = progress.hasSignalledStop();
785 }
786 if(has_signalled_stop) {
787 status = CANCELLED;
788 }
789 return has_signalled_stop;
790 }
791
792 /** Converts a type into a text representation.
793 * @param type An <strong>int</strong> which maps to a shell process type.
794 * @return A <strong>String</strong> which is the thread process's text name.
795 */
796 public String typeAsString(int type) {
797 String name = null;
798 switch(type) {
799 case BUILD:
800 name = "buildcol.pl";
801 break;
802 case IMPORT:
803 name = "import.pl";
804 break;
805 case NEW:
806 name = "mkcol.pl";
807 break;
808 case EXPORTAS:
809 name = "export.pl";
810 break;
811 case CDIMAGE:
812 name = "exportcol.pl";
813 break;
814 case CONVERT:
815 name = "convert_coll_from_gs2.pl";
816 break;
817 case EXPLODE:
818 name = "explode_metadata_database.pl";
819 break;
820 default:
821 name = "";
822 }
823 return name;
824 }
825}
Note: See TracBrowser for help on using the repository browser.