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

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

Instead of using sun's BASE64Encoder on fedora login (which throws warnings), uses the Base64 class in Greenstone's feedback package.

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