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

Last change on this file since 17628 was 17628, checked in by ak19, 16 years ago

Minor change to stop the GLIApplet from closing the browser

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