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

Last change on this file since 19544 was 19544, checked in by ak19, 15 years ago

Put back and corrected the GLI code that was recently reverted for dealing with a GSI that's started independently of GLI (via gs2-server.sh) and which has started the server or not yet autoentered the library. Now it works for Linux.

  • Property svn:keywords set to Author Date Id Revision
File size: 47.9 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
29import java.awt.*;
30import java.awt.event.*;
31import java.io.*;
32import java.lang.*;
33import java.net.*;
34import java.util.*;
35import javax.swing.*;
36import javax.swing.plaf.*;
37import javax.swing.text.*;
38
39
40import org.greenstone.gatherer.Configuration;
41import org.greenstone.gatherer.GAuthenticator;
42import org.greenstone.gatherer.FedoraInfo;
43import org.greenstone.gatherer.collection.CollectionManager;
44import org.greenstone.gatherer.feedback.ActionRecorderDialog;
45import org.greenstone.gatherer.feedback.Base64;
46import org.greenstone.gatherer.file.FileManager;
47import org.greenstone.gatherer.file.FileAssociationManager;
48import org.greenstone.gatherer.file.RecycleBin;
49import org.greenstone.gatherer.greenstone.Classifiers;
50import org.greenstone.gatherer.greenstone.LocalGreenstone;
51import org.greenstone.gatherer.greenstone.LocalLibraryServer;
52import org.greenstone.gatherer.greenstone.Plugins;
53import org.greenstone.gatherer.greenstone3.ServletConfiguration;
54import org.greenstone.gatherer.gui.GUIManager;
55import org.greenstone.gatherer.gui.URLField;
56import org.greenstone.gatherer.gui.WarningDialog;
57import org.greenstone.gatherer.gui.FedoraLogin;
58import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
59import org.greenstone.gatherer.util.JarTools;
60import org.greenstone.gatherer.util.StaticStrings;
61import org.greenstone.gatherer.util.Utility;
62
63
64/** Containing the top-level "core" for the Gatherer, this class is the
65 * common core for the GLI application and applet. It first parses the
66 * command line arguments, preparing to update the configuration as
67 * required. Next it loads several important support classes such as the
68 * Configuration and Dictionary. Finally it creates the other important
69 * managers and sends them on their way.
70 * @author John Thompson, Greenstone Digital Library, University of Waikato
71 * @version 2.3
72 */
73public class Gatherer
74{
75 /** The name of the GLI. */
76 static final public String PROGRAM_NAME = "Greenstone Librarian Interface";
77 /** The current version of the GLI.
78 * Note: the gs3-release-maker relies on this variable being declared
79 * in a line which maches this java regex:
80 * ^(.*)String\s*PROGRAM_VERSION\s*=\s*"trunk";
81 * If change the declaration and it no longer matches the regex, please
82 * change the regex in the gs3-release-maker code and in this message
83 */
84
85 static final public String PROGRAM_VERSION = "trunk";
86
87 static private Dimension size = new Dimension(800, 540);
88 static public RemoteGreenstoneServer remoteGreenstoneServer = null;
89
90 /** Has the exit flag been set? */
91 static final public int EXIT_THEN_RESTART= 2;
92 static public boolean exit = false;
93 static public int exit_status = 0;
94
95 static private String gli_directory_path = null;
96 static private String gli_user_directory_path = null;
97
98 static public String client_operating_system = null;
99
100 /** All of the external applications that must exit before we close the Gatherer. */
101 static private Vector apps = new Vector();
102 static private String non_standard_collect_directory_path = null;
103 static public String open_collection_file_path = null;
104 /** A public reference to the FileAssociationManager. */
105 static public FileAssociationManager assoc_man;
106 /** A public reference to the CollectionManager. */
107 static public CollectionManager c_man;
108 /** A public reference to the RecycleBin. */
109 static public RecycleBin recycle_bin;
110 /** a reference to the Servlet Configuration is GS3 */
111 static public ServletConfiguration servlet_config;
112 /** A public reference to the FileManager. */
113 static public FileManager f_man;
114 /** A public reference to the GUIManager. */
115 static public GUIManager g_man = null;
116 static private boolean g_man_built = false;
117
118 /** We are using the GLI for GS3 */
119 static public boolean GS3 = false;
120
121 static public boolean isApplet = false;
122 static public boolean isGsdlRemote = false;
123
124 /* TODO: If we're using local GLI, collections are built locally. If we're using client-GLI
125 * and it contains a gs2build folder in it, then localBuild will also be true (if this is not
126 * turned off in Preferences). If we're remote and this is turned off in Prefs, build remotely. */
127 /*static public boolean buildingLocally = true;*/
128 /** If we're using local GLI, we can always download. If we're using client-GLI, we can only
129 * download if we have a gs2build folder inside it. And if we don't turn off downloadEnabling
130 * in the preferences.
131 */
132 static public boolean isDownloadEnabled = true;
133
134 // feedback stuff
135 /** is the feedback feature enabled? */
136 static public boolean feedback_enabled = true;
137 /** the action recorder dialog */
138 static public ActionRecorderDialog feedback_dialog = null;
139
140 // Refresh reasons
141 static public final int COLLECTION_OPENED = 0;
142 static public final int COLLECTION_CLOSED = 1;
143 static public final int COLLECTION_REBUILT = 2;
144 static public final int PREFERENCES_CHANGED = 3;
145
146 //////kk added////////
147 static public String cgiBase="";
148 /////////////////
149
150 /** Magic to allow Enter to fire the default button. */
151 static {
152 KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
153 Keymap map = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
154 map.removeKeyStrokeBinding(enter);
155 }
156
157 static private URL default_gliserver_url=null;
158
159 public Gatherer(String[] args)
160 {
161 // Display the version to make error reports a lot more useful
162 System.err.println("Version: " + PROGRAM_VERSION + "\n");
163
164 JarTools.initialise(this);
165
166 GetOpt go = new GetOpt(args);
167
168 // Remember the GSDLOS value
169 client_operating_system = go.client_operating_system;
170
171 // If feedback is enabled, set up the recorder dialog
172 if (go.feedback_enabled) {
173 // Use the default locale for now - this will be changed by the Gatherer run method
174 feedback_enabled = true;
175 feedback_dialog = new ActionRecorderDialog(Locale.getDefault());
176 }
177
178 // Are we using a remote Greenstone?
179 if (go.use_remote_greenstone) {
180 isGsdlRemote = true;
181
182 // We don't have a local Greenstone!
183 go.gsdl3_path=null;
184 go.gsdl3_src_path=null;
185
186 // Don't set go.gsdl_path to null, since gdsl_path may still be set
187 // if we have a client-gli containing gs2build folder.
188 // However, keep track of whether we can download.
189 if(go.gsdl_path == null) {
190 isDownloadEnabled = false;
191 }
192
193 // We have to use our own collect directory since we can't use the Greenstone one
194 setCollectDirectoryPath(getGLIUserDirectoryPath() + "collect" + File.separator);
195 }
196 // We have a local Greenstone. OR we have a gs2build folder inside
197 // the client-GLI folder (with which the Download panel becomes enabled)
198 if(isDownloadEnabled) {
199 LocalGreenstone.setDirectoryPath(go.gsdl_path);
200 }
201
202 // Users may specify a non-standard collect directory (eg. when running one GLI in a network environment)
203 if (go.collect_directory_path != null) {
204 setCollectDirectoryPath(go.collect_directory_path);
205 }
206
207 // More special code for running with a remote Greenstone
208 if (isGsdlRemote) {
209 if (go.fedora_info.isActive()) {
210 Configuration.TEMPLATE_CONFIG_XML = "xml/" + Configuration.FEDORA_CONFIG_PREFIX + "configRemote.xml";
211 }
212 else {
213 Configuration.TEMPLATE_CONFIG_XML = "xml/configRemote.xml";
214 }
215
216 Configuration.CONFIG_XML = "configRemote.xml";
217
218 File collect_directory = new File(Gatherer.getCollectDirectoryPath());
219 if (!collect_directory.exists() && !collect_directory.mkdir()) {
220 System.err.println("Warning: Unable to make directory: " + collect_directory);
221 }
222 }
223 else {
224 if (go.fedora_info.isActive()) {
225 Configuration.TEMPLATE_CONFIG_XML = "xml/" + Configuration.FEDORA_CONFIG_PREFIX + Configuration.CONFIG_XML;
226 }
227 // else, the CONFIG_XML uses the default config file, which is for the local GS server
228 }
229
230 init(go.gsdl_path, go.gsdl3_path, go.gsdl3_src_path,
231 go.fedora_info,
232 go.local_library_path, go.library_url_string,
233 go.gliserver_url_string, go.debug, go.perl_path, go.no_load, go.filename, go.site_name,
234 go.servlet_path);
235 }
236
237
238 public void init(String gsdl_path, String gsdl3_path, String gsdl3_src_path,
239 FedoraInfo fedora_info,
240 String local_library_path,
241 String library_url_string, String gliserver_url_string, boolean debug_enabled,
242 String perl_path, boolean no_load, String open_collection,
243 String site_name, String servlet_path)
244 {
245 if (gsdl3_path != null && !gsdl3_path.equals("")) {
246 this.GS3 = true;
247 } else {
248 gsdl3_path = null;
249 gsdl3_src_path = null;
250 }
251
252 // Create the debug stream if required
253 if (debug_enabled) {
254 DebugStream.enableDebugging();
255
256 Calendar now = Calendar.getInstance();
257 String debug_file_path = "debug" + now.get(Calendar.DATE) + "-" + now.get(Calendar.MONTH) + "-" + now.get(Calendar.YEAR) + ".txt";
258
259 // Debug file is created in the user's GLI directory
260 debug_file_path = getGLIUserDirectoryPath() + debug_file_path;
261 DebugStream.println("Debug file path: " + debug_file_path);
262 DebugStream.setDebugFile(debug_file_path);
263 DebugStream.print(System.getProperties());
264 }
265
266 // Delete plugins.dat and classifiers.dat files from previous versions of the GLI (no longer used)
267 File plugins_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "plugins.dat");
268 if (plugins_dat_file.exists()) {
269 System.err.println("Deleting plugins.dat file...");
270 Utility.delete(plugins_dat_file);
271 }
272 File classifiers_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "classifiers.dat");
273 if (classifiers_dat_file.exists()) {
274 System.err.println("Deleting classifiers.dat file...");
275 Utility.delete(classifiers_dat_file);
276 }
277
278 try {
279 // Load GLI config file
280 new Configuration(getGLIUserDirectoryPath(), gsdl_path, gsdl3_path, gsdl3_src_path, site_name,
281 fedora_info);
282
283 // Check we know where Perl is
284 Configuration.perl_path = perl_path;
285 if (isGsdlRemote && !isDownloadEnabled && Utility.isWindows() && Configuration.perl_path != null) {
286 if (Configuration.perl_path.toLowerCase().endsWith("perl.exe")) {
287 Configuration.perl_path = Configuration.perl_path.substring(0, Configuration.perl_path.length() - "perl.exe".length());
288 }
289 if (Configuration.perl_path.endsWith(File.separator)) {
290 Configuration.perl_path = Configuration.perl_path.substring(0, Configuration.perl_path.length() - File.separator.length());
291 }
292 }
293
294 // the feedback dialog has been loaded with a default locale,
295 // now set the user specified one
296 if (feedback_enabled && feedback_dialog != null) {
297 feedback_dialog.setLocale(Configuration.getLocale("general.locale", true));
298 }
299
300 // Read Dictionary
301 new Dictionary(Configuration.getLocale("general.locale", true), Configuration.getFont("general.font", true));
302
303 // check that we are using Sun Java
304 String java_vendor = System.getProperty("java.vendor");
305 if (!java_vendor.equals("Sun Microsystems Inc.")) {
306 System.err.println(Dictionary.get("General.NotSunJava", java_vendor));
307 }
308
309 // Unless we're using remote building, we need to know where the local Greenstone is
310 if (!isGsdlRemote && gsdl_path == null) {
311 missingGSDL();
312 }
313
314 if (fedora_info.isActive()) {
315 popupFedoraInfo();
316 }
317
318 // Finally, we're ready to find out the version of the remote Greenstone server
319 if(isGsdlRemote) {
320 // instantiate the RemoteGreenstoneServer object first
321 remoteGreenstoneServer = new RemoteGreenstoneServer();
322
323 // Set up proxy
324 setProxy();
325 // Now we set up an Authenticator
326 Authenticator.setDefault(new GAuthenticator());
327
328 int greenstoneVersion = 2;
329 requestGLIServerURL();
330 gliserver_url_string = Configuration.gliserver_url.toString();
331
332 greenstoneVersion = remoteGreenstoneServer.getGreenstoneVersion();
333 // Display the version to make error reports a lot more useful
334 System.err.println("Remote Greenstone server version: " + greenstoneVersion);
335 if(greenstoneVersion >= 3) {
336 this.GS3 = true;
337 Configuration.prepareForGS3();
338 }
339
340 if(fedora_info.isActive()) {
341 // when GS server is remote, FEDORA_HOME resides on the remote server side,
342 // but we know the library URL from user-provided information
343 library_url_string = fedora_info.getLibraryURL();
344 } else {
345 library_url_string = remoteGreenstoneServer.getLibraryURL(Configuration.gliserver_url.toString());
346 }
347 // write it into the config file
348 Configuration.setString("general.library_url", true, library_url_string);
349 }
350 else { // local greenstone: Start up the local library server, if that's what we want
351 if (local_library_path != null && !GS3) {
352 LocalLibraryServer.start(gsdl_path, local_library_path);
353 }
354 }
355
356 // The "-library_url" option overwrites anything in the config files
357 if (library_url_string != null && library_url_string.length() > 0) {
358 try {
359 System.err.println("Setting library_url to " + library_url_string + "...");
360 Configuration.library_url = new URL(library_url_string);
361 }
362 catch (MalformedURLException error) {
363 DebugStream.printStackTrace(error);
364 }
365 }
366
367
368 // Check that we now know the Greenstone library URL, since we need this for previewing collections
369 // It is not necessary if an independent GSI was launched and the user hasn't pressed Enter Library yet
370 DebugStream.println("Configuration.library_url = " + Configuration.library_url);
371 if (Configuration.library_url == null && !LocalLibraryServer.isURLPending()) {
372 missingEXEC();
373 }
374
375 // The "-gliserver_url" option overwrites anything in the config files
376 if (gliserver_url_string != null && gliserver_url_string.length() > 0) {
377 try {
378 System.err.println("Setting gliserver_url to " + gliserver_url_string + "...");
379 Configuration.gliserver_url = new URL(gliserver_url_string);
380 }
381 catch (MalformedURLException error) {
382 DebugStream.printStackTrace(error);
383 }
384 }
385
386 // If we're using a remote Greenstone we need to know where the gliserver script is
387 DebugStream.println("Configuration.gliserver_url = " + Configuration.gliserver_url);
388
389 if (GS3) {
390 // Load Greenstone 3 servlet configuration
391 if (isGsdlRemote){
392 servlet_config = new ServletConfiguration(Configuration.gli_user_directory_path);
393 }else{
394 servlet_config= new ServletConfiguration(gsdl3_path);
395 }
396 }
397
398 if (GS3 && Configuration.servlet_path == null) {
399 Configuration.servlet_path = servlet_config.getServletPath(Configuration.site_name);
400 }
401
402 // ensure that a directory called 'cache' exists in the GLI user directory
403 File user_cache_dir = new File(Gatherer.getGLIUserCacheDirectoryPath());
404 System.err.println("User cache dir: " + Gatherer.getGLIUserCacheDirectoryPath());
405 if (!user_cache_dir.exists() && !user_cache_dir.mkdir()) {
406 System.err.println("Warning: Unable to make directory: " + user_cache_dir);
407 }
408
409 // Check for ImageMagick
410 if (Gatherer.isGsdlRemote) {
411 DebugStream.println("Not checking for ImageMagick.");
412 }
413 else if (!(new ImageMagickTest()).found()) {
414 // Time for a warning message
415 missingImageMagick();
416 }
417
418 if (Gatherer.isGsdlRemote) {
419 DebugStream.println("Not checking for perl path/exe");
420 }
421 else {
422 // Perl path is a little different as it is perfectly ok to
423 // start the GLI without providing a perl path
424 boolean found_perl = false;
425 if (Configuration.perl_path != null) {
426 // See if the file pointed to actually exists
427 File perl_file = new File(Configuration.perl_path);
428 found_perl = perl_file.exists();
429 perl_file = null;
430 }
431 if (Configuration.perl_path == null || !found_perl) {
432 // Run test to see if we can run perl as is.
433 PerlTest perl_test = new PerlTest();
434 if (perl_test.found()) {
435 // If so replace the perl path with the system
436 // default (or null for unix).
437 Configuration.perl_path = perl_test.toString();
438 found_perl = true;
439 }
440 }
441 if (!found_perl) {
442 // Time for an error message.
443 missingPERL();
444 }
445 }
446
447 // Set the default font for all Swing components.
448 FontUIResource default_font = Configuration.getFont("general.font", true);
449 Enumeration keys = UIManager.getDefaults().keys();
450 while (keys.hasMoreElements()) {
451 Object key = keys.nextElement();
452 Object value = UIManager.get(key);
453 if (value instanceof FontUIResource) {
454 UIManager.put(key, default_font);
455 }
456 }
457
458 assoc_man = new FileAssociationManager();
459 // Create File Manager
460 f_man = new FileManager();
461 // Create Collection Manager
462 c_man = new CollectionManager();
463 // Create Recycle Bin
464 recycle_bin = new RecycleBin();
465
466 if (GS3) {
467 if (site_name==null) {
468 site_name = Configuration.site_name;
469 servlet_path = null; // need to reset this
470 }
471 if (servlet_path == null) {
472 servlet_path = Configuration.getServletPath();
473 }
474 }
475
476 open_collection_file_path = open_collection;
477 if (open_collection_file_path == null) {
478 open_collection_file_path = Configuration.getString(
479 "general.open_collection"+Configuration.gliPropertyNameSuffix(), true);
480 }
481 if (no_load || open_collection_file_path.equals("")) {
482 open_collection_file_path = null;
483 }
484 }
485 catch (Exception exception) {
486 DebugStream.printStackTrace(exception);
487 }
488
489
490 // Create GUI Manager (last) or else suffer the death of a thousand NPE's
491 g_man = new GUIManager(size);
492
493 // Get a list of the core Greenstone classifiers and plugins
494 Classifiers.loadClassifiersList(null);
495 Plugins.loadPluginsList(null);
496
497 // If using a remote Greenstone we need to download the collection configurations now
498 if (Gatherer.isGsdlRemote) {
499 if (remoteGreenstoneServer.downloadCollectionConfigurations().equals("")) {
500 // !! Something went wrong downloading the collection configurations
501 System.err.println("Error: Could not download collection configurations.");
502 if(!Gatherer.isApplet) { // don't close the browser if it is an applet!
503 System.exit(0);
504 }
505 }
506 }
507 }
508
509
510 /** Returns the correct version of the (local or remote) Greenstone server if init() has already been called. */
511 public static int serverVersionNumber() {
512 return GS3 ? 3 : 2;
513 }
514
515 /** Returns "Server: version number" if init() has already been called. */
516 public static String getServerVersionAsString() {
517 return "Server: v" + serverVersionNumber();
518 }
519
520 public void openGUI()
521 {
522 // Size and place the frame on the screen
523 Rectangle bounds = Configuration.getBounds("general.bounds", true);
524 if (bounds == null) {
525 // Choose a sensible default value
526 bounds = new Rectangle(0, 0, 640, 480);
527 }
528
529 // Ensure width and height are reasonable
530 size = bounds.getSize();
531 if (size.width < 640) {
532 size.width = 640;
533 }
534 else if (size.width > Configuration.screen_size.width && Configuration.screen_size.width > 0) {
535 size.width = Configuration.screen_size.width;
536 }
537 if (size.height < 480) {
538 size.height = 480;
539 }
540 else if (size.height > Configuration.screen_size.height && Configuration.screen_size.height > 0) {
541 size.height = Configuration.screen_size.height;
542 }
543
544 if (!g_man_built) {
545
546 g_man.display();
547
548 // 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).
549 g_man.setLocation(bounds.x, bounds.y);
550 g_man.setVisible(true);
551
552 // After the window has been made visible, check that it is in the correct place
553 // sometimes java places a window not in the correct place,
554 // but with an offset. If so, we work out what the offset is
555 // and change the desired location to take that into account
556 Point location = g_man.getLocation();
557 int x_offset = bounds.x - location.x;
558 int y_offset = bounds.y - location.y;
559 // If not, offset the window to move it into the correct location
560 if (x_offset > 0 || y_offset > 0) {
561 ///ystem.err.println("changing the location to "+(bounds.x + x_offset)+" "+ (bounds.y + y_offset));
562 g_man.setLocation(bounds.x + x_offset, bounds.y + y_offset);
563 }
564
565 // 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.
566 g_man.afterDisplay();
567 g_man_built = true;
568 }
569 else {
570 g_man.setVisible(true);
571 }
572
573 // Get a list of the core Greenstone classifiers and plugins
574 /*Classifiers.loadClassifiersList(null);
575 Plugins.loadPluginsList(null);
576
577 // If using a remote Greenstone we need to download the collection configurations now
578 if (Gatherer.isGsdlRemote) {
579 if (remoteGreenstoneServer.downloadCollectionConfigurations().equals("")) {
580 // !! Something went wrong downloading the collection configurations
581 System.err.println("Error: Could not download collection configurations.");
582 System.exit(0);
583 }
584 }*/
585
586 // If there was a collection left open last time, reopen it
587 if (open_collection_file_path == null) {
588
589 //the menu bar items, file and edit, are disabled from the moment of their creation. if there is no left-over collection from the last session, enable them; otherwise it is untill the collection finishes loading, will they be enabled in collectionManager.java
590 setMenuBarEnabled(true);
591 } else {
592
593 // If there was a collection left open last time, reopen it
594 c_man.openCollectionFromLastTime();
595 }
596 }
597
598 public static void setMenuBarEnabled(boolean enabled) {
599 g_man.menu_bar.file.setEnabled(enabled);
600 g_man.menu_bar.edit.setEnabled(enabled);
601 }
602
603 /** Exits the Gatherer after ensuring that things needing saving are saved.
604 * @see java.io.FileOutputStream
605 * @see java.io.PrintStream
606 * @see java.lang.Exception
607 * @see javax.swing.JOptionPane
608 * @see org.greenstone.gatherer.Configuration
609 * @see org.greenstone.gatherer.collection.CollectionManager
610 * @see org.greenstone.gatherer.gui.GUIManager
611 */
612 static public void exit(int new_exit_status)
613 {
614 DebugStream.println("In Gatherer.exit()...");
615 exit = true;
616 if (new_exit_status != 0) {
617 // default exit_status is already 0
618 // only remember a new exit status if it is non-trivial
619 exit_status = new_exit_status;
620 }
621
622 // Save the file associations
623 if (assoc_man != null) {
624 assoc_man.save();
625 assoc_man = null;
626 }
627
628 // Get the gui to deallocate
629 if(g_man != null) {
630 g_man.destroy();
631 g_man_built = false;
632 }
633
634 // Flush debug
635 DebugStream.closeDebugStream();
636
637 // If we started a server, we should try to stop it.
638 if (LocalLibraryServer.isRunning() == true) {
639 LocalLibraryServer.stop();
640 }
641
642 // If we're using a remote Greenstone server we need to make sure that all jobs have completed first
643 if (isGsdlRemote) {
644 remoteGreenstoneServer.exit();
645 }
646
647 // Make sure we haven't started up any processes that are still running
648 if (apps.size() == 0) {
649 // If we're running as an applet we don't actually quit (just hide the main GLI window)
650 if (!Gatherer.isApplet) {
651 // This is the end...
652 System.exit(exit_status);
653 }
654 }
655 else {
656 JOptionPane.showMessageDialog(g_man, Dictionary.get("General.Outstanding_Processes"), Dictionary.get("General.Outstanding_Processes_Title"), JOptionPane.ERROR_MESSAGE);
657 g_man.setVisible(false);
658 }
659 }
660
661 static public void exit()
662 {
663 exit(0);
664 }
665
666 /** Returns the path of the Greenstone "collect" directory. */
667 static public String getCollectDirectoryPath()
668 {
669 if (non_standard_collect_directory_path != null) {
670 return non_standard_collect_directory_path;
671 }
672
673 if (!GS3) {
674 return Configuration.gsdl_path + "collect" + File.separator;
675 }
676 else {
677 return getSitesDirectoryPath() + Configuration.site_name + File.separator + "collect" + File.separator;
678 }
679 }
680
681
682 /** Returns the path of the GLI directory. */
683 static public String getGLIDirectoryPath()
684 {
685 return gli_directory_path;
686 }
687
688
689 /** Returns the path of the GLI "metadata" directory. */
690 static public String getGLIMetadataDirectoryPath()
691 {
692 return getGLIDirectoryPath() + "metadata" + File.separator;
693 }
694
695
696 /** Returns the path of the GLI user directory. */
697 static public String getGLIUserDirectoryPath()
698 {
699 return gli_user_directory_path;
700 }
701
702
703 /** Returns the path of the GLI user "cache" directory. */
704 static public String getGLIUserCacheDirectoryPath()
705 {
706 return getGLIUserDirectoryPath() + "cache" + File.separator;
707 }
708
709
710 /** Returns the path of the GLI user "log" directory. */
711 static public String getGLIUserLogDirectoryPath()
712 {
713 return getGLIUserDirectoryPath() + "log" + File.separator;
714 }
715
716
717 static public String getSitesDirectoryPath()
718 {
719 return Configuration.gsdl3_path + "sites" + File.separator;
720 }
721
722
723 static public void setCollectDirectoryPath(String collect_directory_path)
724 {
725 non_standard_collect_directory_path = collect_directory_path;
726 if (!non_standard_collect_directory_path.endsWith(File.separator)) {
727 non_standard_collect_directory_path = non_standard_collect_directory_path + File.separator;
728 }
729 }
730
731
732 static public void setGLIDirectoryPath(String gli_directory_path_arg)
733 {
734 gli_directory_path = gli_directory_path_arg;
735 }
736
737
738 static public void setGLIUserDirectoryPath(String gli_user_directory_path_arg)
739 {
740 gli_user_directory_path = gli_user_directory_path_arg;
741
742 // Ensure the GLI user directory exists
743 File gli_user_directory = new File(gli_user_directory_path);
744 if (!gli_user_directory.exists() && !gli_user_directory.mkdirs()) {
745 System.err.println("Error: Unable to make directory: " + gli_user_directory);
746 }
747 }
748
749
750 static public void refresh(int refresh_reason)
751 {
752 if (g_man != null) {
753
754 g_man.refresh(refresh_reason, c_man.ready());
755 }
756
757 // Now is a good time to force a garbage collect
758 System.gc();
759 }
760
761
762 // used to send reload coll messages to the tomcat server
763 static public void configGS3Server(String site, String command) {
764 if (Configuration.library_url == null){
765 System.out.println("Error: you have not provide the Greenstone Library address.");
766 return;
767
768 }
769
770 try {
771 // need to add the servlet name to the exec address
772 String raw_url = Configuration.library_url.toString() + Configuration.getServletPath() + command;
773 URL url = new URL(raw_url);
774 DebugStream.println("Action: " + raw_url);
775 HttpURLConnection library_connection = (HttpURLConnection) url.openConnection();
776 int response_code = library_connection.getResponseCode();
777 if(HttpURLConnection.HTTP_OK <= response_code && response_code < HttpURLConnection.HTTP_MULT_CHOICE) {
778 DebugStream.println("200 - Complete.");
779 }
780 else {
781 DebugStream.println("404 - Failed.");
782 }
783 url = null;
784 }
785 catch(java.net.ConnectException connectException) {
786 JOptionPane.showMessageDialog(g_man, Dictionary.get("Preferences.Connection.Library_Path_Connection_Failure", Configuration.library_url.toString()), Dictionary.get("General.Warning"), JOptionPane.WARNING_MESSAGE);
787 DebugStream.println(connectException.getMessage());
788 }
789 catch (Exception exception) {
790 DebugStream.printStackTrace(exception);
791 }
792 }
793
794
795 /** Used to 'spawn' a new child application when a file is double clicked.
796 * @param file The file to open
797 * @see org.greenstone.gatherer.Gatherer.ExternalApplication
798 */
799 static public void spawnApplication(File file) {
800 String [] commands = assoc_man.getCommand(file);
801 if(commands != null) {
802 ExternalApplication app = new ExternalApplication(commands);
803 apps.add(app);
804 app.start();
805 }
806 else {
807 ///ystem.err.println("No open command available.");
808 }
809 }
810
811
812 static public void spawnApplication(String command)
813 {
814 ExternalApplication app = new ExternalApplication(command);
815 apps.add(app);
816 app.start();
817 }
818
819 static public void spawnApplication(String command, String ID)
820 {
821 ExternalApplication app = new ExternalApplication(command, ID);
822 apps.add(app);
823 app.start();
824 }
825
826 static public void terminateApplication(String ID) {
827 for(int i = 0; i < apps.size(); i++) {
828 ExternalApplication app = (ExternalApplication)apps.get(i);
829 if(app.getID() != null && app.getID().equals(ID)) {
830 app.stopExternalApplication();
831 apps.remove(app);
832 }
833 }
834 }
835
836
837 /** Used to 'spawn' a new browser application or reset an existing one when the preview button is clicked
838 * @param url The url to open the browser at
839 * @see org.greenstone.gatherer.Gatherer.BrowserApplication
840 */
841 static public void spawnBrowser(String url) {
842 String command = assoc_man.getBrowserCommand(url);
843 if (command != null) {
844 BrowserApplication app = new BrowserApplication(command, url);
845 apps.add(app);
846 app.start();
847 }
848 else {
849 ///ystem.err.println("No browser command available.");
850 }
851 }
852
853
854 /** Prints a warning message about a missing library path, which means the final collection cannot be previewed in the Gatherer.
855 */
856 static private void missingEXEC() {
857 WarningDialog dialog;
858 String configPropertyName = "general.library_url"+Configuration.gliPropertyNameSuffix();
859
860 if (GS3) {
861 // Warning dialog with no cancel button and no "turn off warning" checkbox
862 dialog = new WarningDialog("warning.MissingEXEC", Dictionary.get("MissingEXEC_GS3.Title"), Dictionary.get("MissingEXEC_GS3.Message"), configPropertyName, false, false);
863 } else { // local case
864 dialog = new WarningDialog("warning.MissingEXEC", Dictionary.get("MissingEXEC.Title"), Dictionary.get("MissingEXEC.Message"), configPropertyName, false);
865 }
866
867 JTextField field = new URLField.Text(Configuration.getColor("coloring.editable_foreground", false), Configuration.getColor("coloring.editable_background", false));
868
869 // Set the default library URL to the tomcat server and port number
870 // specified in the build.properties located in the gsdl3_src_path
871 if (GS3) {
872 String host = "localhost";
873 String port = "8080";
874
875 File buildPropsFile = new File(Configuration.gsdl3_src_path + File.separator + "build.properties");
876 if(buildPropsFile.exists()) {
877 Properties props = new Properties();
878 try{
879 props.load(new FileInputStream(buildPropsFile));
880 host = props.getProperty("tomcat.server", host);
881 port = props.getProperty("tomcat.port", port);
882 }catch(Exception e){
883 DebugStream.println("Could not load build.properties file");
884 System.err.println("Could not load build.properties file");
885 }
886 props = null;
887 }
888 String defaultURL = "http://"+host+":"+port+"/"+"greenstone3/library";
889 field.setText(defaultURL);
890 field.selectAll();
891 }
892 dialog.setValueField(field);
893 dialog.display();
894 dialog.dispose();
895 dialog = null;
896
897 String library_url_string = Configuration.getString(configPropertyName, true);
898 if (!library_url_string.equals("")) {
899 try {
900 // WarningDialog does not allow invalid URLs, so the following is ignored:
901 // make sure the URL the user provided contains the http:// prefix
902 // and then save the corrected URL
903 if(!library_url_string.startsWith("http://")
904 && !library_url_string.startsWith("https://")) {
905 library_url_string = "http://"+library_url_string;
906 Configuration.setString(configPropertyName, true, configPropertyName);
907 }
908 Configuration.library_url = new URL(library_url_string);
909 }
910 catch (MalformedURLException exception) {
911 DebugStream.printStackTrace(exception);
912 }
913 }
914 }
915
916
917
918 /** Prints a warning message about a missing library path, which means the final collection cannot be previewed in the Gatherer.
919 */
920 static private void popupFedoraInfo() {
921
922 FedoraLogin dialog = new FedoraLogin("Fedora Login", false);
923
924 if (Configuration.library_url == null) {
925
926 String library_url_string = dialog.getLibraryURL();
927 if (!library_url_string.equals("")) {
928 try {
929 Configuration.library_url = new URL(library_url_string);
930 }
931 catch (MalformedURLException exception) {
932 DebugStream.printStackTrace(exception);
933 }
934 }
935 }
936
937 boolean showLogin = true;
938 do {
939 if(!dialog.loginRequested()) { // user pressed cancel to exit the FedoraLogin dialog
940 System.exit(0);
941 } else {
942 showLogin = dialog.loginRequested();
943 String hostname = dialog.getHostname();
944 String port = dialog.getPort();
945 String username = dialog.getUsername();
946 String password = dialog.getPassword();
947 String protocol = dialog.getProtocol();
948
949 Configuration.fedora_info.setHostname(hostname);
950 Configuration.fedora_info.setPort(port);
951 Configuration.fedora_info.setUsername(username);
952 Configuration.fedora_info.setPassword(password);
953 Configuration.fedora_info.setProtocol(protocol);
954
955 String ping_url_str = protocol + "://" + hostname + ":" + port + "/fedora";
956 String login_str = username + ":" + password;
957
958 String login_encoding = Base64.encodeBytes(login_str.getBytes());
959
960 try {
961 URL ping_url = new URL(ping_url_str);
962 URLConnection uc = ping_url.openConnection();
963 uc.setRequestProperty ("Authorization", "Basic " + login_encoding);
964 // Attempt to access some content ...
965 InputStream content = (InputStream)uc.getInputStream();
966
967 // if no exception occurred in the above, we would have come here:
968 showLogin = false;
969 dialog.dispose();
970 }
971 catch (Exception exception) {
972 // TODO: move into dictionary
973 String[] errorMessage = {"Failed to connect to the Fedora server.", "It might not be running, or",
974 "incorrect username and/or password."};
975 dialog.setErrorMessage(errorMessage);
976 //DebugStream.printStackTrace(exception);
977 // exception occurred, show the dialog again (do this after printing to
978 // debugStream, else the above does not get done for some reason).
979 dialog.setVisible(true);
980 }
981 }
982 } while(showLogin);
983
984 dialog = null; // no more need of the dialog
985
986 // Now we are connected.
987 }
988
989
990
991 static private void requestGLIServerURL()
992 {
993 WarningDialog dialog;
994 String[] defaultURLs = {
995 "http://localhost:8080/greenstone3/cgi-bin/gliserver.pl",
996 "http://localhost:8080/gsdl/cgi-bin/gliserver.pl"
997 };
998
999 // Warning dialog with no cancel button and no "turn off warning" checkbox
1000 // (since user-input of the gliserver script is mandatory)
1001 dialog = new WarningDialog("warning.MissingGLIServer", Dictionary.get("MissingGLIServer.Title"), Dictionary.get("MissingGLIServer.Message"), "general.gliserver_url", false, false);
1002
1003 dialog.setValueField(new URLField.DropDown(Configuration.getColor("coloring.editable_foreground", false),
1004 Configuration.getColor("coloring.editable_background", false),
1005 defaultURLs, "general.gliserver_url",
1006 "general.open_collection"+Configuration.gliPropertyNameSuffix(),
1007 "gliserver.pl"));
1008
1009 if (Gatherer.default_gliserver_url!=null){
1010 dialog.setValueField(Gatherer.default_gliserver_url.toString());
1011 }
1012
1013 // A WarningDialog cannot always be made to respond (let alone to exit the program) on close. We
1014 // handle the response of this particular WarningDialog here: a URL for gliserver.pl is a crucial
1015 // piece of user-provided data. Therefore, if no URL was entered for gliserver.pl, it'll exit safely.
1016 dialog.addWindowListener(new WindowAdapter() {
1017 public void windowClosing(WindowEvent e) {
1018 Gatherer.exit();
1019 }
1020 });
1021
1022 dialog.display();
1023 dialog.dispose();
1024 dialog = null;
1025
1026
1027 String gliserver_url_string = Configuration.getString("general.gliserver_url", true);
1028 if (!gliserver_url_string.equals("")) {
1029 try {
1030 Configuration.gliserver_url = new URL(gliserver_url_string);
1031 Configuration.setString("general.gliserver_url", true, gliserver_url_string);
1032 }
1033 catch (MalformedURLException exception) {
1034 DebugStream.printStackTrace(exception);
1035 }
1036 }
1037 }
1038
1039
1040 /** Prints a warning message about a missing GSDL path, which although not fatal pretty much ensures nothing will work properly in the GLI.
1041 */
1042 static private void missingGSDL() {
1043 WarningDialog dialog = new WarningDialog("warning.MissingGSDL", Dictionary.get("MissingGSDL.Title"), Dictionary.get("MissingGSDL.Message"), null, false);
1044 dialog.display();
1045 dialog.dispose();
1046 dialog = null;
1047 }
1048
1049 /** Prints a warning message about missing a valid ImageMagick path, which although not fatal means building image collections won't work */
1050 static private void missingImageMagick() {
1051 WarningDialog dialog = new WarningDialog("warning.MissingImageMagick", Dictionary.get("MissingImageMagick.Title"), Dictionary.get("MissingImageMagick.Message"), null, false);
1052 dialog.display();
1053 dialog.dispose();
1054 dialog = null;
1055 }
1056
1057 /** Prints a warning message about missing a valid PERL path, which although not fatal pretty much ensures no collection creation/building will work properly in the GLI. */
1058 static private void missingPERL() {
1059 WarningDialog dialog = new WarningDialog("warning.MissingPERL", Dictionary.get("MissingPERL.Title"), Dictionary.get("MissingPERL.Message"), null, false);
1060 dialog.display();
1061 dialog.dispose();
1062 dialog = null;
1063 }
1064
1065
1066 /** Sets up the proxy connection by setting JVM Environment flags and creating a new Authenticator.
1067 * @see java.lang.Exception
1068 * @see java.lang.System
1069 * @see java.net.Authenticator
1070 * @see org.greenstone.gatherer.Configuration
1071 * @see org.greenstone.gatherer.GAuthenticator
1072 */
1073 static public void setProxy() {
1074 try {// Can throw several exceptions
1075 if(Configuration.get("general.use_proxy", true)) {
1076 System.setProperty("http.proxyType", "4");
1077 System.setProperty("http.proxyHost", Configuration.getString("general.proxy_host", true));
1078 System.setProperty("http.proxyPort", Configuration.getString("general.proxy_port", true));
1079 System.setProperty("http.proxySet", "true");
1080 } else {
1081 System.setProperty("http.proxyHost", "");
1082 System.setProperty("http.proxyPort", "");
1083 System.setProperty("http.proxySet", "false");
1084 }
1085 } catch (Exception error) {
1086 DebugStream.println("Error in Gatherer.initProxy(): " + error);
1087 DebugStream.printStackTrace(error);
1088 }
1089 }
1090
1091
1092 /** 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. */
1093 static private class ExternalApplication
1094 extends Thread {
1095 private Process process = null;
1096 /** The initial command string given to this sub-process. */
1097 private String command = null;
1098 private String[] commands = null;
1099
1100 private String ID = null;
1101
1102 /** Constructor.
1103 * @param command The initial command <strong>String</strong>.
1104 */
1105 public ExternalApplication(String command) {
1106 this.command = command;
1107 }
1108
1109 public ExternalApplication(String[] commands) {
1110 this.commands = commands;
1111 }
1112
1113 public ExternalApplication(String command, String ID) {
1114 this.command = command;
1115 this.ID = ID;
1116 }
1117
1118 public String getID() {
1119 return ID;
1120 }
1121
1122 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
1123 * @see java.lang.Exception
1124 * @see java.lang.Process
1125 * @see java.lang.Runtime
1126 * @see java.lang.System
1127 * @see java.util.Vector
1128 */
1129 public void run() {
1130 // Call an external process using the args.
1131 try {
1132 if(commands != null) {
1133 StringBuffer whole_command = new StringBuffer();
1134 for(int i = 0; i < commands.length; i++) {
1135 whole_command.append(commands[i]);
1136 whole_command.append(" ");
1137 }
1138 DebugStream.println("Running " + whole_command.toString());
1139 Runtime rt = Runtime.getRuntime();
1140 process = rt.exec(commands);
1141 process.waitFor();
1142 }
1143 else {
1144 DebugStream.println("Running " + command);
1145 Runtime rt = Runtime.getRuntime();
1146 process = rt.exec(command);
1147 process.waitFor();
1148 }
1149 }
1150 catch (Exception exception) {
1151 DebugStream.printStackTrace(exception);
1152 }
1153 // Remove ourself from Gatherer list of threads.
1154 apps.remove(this);
1155 // Call exit if we were the last outstanding child process thread.
1156 if (apps.size() == 0 && exit == true) {
1157 // In my opinion (DB) there is no need to exit here,
1158 // the 'run' method ending naturally brings this
1159 // thread to an end. In fact it is potentially
1160 // dangerous to exit here, as the main thread in the
1161 // Gatherer class may be stopped prematurely. As it so
1162 // happens the point at which the ExternalApplication thread
1163 // is asked to stop (Back in the main Gatherer thread) is after
1164 // various configuration files have been saved.
1165 //
1166 // A similar argument holds for BrowserApplication thread below.
1167 System.exit(exit_status);
1168 }
1169 }
1170 public void stopExternalApplication() {
1171 if(process != null) {
1172 process.destroy();
1173 }
1174 }
1175 }
1176 /** 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. */
1177 static private class BrowserApplication
1178 extends Thread {
1179 private Process process = null;
1180 /** The initial command string given to this sub-process. */
1181 private String command = null;
1182 private String url = null;
1183 private String[] commands = null;
1184
1185 public BrowserApplication(String command, String url) {
1186 StringTokenizer st = new StringTokenizer(command);
1187 int num_tokens = st.countTokens();
1188 this.commands = new String [num_tokens];
1189 int i=0;
1190 while (st.hasMoreTokens()) {
1191 commands[i] = st.nextToken();
1192 i++;
1193 }
1194 //this.commands = commands;
1195 this.url = url;
1196 }
1197 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
1198 * @see java.lang.Exception
1199 * @see java.lang.Process
1200 * @see java.lang.Runtime
1201 * @see java.lang.System
1202 * @see java.util.Vector
1203 */
1204 public void run() {
1205 // Call an external process using the args.
1206 if(commands == null) {
1207 apps.remove(this);
1208 return;
1209 }
1210 try {
1211 String prog_name = commands[0];
1212 String lower_name = prog_name.toLowerCase();
1213 if (lower_name.indexOf("mozilla") != -1 || lower_name.indexOf("netscape") != -1) {
1214 DebugStream.println("found mozilla or netscape, trying remote it");
1215 // mozilla and netscape, try using a remote command to get things in the same window
1216 String [] new_commands = new String[] {prog_name, "-raise", "-remote", "openURL("+url+",new-tab)"};
1217 printArray(new_commands);
1218
1219 Runtime rt = Runtime.getRuntime();
1220 process = rt.exec(new_commands);
1221 int exitCode = process.waitFor();
1222 if (exitCode != 0) { // if Netscape or mozilla was not open
1223 DebugStream.println("couldn't do remote, trying original command");
1224 printArray(commands);
1225 process = rt.exec(commands); // try the original command
1226 }
1227 } else {
1228 // just run what we have been given
1229 StringBuffer whole_command = new StringBuffer();
1230 for(int i = 0; i < commands.length; i++) {
1231 whole_command.append(commands[i]);
1232 whole_command.append(" ");
1233 }
1234 DebugStream.println("Running " + whole_command.toString());
1235 Runtime rt = Runtime.getRuntime();
1236 process = rt.exec(commands);
1237 process.waitFor();
1238 }
1239 }
1240
1241 catch (Exception exception) {
1242 DebugStream.printStackTrace(exception);
1243 }
1244 // Remove ourself from Gatherer list of threads.
1245 apps.remove(this);
1246 // Call exit if we were the last outstanding child process thread.
1247 if (apps.size() == 0 && exit == true) {
1248 System.exit(exit_status);
1249 }
1250 }
1251 public void printArray(String [] array) {
1252 for(int i = 0; i < array.length; i++) {
1253 DebugStream.print(array[i]+" ");
1254 System.err.println(array[i]+" ");
1255 }
1256 }
1257 public void stopBrowserApplication() {
1258 if(process != null) {
1259 process.destroy();
1260 }
1261 }
1262 }
1263
1264
1265 private class ImageMagickTest
1266 {
1267 public boolean found()
1268 {
1269 try {
1270 String[] command = new String[2];
1271 command[0] = (Utility.isWindows() ? "identify.exe" : "identify");
1272 command[1] = "-version";
1273 Process image_magick_process = Runtime.getRuntime().exec(command);
1274 image_magick_process.waitFor();
1275
1276 //new way of detection of ImageMagick
1277 InputStreamReader isr = new InputStreamReader(image_magick_process.getInputStream());
1278
1279 BufferedReader br = new BufferedReader(isr);
1280 // Capture the standard output stream and seach for two particular occurances: Version and ImageMagick.
1281
1282 String line = br.readLine();
1283 if (line == null) {
1284 return false;
1285 }
1286 String lc_line = line.toLowerCase();
1287 if (lc_line.indexOf("version") != -1 || lc_line.indexOf("imagemagick") != -1) {
1288 return true;
1289 } else {
1290 return false;
1291 }
1292
1293 //return (image_magick_process.exitValue() == 0);
1294 }
1295 catch (IOException exception) {
1296 return false;
1297 }
1298 catch (InterruptedException exception) {
1299 return false;
1300 }
1301 }
1302 }
1303
1304
1305 private class PerlTest
1306 {
1307 private String[] command = new String[2];
1308
1309 public PerlTest()
1310 {
1311 command[0] = (Utility.isWindows() ? Utility.PERL_EXECUTABLE_WINDOWS : Utility.PERL_EXECUTABLE_UNIX);
1312 command[1] = "-version";
1313 }
1314
1315 public boolean found()
1316 {
1317 try {
1318 Process perl_process = Runtime.getRuntime().exec(command);
1319 perl_process.waitFor();
1320 return (perl_process.exitValue() == 0);
1321 }
1322 catch (Exception exception) {
1323 return false;
1324 }
1325 }
1326
1327 public String toString() {
1328 return command[0];
1329 }
1330 }
1331}
Note: See TracBrowser for help on using the repository browser.