source: trunk/gli/src/org/greenstone/gatherer/Gatherer.java@ 8002

Last change on this file since 8002 was 7991, checked in by mdewsnip, 20 years ago

Removed some dead code.

  • Property svn:keywords set to Author Date Id Revision
File size: 37.3 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 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer;
28
29//import com.l2fprod.gui.*;
30//import com.l2fprod.gui.plaf.skin.*;
31//import com.l2fprod.util.*;
32import java.awt.*;
33import java.awt.event.*;
34import java.io.*;
35import java.lang.*;
36import java.net.*;
37import java.util.*;
38import javax.swing.*;
39import javax.swing.plaf.*;
40import javax.swing.text.*;
41import org.greenstone.gatherer.Configuration;
42import org.greenstone.gatherer.GAuthenticator;
43import org.greenstone.gatherer.collection.CollectionManager;
44import org.greenstone.gatherer.feedback.ActionRecorderDialog;
45import org.greenstone.gatherer.file.FileManager;
46import org.greenstone.gatherer.file.FileAssociationManager;
47import org.greenstone.gatherer.gui.GUIManager;
48import org.greenstone.gatherer.gui.ModalDialog;
49import org.greenstone.gatherer.gui.Splash;
50import org.greenstone.gatherer.gui.URLField;
51import org.greenstone.gatherer.gui.WarningDialog;
52import org.greenstone.gatherer.util.GSDLSiteConfig;
53import org.greenstone.gatherer.util.StaticStrings;
54import org.greenstone.gatherer.util.Utility;
55// import sun.misc.*;
56
57/** Containing the top-level "core" for the Gatherer, this class is the
58 * common core for the GLI application and applet. It first parses the
59 * command line arguments, preparing to update the configuration as
60 * required. Next it loads several important support classes such as the
61 * Configuration and Dictionary. Finally it creates the other important
62 * managers and sends them on their way.
63 * @author John Thompson, Greenstone Digital Library, University of Waikato
64 * @version 2.3
65 */
66
67// How to catch All Exceptions including those from the AWT Event thread.
68// Step 1: register a handler class in your main()
69//
70// System.setProperty("sun.awt.exception.handler", "YourHandler");
71//
72// Step 2: implement your handler class.
73//
74// public class YourHandler {
75// public void handle(Throwable thrown) {
76// eat the exception without dumping to the console.
77// }
78// }
79
80public class Gatherer
81{
82 static public Hashtable authentications = new Hashtable();
83
84 static final private String SKIN_DEFINITION_FILE = "lib/greenaqua/greenaqua.xml";
85
86 static public boolean always_show_exceptions = true;
87 /** Has the exit flag been set? <i>true</i> if so, <i>false</i> otherwise. */
88 public boolean exit = false;
89 /** The size of the Gatherer window. */
90 public Dimension frame_size = null;
91
92 /** All of the external applications that must exit before we close the Gatherer. */
93 public Vector apps = new Vector();
94 /** A public reference to the FileAssociationManager. */
95 static public FileAssociationManager assoc_man;
96 /** A public reference to the CollectionManager. */
97 static public CollectionManager c_man;
98 /** A public reference to the Gatherer's configuration. */
99 static public Configuration config;
100 /** a reference to the Servlet Configuration is GS3 */
101 static public ServletConfiguration servlet_config;
102 /** The current modal dialog being shown on screen, if any. */
103 static public ModalDialog current_modal = null;
104 /** A public reference to the Dictionary. */
105 static public Dictionary dictionary;
106 /** A public reference to the FileManager. */
107 static public FileManager f_man;
108 /** A public reference to the GUIManager. */
109 static public GUIManager g_man;
110 static public boolean g_man_built = false;
111
112 /** A static reference to ourselves. */
113 static public Gatherer self;
114 /** The debug print stream. */
115 static public PrintStream debug;
116 /** We are using the GLI for GS3 */
117 static public boolean GS3 = false;
118
119 static public boolean isGsdlRemote = false;
120 static public String cgiBase = "";
121
122 // feedback stuff
123 /** is the feedback feature enabled? */
124 static public boolean feedback_enabled = true;
125 /** the action recorder dialog */
126 static public ActionRecorderDialog feedback_dialog = null;
127 /** Extra environment information which must be set before shell processes will run properly. Should always be null if the startup script/program has done its job properly. */
128 static public String extra_env[] = null;
129 private GSDLSiteConfig gsdlsite_cfg = null;
130 private ExternalApplication server = null;
131
132 /** Magic to allow Enter to fire the default button. */
133 static {
134 KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
135 Keymap map = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
136 map.removeKeyStrokeBinding(enter);
137 }
138
139 public Gatherer()
140 {
141 this.self = this;
142
143 init_images();
144 }
145
146 protected void init_images()
147 {
148 Class base = this.getClass();
149 Utility.BLANK_ICON = new ImageIcon(base.getResource("/images/blank.gif"));
150 Utility.ERROR_ICON = new ImageIcon(base.getResource("/images/error.gif"));
151 Utility.HELP_ICON = new ImageIcon(base.getResource("/images/help.gif"));
152 Utility.ON_ICON = new ImageIcon(base.getResource("/images/check.gif"));
153 Utility.OFF_ICON = new ImageIcon(base.getResource("/images/cross.gif"));
154
155 Utility.base = base;
156 }
157
158
159 public GUIManager init(Dimension size, String gsdl_path, String gsdl3_path,
160 String exec_path, boolean debug_enabled, String perl_path,
161 boolean no_load, String open_collection,
162 String site_name, String servlet_path,
163 boolean mirroring_enabled, String wget_version_str,
164 String wget_path)
165 {
166
167 // This will hopefully catch ctrl-c and terminate, and exit gracefully. However it is platform specific, and may not be supported by some JVMs.
168 /** It does, but I get bloody sick of it working when the Gatherer hangs.
169 CTRLCHandler handler = new CTRLCHandler();
170 Signal.handle(new Signal("INT"), handler);
171 Signal.handle(new Signal("TERM"), handler);
172 handler = null;
173 */
174 if (gsdl3_path != null && !gsdl3_path.equals("")) {
175 this.GS3 = true;
176 } else {
177 gsdl3_path = null;
178 }
179 // Create the debug stream only if required.
180 if(debug_enabled) {
181 try {
182 Calendar now = Calendar.getInstance();
183 StringBuffer name = new StringBuffer("debug");
184 name.append(now.get(Calendar.DATE));
185 name.append("-");
186 name.append(now.get(Calendar.MONTH));
187 name.append("-");
188 name.append(now.get(Calendar.YEAR));
189 name.append(".txt");
190 this.debug = new PrintStream(new FileOutputStream(name.toString()));
191 Properties props = System.getProperties();
192 props.list(debug);
193 }
194 catch(Exception error) {
195 ///ystem.err.println("Error in Gatherer.init(): " + error);
196 error.printStackTrace();
197 System.exit(1);
198 }
199 }
200 try {
201 // Load Config
202 loadConfig(gsdl_path, gsdl3_path, exec_path, perl_path, mirroring_enabled, site_name);
203
204 // the feedback dialog has been loaded with a default locale,
205 // now set the user specified one
206 if (feedback_enabled && feedback_dialog != null) {
207 feedback_dialog.setLocale(config.getLocale("general.locale", true));
208 }
209
210 // Read Dictionary
211 dictionary = new Dictionary(config.getLocale("general.locale", true), config.getFont("general.font", true));
212
213
214 if (gsdl_path == null) {
215 missingGSDL();
216 }
217
218 // If we were given a server run it if neccessary.
219 if (!GS3 && config.exec_file != null) {
220 startServerEXE();
221 }
222
223 // Having loaded the configuration (necessary to determine if certain warnings have been disabled) and dictionary, we now check if the necessary path variables have been provided.
224 if (config.exec_file == null && config.exec_address == null) {
225 if (config.exec_file == null) {
226 Gatherer.println("config.exec_file is null");
227 }
228 if (config.exec_address == null) {
229 Gatherer.println("config.exec_address is null");
230 }
231 missingEXEC();
232 }
233
234 if (Gatherer.isGsdlRemote) {
235 Gatherer.println("Not checking for perl path/exe");
236 }
237 else {
238 // Perl path is a little different as it is perfectly ok to
239 // start the Gatherer without providing a perl path
240 boolean found_perl = false;
241 if (config.perl_path != null) {
242 // See if the file pointed to actually exists
243 File perl_file = new File(config.perl_path);
244 found_perl = perl_file.exists();
245 perl_file = null;
246 }
247 if (config.perl_path == null || !found_perl) {
248 // Run test to see if we can run perl as is.
249 PerlTest perl_test = new PerlTest();
250 if (perl_test.found()) {
251 // If so replace the perl path with the system
252 // default (or null for unix).
253 config.perl_path = perl_test.toString();
254 found_perl = true;
255 }
256 }
257 if (!found_perl) {
258 // Time for an error message.
259 missingPERL();
260 }
261 }
262
263 // also check for wget
264 boolean mirror_workflow = config.get(StaticStrings.WORKFLOW_MIRROR, false);
265 if (mirror_workflow) {
266 wget_version_str = StaticStrings.NO_WGET_STR;
267 // has the user specified a path?
268 if (wget_path != null && !wget_path.equals("")) {
269 File wget_file = new File(wget_path);
270 if (wget_file.exists()) {
271 // we assume its ok if its there
272 wget_version_str = StaticStrings.WGET_STR;
273 }
274 }
275
276 // it hasn't been set by the user so we use the greenstone one
277 if (wget_version_str.equals(StaticStrings.NO_WGET_STR)) {
278 // TODO fix for gs3
279 wget_path = Utility.getWGetPath(gsdl_path);
280 File wget_file = new File(wget_path);
281 if (!wget_file.exists()) {
282 // we give up trying to find one
283 missingWGET();
284 } else {
285 // we have found one
286 wget_version_str = StaticStrings.WGET_STR;
287 }
288 }
289
290 if (wget_version_str.equals(StaticStrings.WGET_STR)) {
291 // we have found one, should we check the version??
292 wget_version_str = testWGetVersion(wget_path);
293 if (wget_version_str.equals(StaticStrings.WGET_OLD_STR)) {
294 oldWGET();
295 }
296 }
297
298 // tell the config the new values
299 config.setWGetPath(wget_path);
300 config.setWGetVersion(wget_version_str);
301 }
302
303 // Set default font
304 setUIFont(config.getFont("general.font", true), config.getFont("general.tooltip_font", true));
305 // Set up proxy
306 setProxy();
307 // Now we set up an Authenticator
308 Authenticator.setDefault(new GAuthenticator());
309
310 assoc_man = new FileAssociationManager();
311 // Create File Manager
312 f_man = new FileManager();
313 // Create Collection Manager
314 c_man = new CollectionManager();
315
316 if (GS3) {
317 if (site_name==null) {
318 site_name = config.site_name;
319 servlet_path = null; // need to reset this
320 }
321 if (servlet_path == null) {
322 servlet_path = config.getServletPath();
323 }
324 }
325
326 // If there was an open collection last session, reopen it.
327 if (open_collection == null) {
328 open_collection = config.getString("general.open_collection", true);
329 }
330 if (!no_load && open_collection.length() > 0) {
331 c_man.loadCollection(open_collection);
332 }
333
334 }
335 catch (Exception error) {
336 error.printStackTrace();
337 }
338
339 // Create GUI Manager (last) or else suffer the death of a thousand NPE's
340 g_man = new GUIManager(size);
341
342 return g_man;
343 }
344
345
346
347 public void run(Dimension size, Splash splash, GUIManager g_man)
348 {
349 // Size and place the frame on the screen
350 Rectangle bounds = config.getBounds("general.bounds", true);
351 if (bounds == null) {
352 // Choose a sensible default value
353 bounds = new Rectangle(0, 0, 640, 480);
354 }
355
356 // Ensure width and height are reasonable
357 size = bounds.getSize();
358 if (size.width < 640) {
359 size.width = 640;
360 }
361 else if (size.width > config.screen_size.width) {
362 size.width = config.screen_size.width;
363 }
364 if (size.height < 480) {
365 size.height = 480;
366 }
367 else if (size.height > config.screen_size.height) {
368 size.height = config.screen_size.height;
369 }
370
371 if (splash != null) { splash.toFront(); }
372
373 if (!g_man_built) {
374
375 g_man.display();
376
377 // Place the window in the desired location on the screen, if this is do-able (not under most linux window managers apparently. In fact you're lucky if they listen to any of your screen size requests).
378 g_man.setLocation(bounds.x, bounds.y);
379 g_man.setVisible(true);
380
381 // After the window has been made visible, check that it is in the correct place
382 // sometimes java places a window not in the correct place,
383 // but with an offset. If so, we work out what the offset is
384 // and change the desired location to take that into account
385 Point location = g_man.getLocation();
386 int x_offset = bounds.x - location.x;
387 int y_offset = bounds.y - location.y;
388 // If not, offset the window to move it into the correct location
389 if (x_offset > 0 || y_offset > 0) {
390 ///ystem.err.println("changing the location to "+(bounds.x + x_offset)+" "+ (bounds.y + y_offset));
391 g_man.setLocation(bounds.x + x_offset, bounds.y + y_offset);
392 }
393
394 // The 'after-display' triggers several events which don't occur until after the visual components are actually available on screen. Examples of these would be the various html renderings, as they can't happen offscreen.
395 g_man.afterDisplay();
396 g_man_built = true;
397 }
398 else {
399 g_man.setVisible(true);
400 }
401
402 if (splash != null) {
403 // Hide the splash screen
404 splash.hide();
405 splash.destroy();
406 splash = null;
407 }
408 }
409
410
411 /** Exits the Gatherer after ensuring that things needing saving are saved.
412 * @see java.io.FileOutputStream
413 * @see java.io.PrintStream
414 * @see java.lang.Exception
415 * @see javax.swing.JOptionPane
416 * @see org.greenstone.gatherer.Configuration
417 * @see org.greenstone.gatherer.collection.CollectionManager
418 * @see org.greenstone.gatherer.gui.GUIManager
419 */
420 public void exit() {
421 exit = true;
422 // If we have an open collection make note of it.
423 config.setString("general.open_collection", true, null);
424 if(c_man.ready()) {
425 ///ystem.err.println("Collection open.");
426 if(c_man.saved()) {
427 ///ystem.err.println("Collection has been recently saved, so I'll remember it for next time.");
428 config.setString("general.open_collection", true, c_man.getCollectionFilename());
429 }
430 c_man.closeCollection();
431 }
432 if(assoc_man != null) {
433 assoc_man.save();
434 assoc_man = null;
435 }
436
437 // Store the current position and size (if reasonable) of the Gatherer for next time
438 Rectangle bounds = g_man.getBounds();
439 config.setBounds("general.bounds", true, bounds);
440
441 // Save configuration.
442 saveConfig();
443
444 // Get the gui to deallocate
445 g_man.hide();
446 g_man.destroy();
447 g_man_built = false;
448
449
450 // Flush dictionary
451 // dictionary.destroy();
452
453 // Flush debug
454 if(debug != null) {
455 try {
456 debug.flush();
457 debug.close();
458 }
459 catch (Exception error) {
460 error.printStackTrace();
461 }
462 }
463
464 // If we started a server, we should try to stop it.
465 if(!GS3 && gsdlsite_cfg != null) {
466 stopServerEXE();
467 }
468
469 if(apps.size() == 0) {
470 if (!Gatherer.isGsdlRemote) {
471 System.exit(0);
472 }
473 }
474 else {
475 JOptionPane.showMessageDialog(g_man, Dictionary.get("General.Outstanding_Processes"), Dictionary.get("General.Outstanding_Processes_Title"), JOptionPane.ERROR_MESSAGE);
476 g_man.hide();
477 }
478 }
479
480 // Used to send messages to the local library
481 // Warning: this has a lot of potential for nasty race conditions
482 // The response code is returned immediately -- but this does not mean the local
483 // library action has finished!
484 public void configServer(String command)
485 {
486 try {
487 String raw_url = config.exec_address.toString() + command;
488 URL url = new URL(raw_url);
489 Gatherer.println("Action: " + raw_url);
490 HttpURLConnection library_connection = (HttpURLConnection) url.openConnection();
491 int response_code = library_connection.getResponseCode();
492 if(HttpURLConnection.HTTP_OK <= response_code && response_code < HttpURLConnection.HTTP_MULT_CHOICE) {
493 Gatherer.println("200 - Complete.");
494 }
495 else {
496 Gatherer.println("404 - Failed.");
497 }
498 url = null;
499 }
500 catch (Exception ex) {
501 ex.printStackTrace();
502 Gatherer.printStackTrace(ex);
503 }
504 }
505
506 // used to send reload coll messages to the tomcat server
507 public void configGS3Server(String site, String command) {
508
509 try {
510 // need to add the servlet name to the exec address
511 String raw_url = config.exec_address.toString() + config.getServletPath() + command;
512 URL url = new URL(raw_url);
513 Gatherer.println("Action: " + raw_url);
514 HttpURLConnection library_connection = (HttpURLConnection) url.openConnection();
515 int response_code = library_connection.getResponseCode();
516 if(HttpURLConnection.HTTP_OK <= response_code && response_code < HttpURLConnection.HTTP_MULT_CHOICE) {
517 Gatherer.println("200 - Complete.");
518 }
519 else {
520 Gatherer.println("404 - Failed.");
521 }
522 url = null;
523 }
524 catch(Exception exception) {
525 Gatherer.printStackTrace(exception);
526 ///ystem.err.println("Bad URL.");
527 }
528 }
529
530 /** Retrieve the metadata directory, as required by any MSMCaller implementation.
531 * @return The currently active collection metadata directory as a <strong>String</strong>.
532 * @see org.greenstone.gatherer.collection.CollectionManager
533 */
534 public String getCollectionMetadata() {
535 if (c_man != null && c_man.ready()) {
536 return c_man.getCollectionMetadata();
537 }
538 return "";
539 }
540
541 /** Used to 'spawn' a new child application when a file is double clicked.
542 * @param file The file to open
543 * @see org.greenstone.gatherer.Gatherer.ExternalApplication
544 */
545 public void spawnApplication(File file) {
546 String [] commands = assoc_man.getCommand(file);
547 if(commands != null) {
548 ExternalApplication app = new ExternalApplication(commands);
549 apps.add(app);
550 app.start();
551 }
552 else {
553 ///ystem.err.println("No open command available.");
554 }
555 }
556
557 /** Used to 'spawn' a new browser application or reset an existing one when the preview button is clicked
558 * @param url The url to open the browser at
559 * @see org.greenstone.gatherer.Gatherer.BrowserApplication
560 */
561 public void spawnBrowser(String url) {
562 String command = assoc_man.getBrowserCommand(url);
563 if (command != null) {
564 BrowserApplication app = new BrowserApplication(command, url);
565 apps.add(app);
566 app.start();
567 }
568 else {
569 ///ystem.err.println("No browser command available.");
570 }
571 }
572
573 /** Prints a warning message about a missing library path, which means the final collection cannot be previewed in the Gatherer.
574 */
575 static public void missingEXEC() {
576 WarningDialog dialog = new WarningDialog("warning.MissingEXEC", "general.exec_address");
577 dialog.setValueField(new URLField(Gatherer.config.getColor("coloring.editable_foreground", false), Gatherer.config.getColor("coloring.editable_background", false), Gatherer.config.getColor("coloring.error_foreground", false), Gatherer.config.getColor("coloring.error_background", false)));
578 dialog.display();
579 dialog.dispose();
580 dialog = null;
581
582 String library_path_string = Gatherer.config.getString("general.exec_address", true);
583 if (!library_path_string.equals("")) {
584 try {
585 Gatherer.config.exec_address = new URL(library_path_string);
586 }
587 catch (MalformedURLException error) {
588 ///ystem.err.println("Error: Bad address: " + exec_address_string);
589 }
590 }
591 }
592
593 /** Prints a warning message about a missing GSDL path, which although not fatal pretty much ensures nothing will work properly in the Gatherer.
594 */
595 static public void missingGSDL() {
596 WarningDialog dialog = new WarningDialog("warning.MissingGSDL", false);
597 dialog.display();
598 dialog.dispose();
599 dialog = null;
600 }
601
602 /** Prints a warning message about a missing PERL path, which although not fatal pretty much ensures no collection creation/building will work properly in the Gatherer. */
603 static public void missingPERL() {
604 WarningDialog dialog = new WarningDialog("warning.MissingPERL", false);
605 dialog.display();
606 dialog.dispose();
607 dialog = null;
608 }
609
610 /** Prints a warning message about a missing a valid WGet path. not fatal, but mirroring won't work */
611 static public void missingWGET() {
612 WarningDialog dialog = new WarningDialog("warning.MissingWGET", false);
613 dialog.display();
614 dialog.dispose();
615 dialog = null;
616 }
617 /** Prints a warning message about having an old version of WGet. not fatal, but mirroring may not work properly */
618 static public void oldWGET() {
619 WarningDialog dialog = new WarningDialog("warning.OldWGET", false);
620 dialog.display();
621 dialog.dispose();
622 dialog = null;
623 }
624 /** Print a message to the debug stream. */
625 static synchronized public void print(String message) {
626 if(debug != null) {
627 debug.print(message);
628 System.err.print(message);
629 }
630 }
631 /** Print a message to the debug stream. */
632 static synchronized public void println(String message) {
633 if(debug != null) {
634 debug.println(message);
635 System.err.println(message);
636 }
637 }
638
639 /** Print a stack trace to the debug stream. */
640 static synchronized public void printStackTrace(Exception exception) {
641 if(debug != null) {
642 exception.printStackTrace(debug);
643 exception.printStackTrace();
644 }
645 }
646 /** Prints a usage message to screen.
647 */
648 static public void printUsage(Dictionary dictionary) {
649 System.out.println(Dictionary.get("General.Usage"));
650 }
651
652 /** Sets up the proxy connection by setting JVM Environment flags and creating a new Authenticator.
653 * @see java.lang.Exception
654 * @see java.lang.System
655 * @see java.net.Authenticator
656 * @see org.greenstone.gatherer.Configuration
657 * @see org.greenstone.gatherer.GAuthenticator
658 */
659 static public void setProxy() {
660 try {// Can throw several exceptions
661 if(Gatherer.config.get("general.use_proxy", true)) {
662 System.setProperty("http.proxyType", "4");
663 System.setProperty("http.proxyHost", Gatherer.config.getString("general.proxy_host", true));
664 System.setProperty("http.proxyPort", Gatherer.config.getString("general.proxy_port", true));
665 System.setProperty("http.proxySet", "true");
666 } else {
667 System.setProperty("http.proxySet", "false");
668 }
669 } catch (Exception error) {
670 Gatherer.println("Error in Gatherer.initProxy(): " + error);
671 Gatherer.printStackTrace(error);
672 }
673 }
674
675 /** Set all the default fonts of the program to a choosen font, except the tooltip font which should be some fixed width font.
676 * @param f The default font to use in the Gatherer as a <strong>FontUIResource</strong>.
677 * @param ttf The tooltip font to use also as a <strong>FontUIResource</strong>.
678 * @see java.util.Enumeration
679 * @see javax.swing.UIManager
680 */
681 static private void setUIFont(FontUIResource f, FontUIResource ttf) {
682 // sets the default font for all Swing components.
683 // ex.
684 // setUIFont (new FontUIResource("Serif",Font.ITALIC,12));
685 //
686 Enumeration keys = UIManager.getDefaults().keys();
687 while (keys.hasMoreElements()) {
688 Object key = keys.nextElement();
689 Object value = UIManager.get (key);
690 if (value instanceof FontUIResource)
691 UIManager.put (key, f);
692 }
693 // Now set the tooltip font to some fixed width font
694 UIManager.put("ToolTip.font", ttf);
695 }
696
697 /** Loads the configuration file if one exists. Otherwise it creates a new one. Currently uses serialization.
698 * @param gsdl_path The path to the gsdl directory, gathered from the startup arguments, and presented as a <strong>String</strong>.
699 * @param exec_path The path to the library executable, gathered from the startup arguments, and presented as a <strong>String</strong>.
700 * @param perl_path The path to the PERL compiler as a <strong>String</strong>. Necessary for windows platform versions.
701 * @param mirroring_enabled
702 * @param wget_version_str
703 * @param wget_path
704 * @see java.io.FileInputStream
705 * @see java.io.ObjectInputStream
706 * @see java.lang.Exception
707 * @see org.greenstone.gatherer.Configuration
708 */
709 private void loadConfig(String gsdl_path, String gsdl3_path, String exec_path, String perl_path, boolean mirroring_enabled, String site_name) {
710 try {
711 config = new Configuration(gsdl_path, gsdl3_path, exec_path, perl_path, mirroring_enabled, site_name);
712 }
713 catch (Exception error) {
714 Gatherer.println(Configuration.CONFIG_XML+" is not a well formed XML document.");
715 Gatherer.printStackTrace(error);
716 }
717 if (GS3) {
718 try {
719 servlet_config = new ServletConfiguration(gsdl3_path);
720 } catch (Exception error) {
721 error.printStackTrace();
722 }
723 }
724 }
725
726 /** Causes the general configuration file to export itself to xml. Doesn't effect any remaining collection configuration, as its up to the collection manager to handle them (especially since we have no idea where they are going). */
727 private void saveConfig() {
728 try {
729 config.save();
730 } catch (Exception error) {
731 Gatherer.printStackTrace(error);
732 }
733 }
734
735 private void startServerEXE() {
736 if(config.exec_file != null && config.exec_address == null && Utility.isWindows() && !GS3) {
737 // First of all we create a GSDLSiteCFG object and check if a URL is already present, in which case the server is already running.
738 gsdlsite_cfg = new GSDLSiteConfig(config.exec_file);
739 String url = gsdlsite_cfg.getURL();
740 // If its already running then set exec address.
741 if(url != null) {
742 try {
743 config.exec_address = new URL(url);
744 }
745 catch(Exception error) {
746 }
747 }
748 // Otherwise its time to run the server in a spawned process.
749 if(config.exec_address == null && config.exec_file.exists()) {
750 // Configure for immediate entry. Note that this only works if the gsdlsite.cfg file exists.
751 gsdlsite_cfg.set();
752 // Spawn server
753 String command = config.exec_file.getAbsolutePath() + " " + gsdlsite_cfg.getSiteConfigFilename();
754 server = new ExternalApplication(command);
755 server.start();
756 command = null;
757 // Now we have to wait until program has started. We do this by reloading and checking
758 ///ystem.err.print("Waiting until the local library has loaded");
759 try {
760 gsdlsite_cfg.load();
761
762 int try_again = JOptionPane.YES_OPTION;
763 int attempt_count = 0;
764 while(gsdlsite_cfg.getURL() == null && try_again == JOptionPane.YES_OPTION) {
765 ///ystem.err.print(".");
766 if(attempt_count == 60) {
767 attempt_count = 0;
768 try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.QuitTimeOut"), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
769 }
770 else {
771 synchronized(this) {
772 wait(1000); // Wait one second (give or take)
773 }
774 gsdlsite_cfg.load();
775 attempt_count++;
776 }
777 }
778
779 if((url = gsdlsite_cfg.getURL()) != null) {
780 // Ta-da. Now the url should be available.
781 config.exec_address = new URL(url);
782
783 // A quick test involves opening a connection to get the home page for this collection. If this fails then we try changing the url to be localhost.
784 try {
785 Gatherer.println("Try connecting to server on config url: '" + config.exec_address + "'");
786 URLConnection connection = config.exec_address.openConnection();
787 connection.getContent();
788 }
789 catch(IOException bad_url_connection) {
790 try {
791 Gatherer.println("Try connecting to server on local host: '" + gsdlsite_cfg.getLocalHostURL() + "'");
792 config.exec_address = new URL(gsdlsite_cfg.getLocalHostURL ());
793 URLConnection connection = config.exec_address.openConnection();
794 connection.getContent();
795 }
796 catch(IOException worse_url_connection) {
797 Gatherer.println("Can't connect to server on either address.");
798 config.exec_address = null;
799 config.exec_file = null;
800 }
801 }
802 }
803 // Unable to start local library. Show appropriate message.
804 else {
805 missingEXEC();
806 }
807 }
808 catch (Exception error) {
809 error.printStackTrace();
810 }
811 }
812 // Can't do a damb thing.
813 }
814 Gatherer.println("Having started server.exe, exec_address is: " + config.exec_address);
815 }
816
817 private void stopServerEXE() {
818 if(server != null && config.exec_address != null) {
819 // See if its already exited for some reason.
820 gsdlsite_cfg.load();
821 if(gsdlsite_cfg.getURL() != null) {
822 // Send the command for it to exit.
823 configServer(GSDLSiteConfig.QUIT_COMMAND);
824 // Wait until it exits.
825 try {
826 gsdlsite_cfg.load();
827 int try_again = JOptionPane.YES_OPTION;
828 int attempt_count = 0;
829 while(gsdlsite_cfg.getURL() != null && try_again == JOptionPane.YES_OPTION) {
830 if(attempt_count == 60) {
831 attempt_count = 0;
832 try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.QuitTimeOut"), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
833 }
834 else {
835 synchronized(this) {
836 wait(1000); // Wait one second (give or take)
837 }
838 gsdlsite_cfg.load();
839 attempt_count++;
840 }
841 }
842 //if(gsdlsite_cfg.getURL() != null) {
843 //JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.QuitManual"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
844 //}
845 }
846 catch (Exception error) {
847 error.printStackTrace();
848 }
849 }
850 // Restore the gsdlsite_cfg.
851 if(gsdlsite_cfg != null) {
852 gsdlsite_cfg.restore();
853 }
854 // If the local server is still running then our changed values will get overwritten.
855 if(gsdlsite_cfg.getURL() != null) {
856 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.QuitFailed"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
857 }
858 gsdlsite_cfg = null;
859 server = null;
860 }
861 }
862
863 // TODO fill this in
864 private String testWGetVersion(String wget_path) {
865 return StaticStrings.WGET_STR;
866 }
867
868 /** This private class contains an instance of an external application running within a JVM shell. It is important that this process sits in its own thread, but its more important that when we exit the Gatherer we don't actually System.exit(0) the Gatherer object until the user has volunteerily ended all of these child processes. Otherwise when we quit the Gatherer any changes the users may have made in external programs will be lost and the child processes are automatically deallocated. */
869 private class ExternalApplication
870 extends Thread {
871 private Process process = null;
872 /** The initial command string given to this sub-process. */
873 private String command = null;
874 private String[] commands = null;
875 /** Constructor.
876 * @param command The initial command <strong>String</strong>.
877 */
878 public ExternalApplication(String command) {
879 this.command = command;
880 }
881
882 public ExternalApplication(String[] commands) {
883 this.commands = commands;
884 }
885 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
886 * @see java.lang.Exception
887 * @see java.lang.Process
888 * @see java.lang.Runtime
889 * @see java.lang.System
890 * @see java.util.Vector
891 */
892 public void run() {
893 // Call an external process using the args.
894 try {
895 if(commands != null) {
896 StringBuffer whole_command = new StringBuffer();
897 for(int i = 0; i < commands.length; i++) {
898 whole_command.append(commands[i]);
899 whole_command.append(" ");
900 }
901 println("Running " + whole_command.toString());
902 Runtime rt = Runtime.getRuntime();
903 process = rt.exec(commands);
904 process.waitFor();
905 }
906 else {
907 println("Running " + command);
908 Runtime rt = Runtime.getRuntime();
909 process = rt.exec(command);
910 process.waitFor();
911 }
912 }
913 catch (Exception error) {
914 println("Error in ExternalApplication.run(): " + error);
915 printStackTrace(error);
916 }
917 // Remove ourself from Gatherer list of threads.
918 apps.remove(this);
919 // Call exit if we were the last outstanding child process thread.
920 if(apps.size() == 0 && exit == true) {
921 stopServerEXE();
922 System.exit(0);
923 }
924 }
925 public void stopExternalApplication() {
926 if(process != null) {
927 process.destroy();
928 }
929 }
930 }
931 /** This private class contains an instance of an external application running within a JVM shell. It is important that this process sits in its own thread, but its more important that when we exit the Gatherer we don't actually System.exit(0) the Gatherer object until the user has volunteerily ended all of these child processes. Otherwise when we quit the Gatherer any changes the users may have made in external programs will be lost and the child processes are automatically deallocated. */
932 private class BrowserApplication
933 extends Thread {
934 private Process process = null;
935 /** The initial command string given to this sub-process. */
936 private String command = null;
937 private String url = null;
938 private String[] commands = null;
939 /** Constructor.
940 * @param command The initial command <strong>String</strong>.
941 */
942// public BrowserApplication(String command) {
943// this.command = command;
944// }
945
946 public BrowserApplication(String command, String url) {
947 StringTokenizer st = new StringTokenizer(command);
948 int num_tokens = st.countTokens();
949 this.commands = new String [num_tokens];
950 int i=0;
951 while (st.hasMoreTokens()) {
952 commands[i] = st.nextToken();
953 i++;
954 }
955 //this.commands = commands;
956 this.url = url;
957 }
958 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
959 * @see java.lang.Exception
960 * @see java.lang.Process
961 * @see java.lang.Runtime
962 * @see java.lang.System
963 * @see java.util.Vector
964 */
965 public void run() {
966 // Call an external process using the args.
967 if(commands == null) {
968 apps.remove(this);
969 return;
970 }
971 try {
972 String prog_name = commands[0];
973 String lower_name = prog_name.toLowerCase();
974 if (lower_name.indexOf("mozilla") != -1 || lower_name.indexOf("netscape") != -1) {
975 Gatherer.println("found mozilla or netscape, trying remote it");
976 // mozilla and netscape, try using a remote command to get things in the same window
977 String [] new_commands = new String[] {prog_name, "-raise", "-remote", "openURL("+url+",new-tab)"};
978 if(debug != null) {
979 printArray(new_commands);
980 }
981 Runtime rt = Runtime.getRuntime();
982 process = rt.exec(new_commands);
983 int exitCode = process.waitFor();
984 if (exitCode != 0) { // if Netscape or mozilla was not open
985 Gatherer.println("couldn't do remote, trying original command");
986 if(debug != null) {
987 printArray(commands);
988 }
989 process = rt.exec(commands); // try the original command
990 }
991 } else {
992 // just run what we have been given
993 StringBuffer whole_command = new StringBuffer();
994 for(int i = 0; i < commands.length; i++) {
995 whole_command.append(commands[i]);
996 whole_command.append(" ");
997 }
998 println("Running " + whole_command.toString());
999 Runtime rt = Runtime.getRuntime();
1000 process = rt.exec(commands);
1001 process.waitFor();
1002 }
1003 }
1004
1005 catch (Exception error) {
1006 println("Error in BrowserApplication.run(): " + error);
1007 printStackTrace(error);
1008 }
1009 // Remove ourself from Gatherer list of threads.
1010 apps.remove(this);
1011 // Call exit if we were the last outstanding child process thread.
1012 if(apps.size() == 0 && exit == true) {
1013 stopServerEXE();
1014 System.exit(0);
1015 }
1016 }
1017 public void printArray(String [] array) {
1018 for(int i = 0; i < array.length; i++) {
1019 debug.print(array[i]+" ");
1020 System.err.println(array[i]+" ");
1021 }
1022 }
1023 public void stopBrowserApplication() {
1024 if(process != null) {
1025 process.destroy();
1026 }
1027 }
1028 }
1029
1030 /** This class is intented to detect a specific SIGNAL, in this case SIGINT, and exit properly, rather than letting the Gatherer be interrupted which has the potential to leave erroneous lock files. */
1031// private class CTRLCHandler
1032// implements SignalHandler {
1033// /** <i>true</i> if we ignore any other signals we receive, most likely because we are already dealing with one, <i>false</i> otherwise. */
1034// private boolean ignore = false;
1035// /** The method called by the system to inform us a signal has occured.
1036// * @param sig The <strong>Signal</strong> itself.
1037// * @see org.greenstone.gatherer.collection.CollectionManager
1038// */
1039// public void handle(Signal sig) {
1040// if(!ignore) {
1041// ignore = true;
1042// // handle SIGINT
1043// System.out.println("Caught Ctrl-C...");
1044// if(c_man != null && c_man.ready()) {
1045// c_man.closeCollection();
1046// }
1047// exit();
1048// ignore = false;
1049// }
1050// }
1051// }
1052
1053 private class PerlTest {
1054
1055 private String[] command = new String[2];
1056
1057 public PerlTest() {
1058 if(Utility.isWindows()) {
1059 command[0] = Utility.PERL_EXECUTABLE_WINDOWS;
1060 }
1061 else {
1062 command[0] = Utility.PERL_EXECUTABLE_UNIX;
1063 }
1064 command[1] = "-version";
1065 }
1066
1067 public boolean found() {
1068 boolean found = false;
1069 try {
1070 Process prcs = Runtime.getRuntime().exec(command);
1071 prcs.waitFor();
1072 found = (prcs.exitValue() == 0);
1073 prcs = null;
1074 }
1075 catch(Exception error) {
1076 }
1077 return found;
1078 }
1079
1080 public String toString() {
1081 return command[0];
1082 }
1083 }
1084}
Note: See TracBrowser for help on using the repository browser.