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

Last change on this file since 8142 was 8062, checked in by kjdon, 20 years ago

changed the library url warnign message for gs3

  • Property svn:keywords set to Author Date Id Revision
File size: 37.4 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 String message_name;
577 if (GS3) {
578 message_name = "warning.MissingEXEC_GS3";
579 } else {
580 message_name = "warning.MissingEXEC";
581 }
582 WarningDialog dialog = new WarningDialog(message_name, "general.exec_address" );
583 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)));
584 dialog.display();
585 dialog.dispose();
586 dialog = null;
587
588 String library_path_string = Gatherer.config.getString("general.exec_address", true);
589 if (!library_path_string.equals("")) {
590 try {
591 Gatherer.config.exec_address = new URL(library_path_string);
592 }
593 catch (MalformedURLException error) {
594 ///ystem.err.println("Error: Bad address: " + exec_address_string);
595 }
596 }
597 }
598
599 /** Prints a warning message about a missing GSDL path, which although not fatal pretty much ensures nothing will work properly in the Gatherer.
600 */
601 static public void missingGSDL() {
602 WarningDialog dialog = new WarningDialog("warning.MissingGSDL", false);
603 dialog.display();
604 dialog.dispose();
605 dialog = null;
606 }
607
608 /** 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. */
609 static public void missingPERL() {
610 WarningDialog dialog = new WarningDialog("warning.MissingPERL", false);
611 dialog.display();
612 dialog.dispose();
613 dialog = null;
614 }
615
616 /** Prints a warning message about a missing a valid WGet path. not fatal, but mirroring won't work */
617 static public void missingWGET() {
618 WarningDialog dialog = new WarningDialog("warning.MissingWGET", false);
619 dialog.display();
620 dialog.dispose();
621 dialog = null;
622 }
623 /** Prints a warning message about having an old version of WGet. not fatal, but mirroring may not work properly */
624 static public void oldWGET() {
625 WarningDialog dialog = new WarningDialog("warning.OldWGET", false);
626 dialog.display();
627 dialog.dispose();
628 dialog = null;
629 }
630 /** Print a message to the debug stream. */
631 static synchronized public void print(String message) {
632 if(debug != null) {
633 debug.print(message);
634 System.err.print(message);
635 }
636 }
637 /** Print a message to the debug stream. */
638 static synchronized public void println(String message) {
639 if(debug != null) {
640 debug.println(message);
641 System.err.println(message);
642 }
643 }
644
645 /** Print a stack trace to the debug stream. */
646 static synchronized public void printStackTrace(Exception exception) {
647 if(debug != null) {
648 exception.printStackTrace(debug);
649 exception.printStackTrace();
650 }
651 }
652 /** Prints a usage message to screen.
653 */
654 static public void printUsage(Dictionary dictionary) {
655 System.out.println(Dictionary.get("General.Usage"));
656 }
657
658 /** Sets up the proxy connection by setting JVM Environment flags and creating a new Authenticator.
659 * @see java.lang.Exception
660 * @see java.lang.System
661 * @see java.net.Authenticator
662 * @see org.greenstone.gatherer.Configuration
663 * @see org.greenstone.gatherer.GAuthenticator
664 */
665 static public void setProxy() {
666 try {// Can throw several exceptions
667 if(Gatherer.config.get("general.use_proxy", true)) {
668 System.setProperty("http.proxyType", "4");
669 System.setProperty("http.proxyHost", Gatherer.config.getString("general.proxy_host", true));
670 System.setProperty("http.proxyPort", Gatherer.config.getString("general.proxy_port", true));
671 System.setProperty("http.proxySet", "true");
672 } else {
673 System.setProperty("http.proxySet", "false");
674 }
675 } catch (Exception error) {
676 Gatherer.println("Error in Gatherer.initProxy(): " + error);
677 Gatherer.printStackTrace(error);
678 }
679 }
680
681 /** Set all the default fonts of the program to a choosen font, except the tooltip font which should be some fixed width font.
682 * @param f The default font to use in the Gatherer as a <strong>FontUIResource</strong>.
683 * @param ttf The tooltip font to use also as a <strong>FontUIResource</strong>.
684 * @see java.util.Enumeration
685 * @see javax.swing.UIManager
686 */
687 static private void setUIFont(FontUIResource f, FontUIResource ttf) {
688 // sets the default font for all Swing components.
689 // ex.
690 // setUIFont (new FontUIResource("Serif",Font.ITALIC,12));
691 //
692 Enumeration keys = UIManager.getDefaults().keys();
693 while (keys.hasMoreElements()) {
694 Object key = keys.nextElement();
695 Object value = UIManager.get (key);
696 if (value instanceof FontUIResource)
697 UIManager.put (key, f);
698 }
699 // Now set the tooltip font to some fixed width font
700 UIManager.put("ToolTip.font", ttf);
701 }
702
703 /** Loads the configuration file if one exists. Otherwise it creates a new one. Currently uses serialization.
704 * @param gsdl_path The path to the gsdl directory, gathered from the startup arguments, and presented as a <strong>String</strong>.
705 * @param exec_path The path to the library executable, gathered from the startup arguments, and presented as a <strong>String</strong>.
706 * @param perl_path The path to the PERL compiler as a <strong>String</strong>. Necessary for windows platform versions.
707 * @param mirroring_enabled
708 * @param wget_version_str
709 * @param wget_path
710 * @see java.io.FileInputStream
711 * @see java.io.ObjectInputStream
712 * @see java.lang.Exception
713 * @see org.greenstone.gatherer.Configuration
714 */
715 private void loadConfig(String gsdl_path, String gsdl3_path, String exec_path, String perl_path, boolean mirroring_enabled, String site_name) {
716 try {
717 config = new Configuration(gsdl_path, gsdl3_path, exec_path, perl_path, mirroring_enabled, site_name);
718 }
719 catch (Exception error) {
720 Gatherer.println(Configuration.CONFIG_XML+" is not a well formed XML document.");
721 Gatherer.printStackTrace(error);
722 }
723 if (GS3) {
724 try {
725 servlet_config = new ServletConfiguration(gsdl3_path);
726 } catch (Exception error) {
727 error.printStackTrace();
728 }
729 }
730 }
731
732 /** 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). */
733 private void saveConfig() {
734 try {
735 config.save();
736 } catch (Exception error) {
737 Gatherer.printStackTrace(error);
738 }
739 }
740
741 private void startServerEXE() {
742 if(config.exec_file != null && config.exec_address == null && Utility.isWindows() && !GS3) {
743 // First of all we create a GSDLSiteCFG object and check if a URL is already present, in which case the server is already running.
744 gsdlsite_cfg = new GSDLSiteConfig(config.exec_file);
745 String url = gsdlsite_cfg.getURL();
746 // If its already running then set exec address.
747 if(url != null) {
748 try {
749 config.exec_address = new URL(url);
750 }
751 catch(Exception error) {
752 }
753 }
754 // Otherwise its time to run the server in a spawned process.
755 if(config.exec_address == null && config.exec_file.exists()) {
756 // Configure for immediate entry. Note that this only works if the gsdlsite.cfg file exists.
757 gsdlsite_cfg.set();
758 // Spawn server
759 String command = config.exec_file.getAbsolutePath() + " " + gsdlsite_cfg.getSiteConfigFilename();
760 server = new ExternalApplication(command);
761 server.start();
762 command = null;
763 // Now we have to wait until program has started. We do this by reloading and checking
764 ///ystem.err.print("Waiting until the local library has loaded");
765 try {
766 gsdlsite_cfg.load();
767
768 int try_again = JOptionPane.YES_OPTION;
769 int attempt_count = 0;
770 while(gsdlsite_cfg.getURL() == null && try_again == JOptionPane.YES_OPTION) {
771 ///ystem.err.print(".");
772 if(attempt_count == 60) {
773 attempt_count = 0;
774 try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.QuitTimeOut"), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
775 }
776 else {
777 synchronized(this) {
778 wait(1000); // Wait one second (give or take)
779 }
780 gsdlsite_cfg.load();
781 attempt_count++;
782 }
783 }
784
785 if((url = gsdlsite_cfg.getURL()) != null) {
786 // Ta-da. Now the url should be available.
787 config.exec_address = new URL(url);
788
789 // 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.
790 try {
791 Gatherer.println("Try connecting to server on config url: '" + config.exec_address + "'");
792 URLConnection connection = config.exec_address.openConnection();
793 connection.getContent();
794 }
795 catch(IOException bad_url_connection) {
796 try {
797 Gatherer.println("Try connecting to server on local host: '" + gsdlsite_cfg.getLocalHostURL() + "'");
798 config.exec_address = new URL(gsdlsite_cfg.getLocalHostURL ());
799 URLConnection connection = config.exec_address.openConnection();
800 connection.getContent();
801 }
802 catch(IOException worse_url_connection) {
803 Gatherer.println("Can't connect to server on either address.");
804 config.exec_address = null;
805 config.exec_file = null;
806 }
807 }
808 }
809 // Unable to start local library. Show appropriate message.
810 else {
811 missingEXEC();
812 }
813 }
814 catch (Exception error) {
815 error.printStackTrace();
816 }
817 }
818 // Can't do a damb thing.
819 }
820 Gatherer.println("Having started server.exe, exec_address is: " + config.exec_address);
821 }
822
823 private void stopServerEXE() {
824 if(server != null && config.exec_address != null) {
825 // See if its already exited for some reason.
826 gsdlsite_cfg.load();
827 if(gsdlsite_cfg.getURL() != null) {
828 // Send the command for it to exit.
829 configServer(GSDLSiteConfig.QUIT_COMMAND);
830 // Wait until it exits.
831 try {
832 gsdlsite_cfg.load();
833 int try_again = JOptionPane.YES_OPTION;
834 int attempt_count = 0;
835 while(gsdlsite_cfg.getURL() != null && try_again == JOptionPane.YES_OPTION) {
836 if(attempt_count == 60) {
837 attempt_count = 0;
838 try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.QuitTimeOut"), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
839 }
840 else {
841 synchronized(this) {
842 wait(1000); // Wait one second (give or take)
843 }
844 gsdlsite_cfg.load();
845 attempt_count++;
846 }
847 }
848 //if(gsdlsite_cfg.getURL() != null) {
849 //JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.QuitManual"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
850 //}
851 }
852 catch (Exception error) {
853 error.printStackTrace();
854 }
855 }
856 // Restore the gsdlsite_cfg.
857 if(gsdlsite_cfg != null) {
858 gsdlsite_cfg.restore();
859 }
860 // If the local server is still running then our changed values will get overwritten.
861 if(gsdlsite_cfg.getURL() != null) {
862 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.QuitFailed"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
863 }
864 gsdlsite_cfg = null;
865 server = null;
866 }
867 }
868
869 // TODO fill this in
870 private String testWGetVersion(String wget_path) {
871 return StaticStrings.WGET_STR;
872 }
873
874 /** 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. */
875 private class ExternalApplication
876 extends Thread {
877 private Process process = null;
878 /** The initial command string given to this sub-process. */
879 private String command = null;
880 private String[] commands = null;
881 /** Constructor.
882 * @param command The initial command <strong>String</strong>.
883 */
884 public ExternalApplication(String command) {
885 this.command = command;
886 }
887
888 public ExternalApplication(String[] commands) {
889 this.commands = commands;
890 }
891 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
892 * @see java.lang.Exception
893 * @see java.lang.Process
894 * @see java.lang.Runtime
895 * @see java.lang.System
896 * @see java.util.Vector
897 */
898 public void run() {
899 // Call an external process using the args.
900 try {
901 if(commands != null) {
902 StringBuffer whole_command = new StringBuffer();
903 for(int i = 0; i < commands.length; i++) {
904 whole_command.append(commands[i]);
905 whole_command.append(" ");
906 }
907 println("Running " + whole_command.toString());
908 Runtime rt = Runtime.getRuntime();
909 process = rt.exec(commands);
910 process.waitFor();
911 }
912 else {
913 println("Running " + command);
914 Runtime rt = Runtime.getRuntime();
915 process = rt.exec(command);
916 process.waitFor();
917 }
918 }
919 catch (Exception error) {
920 println("Error in ExternalApplication.run(): " + error);
921 printStackTrace(error);
922 }
923 // Remove ourself from Gatherer list of threads.
924 apps.remove(this);
925 // Call exit if we were the last outstanding child process thread.
926 if(apps.size() == 0 && exit == true) {
927 stopServerEXE();
928 System.exit(0);
929 }
930 }
931 public void stopExternalApplication() {
932 if(process != null) {
933 process.destroy();
934 }
935 }
936 }
937 /** 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. */
938 private class BrowserApplication
939 extends Thread {
940 private Process process = null;
941 /** The initial command string given to this sub-process. */
942 private String command = null;
943 private String url = null;
944 private String[] commands = null;
945 /** Constructor.
946 * @param command The initial command <strong>String</strong>.
947 */
948// public BrowserApplication(String command) {
949// this.command = command;
950// }
951
952 public BrowserApplication(String command, String url) {
953 StringTokenizer st = new StringTokenizer(command);
954 int num_tokens = st.countTokens();
955 this.commands = new String [num_tokens];
956 int i=0;
957 while (st.hasMoreTokens()) {
958 commands[i] = st.nextToken();
959 i++;
960 }
961 //this.commands = commands;
962 this.url = url;
963 }
964 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
965 * @see java.lang.Exception
966 * @see java.lang.Process
967 * @see java.lang.Runtime
968 * @see java.lang.System
969 * @see java.util.Vector
970 */
971 public void run() {
972 // Call an external process using the args.
973 if(commands == null) {
974 apps.remove(this);
975 return;
976 }
977 try {
978 String prog_name = commands[0];
979 String lower_name = prog_name.toLowerCase();
980 if (lower_name.indexOf("mozilla") != -1 || lower_name.indexOf("netscape") != -1) {
981 Gatherer.println("found mozilla or netscape, trying remote it");
982 // mozilla and netscape, try using a remote command to get things in the same window
983 String [] new_commands = new String[] {prog_name, "-raise", "-remote", "openURL("+url+",new-tab)"};
984 if(debug != null) {
985 printArray(new_commands);
986 }
987 Runtime rt = Runtime.getRuntime();
988 process = rt.exec(new_commands);
989 int exitCode = process.waitFor();
990 if (exitCode != 0) { // if Netscape or mozilla was not open
991 Gatherer.println("couldn't do remote, trying original command");
992 if(debug != null) {
993 printArray(commands);
994 }
995 process = rt.exec(commands); // try the original command
996 }
997 } else {
998 // just run what we have been given
999 StringBuffer whole_command = new StringBuffer();
1000 for(int i = 0; i < commands.length; i++) {
1001 whole_command.append(commands[i]);
1002 whole_command.append(" ");
1003 }
1004 println("Running " + whole_command.toString());
1005 Runtime rt = Runtime.getRuntime();
1006 process = rt.exec(commands);
1007 process.waitFor();
1008 }
1009 }
1010
1011 catch (Exception error) {
1012 println("Error in BrowserApplication.run(): " + error);
1013 printStackTrace(error);
1014 }
1015 // Remove ourself from Gatherer list of threads.
1016 apps.remove(this);
1017 // Call exit if we were the last outstanding child process thread.
1018 if(apps.size() == 0 && exit == true) {
1019 stopServerEXE();
1020 System.exit(0);
1021 }
1022 }
1023 public void printArray(String [] array) {
1024 for(int i = 0; i < array.length; i++) {
1025 debug.print(array[i]+" ");
1026 System.err.println(array[i]+" ");
1027 }
1028 }
1029 public void stopBrowserApplication() {
1030 if(process != null) {
1031 process.destroy();
1032 }
1033 }
1034 }
1035
1036 /** 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. */
1037// private class CTRLCHandler
1038// implements SignalHandler {
1039// /** <i>true</i> if we ignore any other signals we receive, most likely because we are already dealing with one, <i>false</i> otherwise. */
1040// private boolean ignore = false;
1041// /** The method called by the system to inform us a signal has occured.
1042// * @param sig The <strong>Signal</strong> itself.
1043// * @see org.greenstone.gatherer.collection.CollectionManager
1044// */
1045// public void handle(Signal sig) {
1046// if(!ignore) {
1047// ignore = true;
1048// // handle SIGINT
1049// System.out.println("Caught Ctrl-C...");
1050// if(c_man != null && c_man.ready()) {
1051// c_man.closeCollection();
1052// }
1053// exit();
1054// ignore = false;
1055// }
1056// }
1057// }
1058
1059 private class PerlTest {
1060
1061 private String[] command = new String[2];
1062
1063 public PerlTest() {
1064 if(Utility.isWindows()) {
1065 command[0] = Utility.PERL_EXECUTABLE_WINDOWS;
1066 }
1067 else {
1068 command[0] = Utility.PERL_EXECUTABLE_UNIX;
1069 }
1070 command[1] = "-version";
1071 }
1072
1073 public boolean found() {
1074 boolean found = false;
1075 try {
1076 Process prcs = Runtime.getRuntime().exec(command);
1077 prcs.waitFor();
1078 found = (prcs.exitValue() == 0);
1079 prcs = null;
1080 }
1081 catch(Exception error) {
1082 }
1083 return found;
1084 }
1085
1086 public String toString() {
1087 return command[0];
1088 }
1089 }
1090}
Note: See TracBrowser for help on using the repository browser.