source: gli/branches/rtl-gli/src/org/greenstone/gatherer/Gatherer.java@ 18363

Last change on this file since 18363 was 18363, checked in by kjdon, 15 years ago

updated the rtl-gli branch with files from trunk. Result of a merge 14807:18318

  • Property svn:keywords set to Author Date Id Revision
File size: 45.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.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 // Warning dialog with no cancel button and no "turn off warning" checkbox
824 dialog = new WarningDialog("warning.MissingEXEC", Dictionary.get("MissingEXEC_GS3.Title"), Dictionary.get("MissingEXEC_GS3.Message"), configPropertyName, false, false);
825 } else { // local case
826 dialog = new WarningDialog("warning.MissingEXEC", Dictionary.get("MissingEXEC.Title"), Dictionary.get("MissingEXEC.Message"), configPropertyName, false);
827 }
828
829 JTextField field = new URLField.Text(Configuration.getColor("coloring.editable_foreground", false), Configuration.getColor("coloring.editable_background", false));
830
831 // Set the default library URL to the tomcat server and port number
832 // specified in the build.properties located in the gsdl3_src_path
833 if (GS3) {
834 String host = "localhost";
835 String port = "8080";
836
837 File buildPropsFile = new File(Configuration.gsdl3_src_path + File.separator + "build.properties");
838 if(buildPropsFile.exists()) {
839 Properties props = new Properties();
840 try{
841 props.load(new FileInputStream(buildPropsFile));
842 host = props.getProperty("tomcat.server", host);
843 port = props.getProperty("tomcat.port", port);
844 }catch(Exception e){
845 DebugStream.println("Could not load build.properties file");
846 System.err.println("Could not load build.properties file");
847 }
848 props = null;
849 }
850 String defaultURL = "http://"+host+":"+port+"/"+"greenstone3/library";
851 field.setText(defaultURL);
852 field.selectAll();
853 }
854 dialog.setValueField(field);
855 dialog.display();
856 dialog.dispose();
857 dialog = null;
858
859 String library_url_string = Configuration.getString(configPropertyName, true);
860 if (!library_url_string.equals("")) {
861 try {
862 // WarningDialog does not allow invalid URLs, so the following is ignored:
863 // make sure the URL the user provided contains the http:// prefix
864 // and then save the corrected URL
865 if(!library_url_string.startsWith("http://")
866 && !library_url_string.startsWith("https://")) {
867 library_url_string = "http://"+library_url_string;
868 Configuration.setString(configPropertyName, true, configPropertyName);
869 }
870 Configuration.library_url = new URL(library_url_string);
871 }
872 catch (MalformedURLException exception) {
873 DebugStream.printStackTrace(exception);
874 }
875 }
876 }
877
878
879
880 /** Prints a warning message about a missing library path, which means the final collection cannot be previewed in the Gatherer.
881 */
882 static private void popupFedoraInfo() {
883
884 FedoraLogin dialog = new FedoraLogin("Fedora Login", false);
885
886 if (Configuration.library_url == null) {
887
888 String library_url_string = dialog.getLibraryURL();
889 if (!library_url_string.equals("")) {
890 try {
891 Configuration.library_url = new URL(library_url_string);
892 }
893 catch (MalformedURLException exception) {
894 DebugStream.printStackTrace(exception);
895 }
896 }
897 }
898
899 boolean showLogin = true;
900 do {
901 if(!dialog.loginRequested()) { // user pressed cancel to exit the FedoraLogin dialog
902 System.exit(0);
903 } else {
904 showLogin = dialog.loginRequested();
905 String hostname = dialog.getHostname();
906 String port = dialog.getPort();
907 String username = dialog.getUsername();
908 String password = dialog.getPassword();
909 String protocol = dialog.getProtocol();
910
911 Configuration.fedora_info.setHostname(hostname);
912 Configuration.fedora_info.setPort(port);
913 Configuration.fedora_info.setUsername(username);
914 Configuration.fedora_info.setPassword(password);
915 Configuration.fedora_info.setProtocol(protocol);
916
917 String ping_url_str = protocol + "://" + hostname + ":" + port + "/fedora";
918 String login_str = username + ":" + password;
919
920 String login_encoding = new sun.misc.BASE64Encoder().encode(login_str.getBytes());
921
922 try {
923 URL ping_url = new URL(ping_url_str);
924 URLConnection uc = ping_url.openConnection();
925 uc.setRequestProperty ("Authorization", "Basic " + login_encoding);
926 // Attempt to access some content ...
927 InputStream content = (InputStream)uc.getInputStream();
928
929 // if no exception occurred in the above, we would have come here:
930 showLogin = false;
931 dialog.dispose();
932 }
933 catch (Exception exception) {
934 // TODO: move into dictionary
935 String[] errorMessage = {"Failed to connect to the Fedora server.", "It might not be running, or",
936 "incorrect username and/or password."};
937 dialog.setErrorMessage(errorMessage);
938 //DebugStream.printStackTrace(exception);
939 // exception occurred, show the dialog again (do this after printing to
940 // debugStream, else the above does not get done for some reason).
941 dialog.setVisible(true);
942 }
943 }
944 } while(showLogin);
945
946 dialog = null; // no more need of the dialog
947
948 // Now we are connected.
949 }
950
951
952
953 static private void requestGLIServerURL()
954 {
955 WarningDialog dialog;
956 String[] defaultURLs = {
957 "http://localhost:8080/greenstone3/cgi-bin/gliserver.pl",
958 "http://localhost:8080/gsdl/cgi-bin/gliserver.pl"
959 };
960
961 // Warning dialog with no cancel button and no "turn off warning" checkbox
962 // (since user-input of the gliserver script is mandatory)
963 dialog = new WarningDialog("warning.MissingGLIServer", Dictionary.get("MissingGLIServer.Title"), Dictionary.get("MissingGLIServer.Message"), "general.gliserver_url", false, false);
964
965 dialog.setValueField(new URLField.DropDown(Configuration.getColor("coloring.editable_foreground", false),
966 Configuration.getColor("coloring.editable_background", false),
967 defaultURLs, "general.gliserver_url",
968 "general.open_collection"+Configuration.gliPropertyNameSuffix(),
969 "gliserver.pl"));
970
971 if (Gatherer.default_gliserver_url!=null){
972 dialog.setValueField(Gatherer.default_gliserver_url.toString());
973 }
974
975 // A WarningDialog cannot always be made to respond (let alone to exit the program) on close. We
976 // handle the response of this particular WarningDialog here: a URL for gliserver.pl is a crucial
977 // piece of user-provided data. Therefore, if no URL was entered for gliserver.pl, it'll exit safely.
978 dialog.addWindowListener(new WindowAdapter() {
979 public void windowClosing(WindowEvent e) {
980 Gatherer.exit();
981 }
982 });
983
984 dialog.display();
985 dialog.dispose();
986 dialog = null;
987
988
989 String gliserver_url_string = Configuration.getString("general.gliserver_url", true);
990 if (!gliserver_url_string.equals("")) {
991 try {
992 Configuration.gliserver_url = new URL(gliserver_url_string);
993 Configuration.setString("general.gliserver_url", true, gliserver_url_string);
994 }
995 catch (MalformedURLException exception) {
996 DebugStream.printStackTrace(exception);
997 }
998 }
999 }
1000
1001
1002 /** Prints a warning message about a missing GSDL path, which although not fatal pretty much ensures nothing will work properly in the GLI.
1003 */
1004 static private void missingGSDL() {
1005 WarningDialog dialog = new WarningDialog("warning.MissingGSDL", Dictionary.get("MissingGSDL.Title"), Dictionary.get("MissingGSDL.Message"), null, false);
1006 dialog.display();
1007 dialog.dispose();
1008 dialog = null;
1009 }
1010
1011 /** Prints a warning message about missing a valid ImageMagick path, which although not fatal means building image collections won't work */
1012 static private void missingImageMagick() {
1013 WarningDialog dialog = new WarningDialog("warning.MissingImageMagick", Dictionary.get("MissingImageMagick.Title"), Dictionary.get("MissingImageMagick.Message"), null, false);
1014 dialog.display();
1015 dialog.dispose();
1016 dialog = null;
1017 }
1018
1019 /** 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. */
1020 static private void missingPERL() {
1021 WarningDialog dialog = new WarningDialog("warning.MissingPERL", Dictionary.get("MissingPERL.Title"), Dictionary.get("MissingPERL.Message"), null, false);
1022 dialog.display();
1023 dialog.dispose();
1024 dialog = null;
1025 }
1026
1027
1028 /** Sets up the proxy connection by setting JVM Environment flags and creating a new Authenticator.
1029 * @see java.lang.Exception
1030 * @see java.lang.System
1031 * @see java.net.Authenticator
1032 * @see org.greenstone.gatherer.Configuration
1033 * @see org.greenstone.gatherer.GAuthenticator
1034 */
1035 static public void setProxy() {
1036 try {// Can throw several exceptions
1037 if(Configuration.get("general.use_proxy", true)) {
1038 System.setProperty("http.proxyType", "4");
1039 System.setProperty("http.proxyHost", Configuration.getString("general.proxy_host", true));
1040 System.setProperty("http.proxyPort", Configuration.getString("general.proxy_port", true));
1041 System.setProperty("http.proxySet", "true");
1042 } else {
1043 System.setProperty("http.proxyHost", "");
1044 System.setProperty("http.proxyPort", "");
1045 System.setProperty("http.proxySet", "false");
1046 }
1047 } catch (Exception error) {
1048 DebugStream.println("Error in Gatherer.initProxy(): " + error);
1049 DebugStream.printStackTrace(error);
1050 }
1051 }
1052
1053
1054 /** 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. */
1055 static private class ExternalApplication
1056 extends Thread {
1057 private Process process = null;
1058 /** The initial command string given to this sub-process. */
1059 private String command = null;
1060 private String[] commands = null;
1061 /** Constructor.
1062 * @param command The initial command <strong>String</strong>.
1063 */
1064 public ExternalApplication(String command) {
1065 this.command = command;
1066 }
1067
1068 public ExternalApplication(String[] commands) {
1069 this.commands = commands;
1070 }
1071 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
1072 * @see java.lang.Exception
1073 * @see java.lang.Process
1074 * @see java.lang.Runtime
1075 * @see java.lang.System
1076 * @see java.util.Vector
1077 */
1078 public void run() {
1079 // Call an external process using the args.
1080 try {
1081 if(commands != null) {
1082 StringBuffer whole_command = new StringBuffer();
1083 for(int i = 0; i < commands.length; i++) {
1084 whole_command.append(commands[i]);
1085 whole_command.append(" ");
1086 }
1087 DebugStream.println("Running " + whole_command.toString());
1088 Runtime rt = Runtime.getRuntime();
1089 process = rt.exec(commands);
1090 process.waitFor();
1091 }
1092 else {
1093 DebugStream.println("Running " + command);
1094 Runtime rt = Runtime.getRuntime();
1095 process = rt.exec(command);
1096 process.waitFor();
1097 }
1098 }
1099 catch (Exception exception) {
1100 DebugStream.printStackTrace(exception);
1101 }
1102 // Remove ourself from Gatherer list of threads.
1103 apps.remove(this);
1104 // Call exit if we were the last outstanding child process thread.
1105 if (apps.size() == 0 && exit == true) {
1106 // In my opinion (DB) there is no need to exit here,
1107 // the 'run' method ending naturally brings this
1108 // thread to an end. In fact it is potentially
1109 // dangerous to exit here, as the main thread in the
1110 // Gatherer class may be stopped prematurely. As it so
1111 // happens the point at which the ExternalApplication thread
1112 // is asked to stop (Back in the main Gatherer thread) is after
1113 // various configuration files have been saved.
1114 //
1115 // A similar argument holds for BrowserApplication thread below.
1116 System.exit(exit_status);
1117 }
1118 }
1119 public void stopExternalApplication() {
1120 if(process != null) {
1121 process.destroy();
1122 }
1123 }
1124 }
1125 /** 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. */
1126 static private class BrowserApplication
1127 extends Thread {
1128 private Process process = null;
1129 /** The initial command string given to this sub-process. */
1130 private String command = null;
1131 private String url = null;
1132 private String[] commands = null;
1133
1134 public BrowserApplication(String command, String url) {
1135 StringTokenizer st = new StringTokenizer(command);
1136 int num_tokens = st.countTokens();
1137 this.commands = new String [num_tokens];
1138 int i=0;
1139 while (st.hasMoreTokens()) {
1140 commands[i] = st.nextToken();
1141 i++;
1142 }
1143 //this.commands = commands;
1144 this.url = url;
1145 }
1146 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
1147 * @see java.lang.Exception
1148 * @see java.lang.Process
1149 * @see java.lang.Runtime
1150 * @see java.lang.System
1151 * @see java.util.Vector
1152 */
1153 public void run() {
1154 // Call an external process using the args.
1155 if(commands == null) {
1156 apps.remove(this);
1157 return;
1158 }
1159 try {
1160 String prog_name = commands[0];
1161 String lower_name = prog_name.toLowerCase();
1162 if (lower_name.indexOf("mozilla") != -1 || lower_name.indexOf("netscape") != -1) {
1163 DebugStream.println("found mozilla or netscape, trying remote it");
1164 // mozilla and netscape, try using a remote command to get things in the same window
1165 String [] new_commands = new String[] {prog_name, "-raise", "-remote", "openURL("+url+",new-tab)"};
1166 printArray(new_commands);
1167
1168 Runtime rt = Runtime.getRuntime();
1169 process = rt.exec(new_commands);
1170 int exitCode = process.waitFor();
1171 if (exitCode != 0) { // if Netscape or mozilla was not open
1172 DebugStream.println("couldn't do remote, trying original command");
1173 printArray(commands);
1174 process = rt.exec(commands); // try the original command
1175 }
1176 } else {
1177 // just run what we have been given
1178 StringBuffer whole_command = new StringBuffer();
1179 for(int i = 0; i < commands.length; i++) {
1180 whole_command.append(commands[i]);
1181 whole_command.append(" ");
1182 }
1183 DebugStream.println("Running " + whole_command.toString());
1184 Runtime rt = Runtime.getRuntime();
1185 process = rt.exec(commands);
1186 process.waitFor();
1187 }
1188 }
1189
1190 catch (Exception exception) {
1191 DebugStream.printStackTrace(exception);
1192 }
1193 // Remove ourself from Gatherer list of threads.
1194 apps.remove(this);
1195 // Call exit if we were the last outstanding child process thread.
1196 if (apps.size() == 0 && exit == true) {
1197 System.exit(exit_status);
1198 }
1199 }
1200 public void printArray(String [] array) {
1201 for(int i = 0; i < array.length; i++) {
1202 DebugStream.print(array[i]+" ");
1203 System.err.println(array[i]+" ");
1204 }
1205 }
1206 public void stopBrowserApplication() {
1207 if(process != null) {
1208 process.destroy();
1209 }
1210 }
1211 }
1212
1213
1214 private class ImageMagickTest
1215 {
1216 public boolean found()
1217 {
1218 try {
1219 String[] command = new String[2];
1220 command[0] = (Utility.isWindows() ? "identify.exe" : "identify");
1221 command[1] = "-version";
1222 Process image_magick_process = Runtime.getRuntime().exec(command);
1223 image_magick_process.waitFor();
1224
1225 //new way of detection of ImageMagick
1226 InputStreamReader isr = new InputStreamReader(image_magick_process.getInputStream());
1227
1228 BufferedReader br = new BufferedReader(isr);
1229 // Capture the standard output stream and seach for two particular occurances: Version and ImageMagick.
1230
1231 String line = br.readLine();
1232 if (line == null) {
1233 return false;
1234 }
1235 String lc_line = line.toLowerCase();
1236 if (lc_line.indexOf("version") != -1 || lc_line.indexOf("imagemagick") != -1) {
1237 return true;
1238 } else {
1239 return false;
1240 }
1241
1242 //return (image_magick_process.exitValue() == 0);
1243 }
1244 catch (IOException exception) {
1245 return false;
1246 }
1247 catch (InterruptedException exception) {
1248 return false;
1249 }
1250 }
1251 }
1252
1253
1254 private class PerlTest
1255 {
1256 private String[] command = new String[2];
1257
1258 public PerlTest()
1259 {
1260 command[0] = (Utility.isWindows() ? Utility.PERL_EXECUTABLE_WINDOWS : Utility.PERL_EXECUTABLE_UNIX);
1261 command[1] = "-version";
1262 }
1263
1264 public boolean found()
1265 {
1266 try {
1267 Process perl_process = Runtime.getRuntime().exec(command);
1268 perl_process.waitFor();
1269 return (perl_process.exitValue() == 0);
1270 }
1271 catch (Exception exception) {
1272 return false;
1273 }
1274 }
1275
1276 public String toString() {
1277 return command[0];
1278 }
1279 }
1280}
Note: See TracBrowser for help on using the repository browser.