source: branches/gsdl-2_62-distribution-branch/gli/src/org/greenstone/gatherer/shell/GShell.java@ 10876

Last change on this file since 10876 was 10876, checked in by kjdon, 18 years ago

added the macros directory to be uploaded along with images directory

  • Property svn:keywords set to Author Date Id Revision
File size: 27.0 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 File macro_dir = new File(Gatherer.c_man.getCollectionMacrosDirectoryPath());
285 if (macro_dir.exists() && macro_dir.list().length > 0) {
286 // upload images/ directory to server
287 if(hasSignalledStop()) { return; }
288 ZipTools.zipup(collect_directory_path, col_name, "macros", this, "", "");
289
290 if(hasSignalledStop()) { return; }
291 RemoteGreenstoneServer.upload_url_zip(col_name, "macros", "", this);
292
293 }
294
295 if(hasSignalledStop()) { return; }
296 // see if collection specific image needs uploading
297 CollectionMetaManager cmm
298 = CollectionDesignManager.collectionmeta_manager;
299
300 CollectionMeta icon_collection_collectionmeta
301 = cmm.getMetadatum(CollectionConfiguration.COLLECTIONMETADATA_ICONCOLLECTION_STR);
302 CollectionMeta icon_collection_small_collectionmeta
303 = cmm.getMetadatum(CollectionConfiguration.COLLECTIONMETADATA_ICONCOLLECTIONSMALL_STR);
304
305 String ics_text = icon_collection_collectionmeta.getValue(CollectionMeta.TEXT);
306 String icsc_text = icon_collection_small_collectionmeta.getValue(CollectionMeta.TEXT);
307 if ((ics_text != null) && (ics_text != "")) {
308 // Stub code for detecting when collectoin image changed
309 // => need to upload images
310 // System.err.println("**** ics_text = " + ics_text);
311 }
312
313 if (progress!=null) {
314 progress.messageOnProgressBar("");
315 }
316 }
317
318 if(hasSignalledStop()) { return; }
319 String perl_cmd = args[0];
320 int perl_cmd_root = perl_cmd.lastIndexOf(File.separator);
321
322 if (perl_cmd_root > 0) {
323 String perl_cmd_cut = perl_cmd.substring(perl_cmd_root+1);
324 perl_cmd = perl_cmd_cut;
325 }
326
327 String cols_concat = null;
328 String launch = Gatherer.cgiBase + "launch";
329 launch = launch + "?cmd=" + perl_cmd;
330
331 for(int i = 1; i<args.length; i++) {
332
333 String arg = args[i];
334
335 if (arg.equals("-collectdir") || arg.equals("-importdir")
336 || arg.equals("-builddir")) {
337 // skip it
338 i++;
339 continue;
340 }
341
342 if(arg.startsWith(StaticStrings.MINUS_CHARACTER)) {
343 String name = arg.substring(1);
344 launch = launch + "&" + name + "=";
345 if (i+1<args.length-1) {
346 if (!args[i+1].startsWith(StaticStrings.MINUS_CHARACTER)) {
347 i++;
348 String val = URLEncoder.encode(args[i],"UTF-8");
349 launch = launch + val;
350 }
351 }
352 }
353 else {
354 if (cols_concat==null) {
355 cols_concat = arg;
356 }
357 else {
358 cols_concat = cols_concat + ":" + arg;
359 }
360 }
361 }
362
363 if (cols_concat!=null) {
364 launch = launch + "&c=" + cols_concat;
365 }
366
367 System.err.println("**** launch url = " + launch);
368 // fireMessage(type, Dictionary.get("GShell.Command") + ": " + launch, status, null); // ****
369
370 URL launch_url = new URL(launch);
371 URLConnection launch_connection = launch_url.openConnection();
372 InputStream stdis = launch_connection.getInputStream();
373 InputStreamReader stdisr = new InputStreamReader(stdis, "UTF-8");
374
375 BufferedReader stdbr = new BufferedReader(stdisr);
376
377 if (type == GShell.NEW) {
378 while(true) {
379 String line = stdbr.readLine();
380 if (line == null) { break; }
381 error_count = check_for_error(line,error_list,error_count);
382 }
383 }
384 else {
385 while(!hasSignalledStop()) {
386 String line = stdbr.readLine();
387 if (line == null) { break; }
388 error_count = check_for_error(line,error_list,error_count);
389 fireMessage(type, typeAsString(type) + "> " + line, status, bos);
390 }
391 }
392 stdbr.close();
393
394 if (error_count>0) {
395 status = ERROR;
396 System.err.println(error_list);
397 if (type != GShell.NEW) {
398 fireMessage(type, typeAsString(type) + "> " + error_list, status, null);
399 }
400 }
401 else if(hasSignalledStop()) {
402 //User pressed the cancel button.
403 //Status already set in hasSignalledStop method.
404 }
405 else {
406 status = OK;
407 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
408 }
409 }
410 // Exception
411 catch (Exception exception) {
412 System.err.println("Exception in GShell.runRemote() - unexpected");
413 DebugStream.printStackTrace(exception);
414 status = ERROR;
415 }
416 }
417
418
419 protected void runLocal(String[] args, BufferedOutputStream bos)
420 {
421 try {
422 String command = "";
423 for(int i = 0; i < args.length; i++) {
424 command = command + args[i] + " ";
425 }
426
427 DebugStream.println("Command: "+command);
428 ///ystem.err.println("Command: " + command);
429 fireMessage(type, Dictionary.get("GShell.Command") + ": " + command, status, null);
430
431 Runtime rt = Runtime.getRuntime();
432 Process prcs = rt.exec(args);
433
434 InputStreamReader eisr = new InputStreamReader( prcs.getErrorStream(), "UTF-8" );
435 InputStreamReader stdisr = new InputStreamReader( prcs.getInputStream(), "UTF-8" );
436
437 StringBuffer eline_buffer = new StringBuffer();
438 StringBuffer stdline_buffer = new StringBuffer();
439
440 while(type != GShell.NEW && processRunning(prcs) && !hasSignalledStop()) {
441 // Hopefully this doesn't block if the process is trying to write to STDOUT.
442 if((eisr!=null) && eisr.ready()) {
443 eline_buffer = get_stream_char(eisr,eline_buffer,bos);
444 }
445 // Hopefully this won't block if the process is trying to write to STDERR
446 else if(stdisr.ready()) {
447 stdline_buffer = get_stream_char(stdisr,stdline_buffer,bos);
448 }
449 else {
450 try {
451 sleep(100);
452 }
453 catch(Exception exception) {
454 }
455 }
456 }
457
458 if(!hasSignalledStop()) {
459 // Of course, just because the process is finished doesn't
460 // mean the incoming streams are empty. Unfortunately I've
461 // got no chance of preserving order, so I'll process the
462 // error stream first, then the out stream
463 while(eisr.ready()) {
464 eline_buffer = get_stream_char(eisr,eline_buffer,bos);
465 }
466
467 while(stdisr.ready()) {
468 stdline_buffer = get_stream_char(stdisr,stdline_buffer,bos);
469 }
470
471 // Ensure that any messages still remaining in the string buffers are fired off.
472 if(eline_buffer.length() > 0) {
473 String eline = eline_buffer.toString();
474 //DebugStream.println("Last bit of eline: " + eline);
475 fireMessage(type, typeAsString(type) + "> " + eline, status, bos);
476 eline = null;
477 }
478
479 if(stdline_buffer.length() > 0) {
480 String stdline = stdline_buffer.toString();
481 //DebugStream.println("Last bit of stdline: " + stdline);
482 fireMessage(type, typeAsString(type) + "> " + stdline, status, null);
483 stdline = null;
484 }
485 }
486 else {
487 System.err.println("We've been asked to stop.");
488 }
489
490
491 if(!hasSignalledStop()) {
492 // Now display final message based on exit value
493
494 prcs.waitFor();
495
496 if(prcs.exitValue() == 0) {
497 status = OK;
498 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
499 }
500 else {
501 status = ERROR;
502 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Failure"), status, null);
503 }
504
505 eisr.close();
506 stdisr.close();
507 }
508 else {
509 // I need to somehow kill the child process. Unfortunately
510 // Thread.stop() and Process.destroy() both fail to do
511 // this. But now, thankx to the magic of Michaels 'close the
512 // stream suggestion', it works fine (no it doesn't!)
513 prcs.getInputStream().close();
514 prcs.getErrorStream().close();
515 prcs.getOutputStream().close();
516 prcs.destroy();
517 status = CANCELLED;
518 }
519 }
520 // Exception
521 catch (Exception exception) {
522 DebugStream.println("Exception in GShell.runLocal() - unexpected");
523 DebugStream.printStackTrace(exception);
524 status = ERROR;
525 }
526 }
527
528
529
530 /** Any threaded class must include this method to allow the thread body to be run. */
531 public void run() {
532 String col_name = args[args.length-1];
533
534 // Determine if the user has asked for an outfile.
535 String out_name = null;
536 BufferedOutputStream bos = null;
537 if(type == IMPORT || type == BUILD) {
538 if(type == IMPORT) {
539 out_name = (String) Gatherer.c_man.getCollection().import_options.getValue("out");
540 }
541 else {
542 out_name = (String) Gatherer.c_man.getCollection().build_options.getValue("out");
543 }
544 if(out_name != null && out_name.length() > 0) {
545 try {
546 bos = new BufferedOutputStream(new FileOutputStream(new File(out_name), true));
547 }
548 catch (Exception error) {
549 DebugStream.printStackTrace(error);
550 }
551 }
552 }
553
554 // Issue a processBegun event
555 fireProcessBegun(type, status);
556 if (Gatherer.isGsdlRemote) {
557 runRemote(args,bos);
558 }
559 else {
560 runLocal(args,bos);
561 }
562
563 if(status == OK) {
564 if (type == NEW) {
565 if (Gatherer.isGsdlRemote) {
566 RemoteGreenstoneServer.download_url_zip(col_name, ".", this, "", "");
567 if (!hasSignalledStop()) {
568 ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
569 }
570 }
571 }
572 else if(type == IMPORT) {
573
574 // download the archives directory (if gsdl server is remote)
575 if (Gatherer.isGsdlRemote) {
576
577 if (progress!=null) {
578 progress.messageOnProgressBar("Downloading archive data from server");
579 }
580
581 Utility.delete(Gatherer.c_man.getCollectionArchivesDirectoryPath()); // remove current archives
582 //new File(Gatherer.c_man.getCollectionArchivesDirectoryPath()).mkdir(); //Make a clean dir
583 RemoteGreenstoneServer.download_url_zip(col_name, "archives", this, ".*doc\\.xml", "");
584 if (hasSignalledStop()) {
585 // Clean up, then exit
586 fireProcessComplete(type, status);
587 // Close bos
588 if(bos != null) {
589 try {
590 bos.close();
591 bos = null;
592 }
593 catch(Exception error) {
594 DebugStream.printStackTrace(error);
595 }
596 }
597 return;
598 }
599 ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
600
601 if (progress!=null) {
602 progress.messageOnProgressBar("");
603 }
604 }
605
606 // Refresh the DocXMLFileManager
607 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Start"), status, null);
608 DocXMLFileManager.clearDocXMLFiles();
609 DocXMLFileManager.loadDocXMLFiles(new File(Gatherer.c_man.getCollectionArchivesDirectoryPath()));
610 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Parsing_Metadata_Complete"), status, null);
611 }
612
613 else if(type == BUILD) {
614 // download the building directory (if gsdl server is remote)
615 if (Gatherer.isGsdlRemote) {
616 if (progress!=null) {
617 progress.messageOnProgressBar("Downloading index data from server");
618 }
619
620 File buildDir = new File(Gatherer.c_man.getCollectionBuildingDirectoryPath());
621 Utility.delete(buildDir); // remove current build dir
622 //Only need build.cfg
623 RemoteGreenstoneServer.download_url_zip(col_name, "building", this, ".*build\\.cfg", "");
624 if (!hasSignalledStop()) {
625 ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
626 }
627
628 if (progress!=null) {
629 progress.messageOnProgressBar("");
630 }
631 }
632 }
633 else if(type == CDIMAGE) {
634 // download exported files from tmp folder (if gsdl server is remote)
635 if (Gatherer.isGsdlRemote) {
636 if (progress!=null) {
637 progress.messageOnProgressBar("Downloading CD-ROM data from server");
638 }
639
640 // !! TO DO
641
642 if (progress!=null) {
643 progress.messageOnProgressBar("");
644 }
645 }
646 }
647 }
648
649 // We're done.
650 fireProcessComplete(type, status);
651 // Close bos
652 if(bos != null) {
653 try {
654 bos.close();
655 bos = null;
656 }
657 catch(Exception error) {
658 DebugStream.printStackTrace(error);
659 }
660 }
661 }
662 /** Method for firing a message to all interested listeners.
663 * @param type An <strong>int</strong> indicating the process type.
664 * @param message The message as a <strong>String</strong>.
665 * @param status An <strong>int</strong> specifying the current status of the process.
666 */
667 public void fireMessage(int type, String message, int status, BufferedOutputStream bos) {
668 GShellEvent event = new GShellEvent(this, 0, type, message, status);
669 // 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.
670 ArrayList message_queue = new ArrayList();
671 message_queue.add(event);
672 if(progress != null) {
673 progress.process(message_queue);
674 }
675 for(int j = 0; j < message_queue.size(); j++) {
676 GShellEvent current_event = (GShellEvent) message_queue.get(j);
677 // If the event hasn't been vetoed, pass it on to other listeners
678 if(!current_event.isVetoed()) {
679 Object[] concerned = listeners.getListenerList();
680 for(int i = 0; i < concerned.length ; i++) {
681 if(concerned[i] == GShellListener.class) {
682 ((GShellListener)concerned[i+1]).message(current_event);
683 }
684 }
685 concerned = null;
686 }
687 }
688 // And if we have a buffered output stream from error messages, send the message there
689 if(bos != null) {
690 try {
691 bos.write(message.getBytes(), 0, message.length());
692 }
693 catch(Exception exception) {
694 DebugStream.println("Exception in GShell.fireMessage() - unexpected");
695 DebugStream.printStackTrace(exception);
696 }
697 }
698 message_queue = null;
699 event = null;
700 }
701
702 /** Method for firing a process begun event which is called, strangly enough, when the process begins.
703 * @param type An <strong>int</strong> indicating the process type.
704 * @param status An <strong>int</strong> specifying the current status of the process.
705 */
706 protected void fireProcessBegun(int type, int status) {
707 // Start the progres monitor if available
708 if(progress != null) {
709 progress.start();
710 }
711 // Fire an event
712 GShellEvent event = new GShellEvent(this, 0, type, "", status);
713 Object[] concerned = listeners.getListenerList();
714 for(int i = 0; i < concerned.length ; i++) {
715 if(concerned[i] == GShellListener.class) {
716 ((GShellListener)concerned[i+1]).processBegun(event);
717 }
718 }
719 }
720
721
722 /** Method for firing a process complete event which is called, no surprise here, when the process ends.
723 * @param type An <strong>int</strong> indicating the process type.
724 * @param status An <strong>int</strong> specifying the current status of the process.
725 */
726 protected void fireProcessComplete(int type, int status) {
727 // 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).
728 if(progress != null && status != CANCELLED) {
729 progress.stop();
730 }
731
732 // If we were cancelled, and we are lower details modes, fire off one last message.
733 if(status == CANCELLED && Configuration.getMode() <= Configuration.SYSTEMS_MODE) {
734 GShellEvent current_event = new GShellEvent(this, 0, type, Dictionary.get("GShell.Build.BuildCancelled"), 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]).message(current_event);
739 }
740 }
741 concerned = null;
742 }
743 // And firing off an event
744 GShellEvent event = new GShellEvent(this, 0, type, "", status);
745 Object[] concerned = listeners.getListenerList();
746 for(int i = 0; i < concerned.length ; i++) {
747 if(concerned[i] == GShellListener.class) {
748 ((GShellListener)concerned[i+1]).processComplete(event);
749 }
750 }
751 }
752
753 /** Method to determine if the user, via the progress monitor, has signalled stop.
754 * @return A <strong>boolean</strong> indicating if the user wanted to stop.
755 */
756 public boolean hasSignalledStop() {
757 boolean has_signalled_stop = false;
758 if(progress != null) {
759 has_signalled_stop = progress.hasSignalledStop();
760 }
761 if(has_signalled_stop) {
762 status = CANCELLED;
763 }
764 return has_signalled_stop;
765 }
766
767 /** Converts a type into a text representation.
768 * @param type An <strong>int</strong> which maps to a shell process type.
769 * @return A <strong>String</strong> which is the thread process's text name.
770 */
771 public String typeAsString(int type) {
772 String name = null;
773 switch(type) {
774 case BUILD:
775 name = "buildcol.pl";
776 break;
777 case IMPORT:
778 name = "import.pl";
779 break;
780 case NEW:
781 name = "mkcol.pl";
782 break;
783 case EXPORTAS:
784 name = "export.pl";
785 break;
786 case CDIMAGE:
787 name = "exportcol.pl";
788 break;
789 case CONVERT:
790 name = "convert_coll_from_gs2.pl";
791 break;
792 case EXPLODE:
793 name = "explode_metadata_database.pl";
794 break;
795 default:
796 name = "";
797 }
798 return name;
799 }
800}
Note: See TracBrowser for help on using the repository browser.