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

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

Tidied up a lot of path variables. These were all over the place, and were often duplicated. Now all GLI related paths are accessed via static methods in the Gatherer class.

  • Property svn:keywords set to Author Date Id Revision
File size: 26.6 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.cdm.CollectionConfiguration;
52import org.greenstone.gatherer.cdm.CollectionDesignManager;
53import org.greenstone.gatherer.cdm.CollectionMetaManager;
54import org.greenstone.gatherer.cdm.CollectionMeta;
55import org.greenstone.gatherer.metadata.DocXMLFileManager;
56import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
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 // !! TO DO
631
632 if (progress!=null) {
633 progress.messageOnProgressBar("");
634 }
635 }
636 }
637 }
638
639 // We're done.
640 fireProcessComplete(type, status);
641 // Close bos
642 if(bos != null) {
643 try {
644 bos.close();
645 bos = null;
646 }
647 catch(Exception error) {
648 DebugStream.printStackTrace(error);
649 }
650 }
651 }
652 /** Method for firing a message to all interested listeners.
653 * @param type An <strong>int</strong> indicating the process type.
654 * @param message The message as a <strong>String</strong>.
655 * @param status An <strong>int</strong> specifying the current status of the process.
656 */
657 public void fireMessage(int type, String message, int status, BufferedOutputStream bos) {
658 GShellEvent event = new GShellEvent(this, 0, type, message, status);
659 // 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.
660 ArrayList message_queue = new ArrayList();
661 message_queue.add(event);
662 if(progress != null) {
663 progress.process(message_queue);
664 }
665 for(int j = 0; j < message_queue.size(); j++) {
666 GShellEvent current_event = (GShellEvent) message_queue.get(j);
667 // If the event hasn't been vetoed, pass it on to other listeners
668 if(!current_event.isVetoed()) {
669 Object[] concerned = listeners.getListenerList();
670 for(int i = 0; i < concerned.length ; i++) {
671 if(concerned[i] == GShellListener.class) {
672 ((GShellListener)concerned[i+1]).message(current_event);
673 }
674 }
675 concerned = null;
676 }
677 }
678 // And if we have a buffered output stream from error messages, send the message there
679 if(bos != null) {
680 try {
681 bos.write(message.getBytes(), 0, message.length());
682 }
683 catch(Exception exception) {
684 DebugStream.println("Exception in GShell.fireMessage() - unexpected");
685 DebugStream.printStackTrace(exception);
686 }
687 }
688 message_queue = null;
689 event = null;
690 }
691
692 /** Method for firing a process begun event which is called, strangly enough, when the process begins.
693 * @param type An <strong>int</strong> indicating the process type.
694 * @param status An <strong>int</strong> specifying the current status of the process.
695 */
696 protected void fireProcessBegun(int type, int status) {
697 // Start the progres monitor if available
698 if(progress != null) {
699 progress.start();
700 }
701 // Fire an event
702 GShellEvent event = new GShellEvent(this, 0, type, "", status);
703 Object[] concerned = listeners.getListenerList();
704 for(int i = 0; i < concerned.length ; i++) {
705 if(concerned[i] == GShellListener.class) {
706 ((GShellListener)concerned[i+1]).processBegun(event);
707 }
708 }
709 }
710
711
712 /** Method for firing a process complete event which is called, no surprise here, when the process ends.
713 * @param type An <strong>int</strong> indicating the process type.
714 * @param status An <strong>int</strong> specifying the current status of the process.
715 */
716 protected void fireProcessComplete(int type, int status) {
717 // 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).
718 if(progress != null && status != CANCELLED) {
719 progress.stop();
720 }
721
722 // If we were cancelled, and we are lower details modes, fire off one last message.
723 if(status == CANCELLED && Configuration.getMode() <= Configuration.SYSTEMS_MODE) {
724 GShellEvent current_event = new GShellEvent(this, 0, type, Dictionary.get("GShell.Build.BuildCancelled"), status);
725 Object[] concerned = listeners.getListenerList();
726 for(int i = 0; i < concerned.length ; i++) {
727 if(concerned[i] == GShellListener.class) {
728 ((GShellListener)concerned[i+1]).message(current_event);
729 }
730 }
731 concerned = null;
732 }
733 // And firing off an event
734 GShellEvent event = new GShellEvent(this, 0, type, "", status);
735 Object[] concerned = listeners.getListenerList();
736 for(int i = 0; i < concerned.length ; i++) {
737 if(concerned[i] == GShellListener.class) {
738 ((GShellListener)concerned[i+1]).processComplete(event);
739 }
740 }
741 }
742
743 /** Method to determine if the user, via the progress monitor, has signalled stop.
744 * @return A <strong>boolean</strong> indicating if the user wanted to stop.
745 */
746 public boolean hasSignalledStop() {
747 boolean has_signalled_stop = false;
748 if(progress != null) {
749 has_signalled_stop = progress.hasSignalledStop();
750 }
751 if(has_signalled_stop) {
752 status = CANCELLED;
753 }
754 return has_signalled_stop;
755 }
756
757 /** Converts a type into a text representation.
758 * @param type An <strong>int</strong> which maps to a shell process type.
759 * @return A <strong>String</strong> which is the thread process's text name.
760 */
761 public String typeAsString(int type) {
762 String name = null;
763 switch(type) {
764 case BUILD:
765 name = "buildcol.pl";
766 break;
767 case IMPORT:
768 name = "import.pl";
769 break;
770 case NEW:
771 name = "mkcol.pl";
772 break;
773 case EXPORTAS:
774 name = "export.pl";
775 break;
776 case CDIMAGE:
777 name = "exportcol.pl";
778 break;
779 case CONVERT:
780 name = "convert_coll_from_gs2.pl";
781 break;
782 case EXPLODE:
783 name = "explode_metadata_database.pl";
784 break;
785 default:
786 name = "";
787 }
788 return name;
789 }
790}
Note: See TracBrowser for help on using the repository browser.