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

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

Updated several files such that the Server2 code in server.jar can interact with GLI code so that the local GS2 server for Linux works the same way as the GS2 Local Library Server on windows.

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