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

Last change on this file since 36229 was 36229, checked in by kjdon, 2 years ago

I find it annoying when switching between gs2 and 3 that the gli config file (in .gli/config.xml) gets changed back and forth. In the same way we now have configRemote.xml for when we are running remotely, now locally, config.xml gets saved as config2.xml or config3.xml. they use the same config.xml template though. added final static strings for the filenames, and always use these, so only Configuration now contains the actual text strings. made Configuration.CONFIG_XML and Configuration.TEMPLATE_CONFIG_XML lowercase as they are not final Strings, they get changed by Gatherer.

  • Property svn:keywords set to Author Date Id Revision
File size: 74.8 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.ProtocolPortProperties;
54import org.greenstone.gatherer.greenstone3.ServletConfiguration;
55import org.greenstone.gatherer.gui.GUIManager;
56import org.greenstone.gatherer.gui.URLField;
57import org.greenstone.gatherer.gui.WarningDialog;
58import org.greenstone.gatherer.gui.FedoraLogin;
59import org.greenstone.gatherer.gui.TestingPreparation;
60import org.greenstone.gatherer.metadata.FilenameEncoding;
61import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
62import org.greenstone.gatherer.util.GS3ServerThread;
63import org.greenstone.gatherer.util.JarTools;
64import org.greenstone.gatherer.util.SafeProcess;
65import org.greenstone.gatherer.util.StaticStrings;
66import org.greenstone.gatherer.util.Utility;
67
68
69/** Containing the top-level "core" for the Gatherer, this class is the
70* common core for the GLI application and applet. It first parses the
71* command line arguments, preparing to update the configuration as
72* required. Next it loads several important support classes such as the
73* Configuration and Dictionary. Finally it creates the other important
74* managers and sends them on their way.
75* @author John Thompson, Greenstone Digital Library, University of Waikato
76* @version 2.3
77*/
78public class Gatherer
79{
80 /** The name of the GLI. */
81 static final public String PROGRAM_NAME = "Greenstone Librarian Interface";
82 /** The current version of the GLI.
83 * Note: the gs3-release-maker relies on this variable being declared
84 * in a line which matches this java regex:
85 * ^(.*)String\s*PROGRAM_VERSION\s*=\s*"trunk";
86 * If change the declaration and it no longer matches the regex, please
87 * change the regex in the gs3-release-maker code and in this message
88 */
89
90 static final public String PROGRAM_VERSION = "trunk";
91
92 static private Dimension size = new Dimension(800, 540);
93 static public RemoteGreenstoneServer remoteGreenstoneServer = null;
94
95 /** Has the exit flag been set? */
96 static final public int EXIT_THEN_RESTART= 2;
97 static public boolean exit = false;
98 static public int exit_status = 0;
99
100 static private String gli_directory_path = null;
101 static private String gli_user_directory_path = null;
102
103 static public String client_operating_system = null;
104
105 /** All of the external applications that must exit before we close the Gatherer. */
106 static private Vector apps = new Vector();
107 static private String non_standard_collect_directory_path = null;
108 static public String open_collection_file_path = null;
109 static public String gsdlsite_collecthome = "";
110 /** A public reference to the FileAssociationManager. */
111 static public FileAssociationManager assoc_man;
112 /** A public reference to the CollectionManager. */
113 static public CollectionManager c_man;
114 /** A public reference to the RecycleBin. */
115 static public RecycleBin recycle_bin;
116 /** a reference to the Servlet Configuration is GS3 */
117 static public ServletConfiguration servlet_config;
118 /** A public reference to the FileManager. */
119 static public FileManager f_man;
120 /** A public reference to the GUIManager. */
121 static public GUIManager g_man = null;
122 static private boolean g_man_built = false;
123
124 /** We are using the GLI for GS3 */
125 static public boolean GS3 = false;
126
127 static public boolean isApplet = false;
128 static public boolean isGsdlRemote = false;
129 static public boolean isLocalLibrary = false;
130
131 // for storing the original proxy settings on GLI startup
132 private static Properties startup_proxy_settings = new Properties();
133
134 /* TODO: If we're using local GLI, collections are built locally. If we're using client-GLI
135 * and it contains a gs2build folder in it, then localBuild will also be true (if this is not
136 * turned off in Preferences). If we're remote and this is turned off in Prefs, build remotely. */
137 /*static public boolean buildingLocally = true;*/
138 /** If we're using local GLI, we can always download. If we're using client-GLI, we can only
139 * download if we have a gs2build folder inside it. And if we don't turn off downloadEnabling
140 * in the preferences.
141 */
142 static public boolean isDownloadEnabled = true;
143
144 // feedback stuff
145 /** is the feedback feature enabled? */
146 static public boolean feedback_enabled = true;
147 /** the action recorder dialog */
148 static public ActionRecorderDialog feedback_dialog = null;
149
150 // Refresh reasons
151 static public final int COLLECTION_OPENED = 0;
152 static public final int COLLECTION_CLOSED = 1;
153 static public final int COLLECTION_REBUILT = 2;
154 static public final int PREFERENCES_CHANGED = 3;
155
156 //////kk added////////
157 static public String cgiBase="";
158 /////////////////
159
160 /** Magic to allow Enter to fire the default button. */
161 static {
162 KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
163 Keymap map = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
164 map.removeKeyStrokeBinding(enter);
165 }
166
167 static private URL default_gliserver_url=null;
168
169 public Gatherer(String[] args)
170 {
171 // Display the version to make error reports a lot more useful
172 System.err.println("Version: " + PROGRAM_VERSION + "\n");
173
174 JarTools.initialise(this);
175
176 GetOpt go = new GetOpt(args);
177
178 // Remember the GSDLOS value
179 client_operating_system = go.client_operating_system;
180
181 // If feedback is enabled, set up the recorder dialog
182 if (go.feedback_enabled) {
183 // Use the default locale for now - this will be changed by the Gatherer run method
184 feedback_enabled = true;
185 feedback_dialog = new ActionRecorderDialog(Locale.getDefault());
186 }
187
188 // Are we greenstone 2 or 3?
189 if (go.gsdl3_path != null && !go.gsdl3_path.equals("")) {
190 this.GS3 = true;
191 Configuration.config_xml = Configuration.CONFIG_XML_3;
192 } else {
193 go.gsdl3_path = null;
194 go.gsdl3_src_path = null;
195 }
196
197 // Are we using a remote Greenstone?
198 if (go.use_remote_greenstone) {
199 isGsdlRemote = true;
200
201 // We don't have a local Greenstone!
202 go.gsdl3_path=null;
203 go.gsdl3_src_path=null;
204
205 // Don't set go.gsdl_path to null, since gdsl_path may still be set
206 // if we have a client-gli containing gs2build folder.
207 // However, keep track of whether we can download.
208 if(go.gsdl_path == null) {
209 isDownloadEnabled = false;
210 }
211
212 // We have to use our own collect directory since we can't use the Greenstone one
213 setCollectDirectoryPath(getGLIUserDirectoryPath() + "collect" + File.separator);
214 }
215 // We have a local Greenstone. OR we have a gs2build folder inside
216 // the client-GLI folder (with which the Download panel becomes enabled)
217 if(isDownloadEnabled) {
218 LocalGreenstone.setDirectoryPath(go.gsdl_path);
219 }
220
221 // Users may specify a non-standard collect directory (eg. when running one GLI in a network environment)
222 // Processing of custom non-standard collect directory passed into gli now happens in init()
223 //if (go.collect_directory_path != null) { setCollectDirectoryPath(go.collect_directory_path); }
224
225 // More special code for running with a remote Greenstone
226 if (isGsdlRemote) {
227 if (go.fedora_info.isActive()) {
228 Configuration.template_config_xml = Configuration.TEMPLATE_CONFIG_PREFIX + Configuration.FEDORA_CONFIG_PREFIX + Configuration.CONFIG_REMOTE_XML;
229 }
230 else {
231 Configuration.template_config_xml = Configuration.TEMPLATE_CONFIG_PREFIX + Configuration.CONFIG_REMOTE_XML;
232 }
233
234 Configuration.config_xml = Configuration.CONFIG_REMOTE_XML;
235
236 File collect_directory = new File(Gatherer.getCollectDirectoryPath());
237 if (!collect_directory.exists() && !collect_directory.mkdir()) {
238 System.err.println("Warning: Unable to make directory: " + collect_directory);
239 }
240 }
241 else {
242 if (go.fedora_info.isActive()) {
243 Configuration.template_config_xml = Configuration.TEMPLATE_CONFIG_PREFIX + Configuration.FEDORA_CONFIG_PREFIX + Configuration.config_xml;
244 }
245 // else, the CONFIG_XML uses the default config file, which is for the local GS server
246 }
247
248 if(go.testing_mode) {
249 TestingPreparation.TEST_MODE = true;
250 }
251
252 init(go.gsdl_path, go.gsdl3_path, go.gsdl3_src_path,
253 go.fedora_info,
254 go.local_library_path, go.library_url_string,
255 go.gliserver_url_string, go.debug, go.perl_path, go.no_load, go.filename, go.site_name,
256 go.servlet_path, go.collect_directory_path);
257 }
258
259
260 public void init(String gsdl_path, String gsdl3_path, String gsdl3_src_path,
261 FedoraInfo fedora_info,
262 String local_library_path,
263 String library_url_string, String gliserver_url_string, boolean debug_enabled,
264 String perl_path, boolean no_load, String open_collection,
265 String site_name, String servlet_path, String collect_directory_path)
266 {
267
268
269 // Create the debug stream if required
270 if (debug_enabled) {
271 DebugStream.enableDebugging();
272
273 Calendar now = Calendar.getInstance();
274 String debug_file_path = "debug" + now.get(Calendar.DATE) + "-" + now.get(Calendar.MONTH) + "-" + now.get(Calendar.YEAR) + ".txt";
275
276 // Debug file is created in the user's GLI directory
277 debug_file_path = getGLIUserDirectoryPath() + debug_file_path;
278 DebugStream.println("Debug file path: " + debug_file_path);
279 DebugStream.setDebugFile(debug_file_path);
280 DebugStream.print(System.getProperties());
281 }
282
283 // Delete plugins.dat and classifiers.dat files from previous versions of the GLI (no longer used)
284 File plugins_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "plugins.dat");
285 if (plugins_dat_file.exists()) {
286 System.err.println("Deleting plugins.dat file...");
287 Utility.delete(plugins_dat_file);
288 }
289 File classifiers_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "classifiers.dat");
290 if (classifiers_dat_file.exists()) {
291 System.err.println("Deleting classifiers.dat file...");
292 Utility.delete(classifiers_dat_file);
293 }
294
295 try {
296 // Load GLI config file
297 new Configuration(getGLIUserDirectoryPath(), gsdl_path, gsdl3_path, gsdl3_src_path, site_name, servlet_path,
298 fedora_info);
299
300 // Check we know where Perl is
301 Configuration.perl_path = perl_path;
302 if (isGsdlRemote && !isDownloadEnabled && Utility.isWindows() && Configuration.perl_path != null) {
303 if (Configuration.perl_path.toLowerCase().endsWith("perl.exe")) {
304 Configuration.perl_path = Configuration.perl_path.substring(0, Configuration.perl_path.length() - "perl.exe".length());
305 }
306 if (Configuration.perl_path.endsWith(File.separator)) {
307 Configuration.perl_path = Configuration.perl_path.substring(0, Configuration.perl_path.length() - File.separator.length());
308 }
309 }
310
311 // the feedback dialog has been loaded with a default locale,
312 // now set the user specified one
313 if (feedback_enabled && feedback_dialog != null) {
314 feedback_dialog.setLocale(Configuration.getLocale("general.locale", true));
315 }
316
317 // Read Dictionary
318 new Dictionary(Configuration.getLocale("general.locale", true), Configuration.getFont("general.font", true));
319
320 // check that we are using Sun Java
321 String java_vendor = System.getProperty("java.vendor");
322 String java_runtime_name = System.getProperty("java.runtime.name");
323
324
325 if (!java_vendor.equals("Sun Microsystems Inc.")
326 && !java_vendor.equals("Oracle Corporation")
327 && !java_runtime_name.equals("OpenJDK Runtime Environment")) {
328 // OK, so the dictionary key label is a bit apocryphal these days, but it gets the job done
329 System.err.println(Dictionary.get("General.NotSunJava", java_vendor));
330 }
331
332 // Unless we're using remote building, we need to know where the local Greenstone is
333 if (!isGsdlRemote && gsdl_path == null) {
334 missingGSDL();
335 }
336
337 if (fedora_info.isActive()) {
338
339 // if we have either a remote GS 2/3 server, or if we are dealing with a
340 // local GS2, or else if it's a local GS3 but with fedora installed elsewhere,
341 // we ask for fedora login details now
342 File fedora_webapp = new File(gsdl3_src_path+File.separator+"packages"+File.separator+"tomcat"+File.separator+"webapps"+File.separator+"fedora");
343
344 if(isGsdlRemote || !GS3 || !fedora_webapp.exists()) {
345 popupFedoraInfo();
346 }
347
348 // else if we have a local GS3 with fedora installed within it, we'll be starting
349 // up fedora further below, together with the local tomcat
350 }
351
352 // the no_load flag to GLI is processed at the end of handling open_collection_file_path
353 open_collection_file_path = open_collection;
354 if (open_collection_file_path == null) {
355 open_collection_file_path = Configuration.getString(
356 "general.open_collection"+Configuration.gliPropertyNameSuffix(), true);
357 }
358 // we haven't worked out site name yet, so do this step later ...
359 //initCollectDirectoryPath();
360
361 if (no_load || (isGsdlRemote && open_collection_file_path.equals(""))) {
362 open_collection_file_path = null;
363 }
364
365
366 // Before calling setProxy, store anything already present
367 // Downloading happens on the machine where GLI is running from, even with clientgli
368 // For downloading with wget, we use ftp/http(s)_proxy env vars, so check if they're
369 // already set
370 if(System.getenv("http_proxy") != null) System.err.println("http_proxy already set");
371 if(System.getenv("https_proxy") != null) System.err.println("https_proxy already set");
372 if(System.getenv("ftp_proxy") != null) System.err.println("ftp_proxy already set");
373
374
375 // Finally, we're ready to find out the version of the remote Greenstone server
376 if(isGsdlRemote) {
377 // instantiate the RemoteGreenstoneServer object first
378 remoteGreenstoneServer = new RemoteGreenstoneServer();
379
380 // Set up proxy
381 setProxy();
382 // Now we set up an Authenticator
383 Authenticator.setDefault(new GAuthenticator());
384
385 int greenstoneVersion = 2;
386 String prev_gliserver_url_string = Configuration.getString("general.gliserver_url", true);
387 requestGLIServerURL(); // opens up the gliserver dialog
388 gliserver_url_string = Configuration.gliserver_url.toString();
389
390
391 greenstoneVersion = remoteGreenstoneServer.getGreenstoneVersion();
392 // Display the version to make error reports a lot more useful
393 System.err.println("Remote Greenstone server version: " + greenstoneVersion);
394 if(greenstoneVersion == -1) { // remote server not running
395 Gatherer.exit();
396 }
397 if(greenstoneVersion >= 3) {
398 this.GS3 = true;
399 if (!prev_gliserver_url_string.equals(gliserver_url_string)) {
400 System.err.println("Using a new GLI server url, clear site and servlet info");
401 Configuration.setSiteAndServlet("", "");
402 } else {
403 Configuration.prepareForGS3();
404 }
405 }
406
407 if(fedora_info.isActive()) {
408 // when GS server is remote, FEDORA_HOME resides on the remote server side,
409 // but we know the library URL from user-provided information
410 library_url_string = fedora_info.getLibraryURL();
411 } else {
412 library_url_string = remoteGreenstoneServer.getLibraryURL(Configuration.gliserver_url.toString());
413 }
414 // write it into the config file
415 Configuration.setString("general.library_url", true, library_url_string);
416 }
417 else { // local greenstone: add shutdown hooks to forcibly stop the server on irregular termination
418 // And start up the local library server, if that's what we want
419
420 // The Java virtual machine shuts down in response to two kinds of events:
421 // - The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
422 // - The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
423 // https://coderanch.com/t/328888/java/Killing-process-spawned-Runtime-exec
424 // So here we add a shutdown hook to take care of Ctrl-C situations where GLI is irregularly terminated
425 // Sadly, the shutdownhook never gets called on Windows, whether GS2 or GS3,
426 // when a Ctrl-C is sent to the DOS prompt that launched GLI. Because GLI on Windows
427 // currently waits to respond to a Ctrl-C until AFTER GLI is already (properly) exited
428 Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
429 public void run() {
430
431 if(Gatherer.exit != true) { // unexpected termination, such as Ctrl-C won't set Gatherer.exit
432 // so still need to at least issue the call to stop any running GS server
433
434 System.err.println("ShutDownHook called...");
435
436 if (GS3) { // issue the ant call to stop any running GS3
437 // (tomcat and networked Derby Server) by calling GS3ServerThread.stopServer()
438 if(!GS3ServerThread.wasServerLaunchedOutsideGLI()) {
439 System.err.println("Attempting to forcibly terminate the GS server...");
440 GS3ServerThread.stopServer();
441 } else {
442 System.err.println("Tomcat was launched outside GLI. Leaving it running...");
443 }
444 } else { // issue the call to stop any running GS2 local library server
445 if (LocalLibraryServer.isRunning() == true) {
446 System.err.println("Attempting to forcibly terminate the GS server...");
447 LocalLibraryServer.forceStopServer();
448 }
449 }
450 }
451 }
452 }));
453
454
455 if (!GS3) {
456 isLocalLibrary = LocalLibraryServer.start(gsdl_path, local_library_path);
457
458 }
459 else { // local GS3, start the local tomcat
460
461 if(!GS3ServerThread.wasServerLaunchedOutsideGLI()) {
462 //System.err.println("@@@@ Launching tomcat from GLI");
463 GS3ServerThread thread = new GS3ServerThread(gsdl3_src_path, "restart");
464 thread.start();
465 }
466
467 // If fedora installed inside this local GS3, then ask for fedora login details now.
468 if (fedora_info.isActive()) {
469 File fedora_webapp = new File(gsdl3_src_path+File.separator+"packages"+File.separator+"tomcat"+File.separator+"webapps"+File.separator+"fedora");
470
471 if(fedora_webapp.exists()) {
472 System.err.println("**** Waiting for the local Greenstone server to start up fedora...");
473 popupFedoraInfo();
474 }
475 }
476 }
477 // else web library: GS server is local, but doesn't use the webserver included with GS2
478 }
479
480 // The "-library_url" option overwrites anything in the config files
481 if (library_url_string != null && library_url_string.length() > 0) {
482 try {
483 System.err.println("Setting library_url to " + library_url_string + "...");
484 Configuration.library_url = new URL(library_url_string);
485 }
486 catch (MalformedURLException error) {
487 DebugStream.printStackTrace(error);
488 }
489 }
490
491
492 // Check that we now know the Greenstone library URL, since we need this for previewing collections
493 // It is not necessary if an independent GSI was launched and the user hasn't pressed Enter Library yet
494 DebugStream.println("Configuration.library_url = " + Configuration.library_url);
495 if (Configuration.library_url == null) {
496 if(isLocalLibrary) {
497 if(!LocalLibraryServer.isURLPending()) {
498 missingEXEC();
499 }
500 // else LocalLibraryServer is expecting a URL soon, so don't need to display the dialog
501 } else { // GS2 webLibrary or GS3 or remote Greenstone
502 missingEXEC();
503 }
504 }
505
506 // The "-gliserver_url" option overwrites anything in the config files
507 // why do this? we have already asked the user for gliserver url and set it...
508 if (gliserver_url_string != null && gliserver_url_string.length() > 0) {
509 try {
510 System.err.println("Setting gliserver_url to " + gliserver_url_string + "...");
511 Configuration.gliserver_url = new URL(gliserver_url_string);
512 }
513 catch (MalformedURLException error) {
514 DebugStream.printStackTrace(error);
515 }
516 }
517
518 // If we're using a remote Greenstone we need to know where the gliserver script is
519 DebugStream.println("Configuration.gliserver_url = " + Configuration.gliserver_url);
520
521 if (GS3) {
522 // Load Greenstone 3 servlet configuration
523 if (isGsdlRemote){
524 servlet_config = new ServletConfiguration(Configuration.gli_user_directory_path);
525 }else{
526 servlet_config= new ServletConfiguration(gsdl3_path);
527 }
528
529
530 if (Configuration.servlet_path == null || Configuration.servlet_path.equals("")) {
531 String my_servlet_path = null;
532 if (isGsdlRemote) {
533 System.err.println("servlet path is null, get new one from remote server");
534 my_servlet_path = remoteGreenstoneServer.getDefaultServletPath().trim();
535 } else {
536 // we need to look up build.properties
537 System.err.println("servlet path is null, get one from build.properties");
538 Properties build_props = loadBuildProperties();
539 my_servlet_path = build_props.getProperty("greenstone.default.servlet", "/library");
540 build_props = null;
541 }
542 // set site name to match
543 String my_site_name = servlet_config.getSiteForServlet(my_servlet_path);
544 System.err.println("setting site and servlet to " +my_site_name+", "+my_servlet_path);
545 Configuration.setSiteAndServlet(my_site_name, my_servlet_path);
546
547 }
548 }
549
550 initCollectDirectoryPath();
551 // ensure that a directory called 'cache' exists in the GLI user directory
552 File user_cache_dir = new File(Gatherer.getGLIUserCacheDirectoryPath());
553 System.err.println("User cache dir: " + Gatherer.getGLIUserCacheDirectoryPath());
554 if (!user_cache_dir.exists() && !user_cache_dir.mkdir()) {
555 System.err.println("Warning: Unable to make directory: " + user_cache_dir);
556 }
557
558
559 if (Gatherer.isGsdlRemote) {
560 DebugStream.println("Not checking for perl path/exe");
561 }
562 else {
563 // Perl path is a little different as it is perfectly ok to
564 // start the GLI without providing a perl path
565 boolean found_perl = false;
566 if (Configuration.perl_path != null) {
567 // See if the file pointed to actually exists
568 File perl_file = new File(Configuration.perl_path);
569 found_perl = perl_file.exists();
570 perl_file = null;
571 }
572 if (Configuration.perl_path == null || !found_perl) {
573 // Run test to see if we can run perl as is.
574 PerlTest perl_test = new PerlTest();
575 if (perl_test.found()) {
576 // If so replace the perl path with the system
577 // default (or null for unix).
578 Configuration.perl_path = perl_test.toString();
579 found_perl = true;
580 }
581 }
582 if (!found_perl) {
583 // Time for an error message.
584 missingPERL();
585 }
586 }
587
588
589 // Check for ImageMagick - dependent on perl_path
590 if (Gatherer.isGsdlRemote) {
591 DebugStream.println("Not checking for ImageMagick.");
592 }
593 else if (!(new ImageMagickTest()).found()) {
594 // Time for a warning message
595 missingImageMagick();
596 }
597
598 // Check for PDFBox
599 if (Gatherer.isGsdlRemote) {
600 DebugStream.println("Not checking for PDFBox.");
601 }
602 else {
603 String gs_dir = gsdl_path; // for GS3, pdf-box is in gs2build/ext (not in GS3/ext), for GS2 it's also in GS2/ext
604 File pdfboxExtensionFolder = new File(gs_dir+File.separator+"ext"+File.separator+"pdf-box");
605 if (!(pdfboxExtensionFolder.exists() && pdfboxExtensionFolder.isDirectory())) {
606 // The user doesn't have PDFBox, inform them of it
607 String zipExtension = Utility.isWindows() ? "zip" : "tar.gz";
608 missingPDFBox(zipExtension, pdfboxExtensionFolder.getParent());
609 }
610 }
611
612 // Check that the locale can support multiple filename encodings
613 //System.err.println("#### Java identifies current Locale as (file.encoding): "
614 // + System.getProperty("file.encoding"));
615 if(System.getProperty("file.encoding").equals("UTF-8")){
616 // If the locale is UTF-8, Java will interpret all filename bytes as UTF-8,
617 // which is a destructive process as it will convert characters not recognised
618 // by UTF-8 into the invalid character, rather than preserving the bytecodes.
619 // This has the effect that non-UTF8 encoded filenames on a system set to a
620 // UTF-8 locale are not 'seen' by Java (if they contain non-ASCII characters).
621
622 // This message popping up first thing after a successful GS install is thought
623 // to be unnecessarily alarming. Turning off.
624 //multipleFilenameEncodingsNotSupported();
625 FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED = false;
626 FilenameEncoding.URL_FILE_SEPARATOR = File.separator;
627 } else {
628 FilenameEncoding.MULTIPLE_FILENAME_ENCODINGS_SUPPORTED = true;
629 FilenameEncoding.URL_FILE_SEPARATOR = "/"; // URL file separator is always "/"
630 }
631
632 // Set the default font for all Swing components.
633 FontUIResource default_font = Configuration.getFont("general.font", true);
634 Enumeration keys = UIManager.getDefaults().keys();
635 while (keys.hasMoreElements()) {
636 Object key = keys.nextElement();
637 Object value = UIManager.get(key);
638 if (value instanceof FontUIResource) {
639 UIManager.put(key, default_font);
640 }
641 }
642
643 // At this point (which is where this code originally used to be), we can set up the proxy for the
644 // non-remote case. The remote Greenstone server would already have setup its proxy when required.
645 if(!isGsdlRemote) {
646 setProxy();
647 // Now we set up an Authenticator
648 Authenticator.setDefault(new GAuthenticator());
649 }
650 assoc_man = new FileAssociationManager();
651 // Create File Manager
652 f_man = new FileManager();
653 // Create Collection Manager
654 c_man = new CollectionManager();
655 // Create Recycle Bin
656 recycle_bin = new RecycleBin();
657
658 if (GS3) {
659 if (site_name==null) {
660 site_name = Configuration.site_name;
661 servlet_path = null; // need to reset this
662 }
663 if (servlet_path == null) {
664 servlet_path = Configuration.getServletPath();
665 }
666 }
667
668
669 } catch (Exception exception) {
670 DebugStream.printStackTrace(exception);
671 }
672
673
674 // Create GUI Manager (last) or else suffer the death of a thousand NPE's
675 g_man = new GUIManager(size);
676
677 // Get a list of the core Greenstone classifiers and plugins
678 Classifiers.loadClassifiersList(null);
679 Plugins.loadPluginsList(null);
680
681 // Users may specify a non-standard collect directory (eg. when running one GLI in a network environment)
682 // Set to any custom collection directory provided to gli. This happens if gli was run as:
683 // ./gli.sh -collectdir </full/path/to/custom/collect>
684 if(collect_directory_path != null) {
685
686 // create a version of the collect_dir_path without a file-separator at end
687 String collectDir = collect_directory_path;
688 if(collectDir.endsWith(File.separator)) {
689 collectDir = collectDir.substring(0, collectDir.length()-1); // remove file separator at end
690 }
691
692 // update .gli/config.xml to contain the version of the path without file-separator at end
693 if(collect_directory_path.equals(getDefaultGSCollectDirectoryPath(false))) {
694 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
695 true, "");
696 } else {
697 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
698 true, collectDir);
699 }
700
701 // set non_standard_collect_directory_path variable. Ensures file_separator at end
702 Gatherer.setCollectDirectoryPath(collect_directory_path);
703
704 // Use version of path without file-separator at end to set collecthome in gsdlsite(3).cfg
705 if(collectDir != null) {
706 collectDir = "\""+collectDir+"\"";
707 }
708 Utility.updatePropertyConfigFile(getGsdlSiteConfigFile(), "collecthome", collectDir);
709 // if gsdlsite.cfg does not exist (if using server.exe for instance), the above method will just return
710 }
711
712 // If using a remote Greenstone we need to download the collection configurations now
713 if (Gatherer.isGsdlRemote) {
714 if (remoteGreenstoneServer.downloadCollectionConfigurations().equals("")) {
715 // !! Something went wrong downloading the collection configurations
716 System.err.println("Error: Could not download collection configurations.");
717 if(!Gatherer.isApplet) { // don't close the browser if it is an applet!
718 System.exit(0);
719 }
720 }
721 }
722 }
723
724
725 /** Returns the correct version of the (local or remote) Greenstone server if init() has already been called. */
726 public static int serverVersionNumber() {
727 return GS3 ? 3 : 2;
728 }
729
730 /** Returns "Server: version number" if init() has already been called. */
731 public static String getServerVersionAsString() {
732 return "Server: v" + serverVersionNumber();
733 }
734
735 public void openGUI()
736 {
737 // Size and place the frame on the screen
738 Rectangle bounds = Configuration.getBounds("general.bounds", true);
739 if (bounds == null) {
740 // Choose a sensible default value
741 bounds = new Rectangle(0, 0, 640, 480);
742 }
743
744 // Ensure width and height are reasonable
745 size = bounds.getSize();
746 if (size.width < 640) {
747 size.width = 640;
748 }
749 else if (size.width > Configuration.screen_size.width && Configuration.screen_size.width > 0) {
750 size.width = Configuration.screen_size.width;
751 }
752 if (size.height < 480) {
753 size.height = 480;
754 }
755 else if (size.height > Configuration.screen_size.height && Configuration.screen_size.height > 0) {
756 size.height = Configuration.screen_size.height;
757 }
758
759 if (!g_man_built) {
760
761 g_man.display();
762
763 // 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).
764 g_man.setLocation(bounds.x, bounds.y);
765 g_man.setVisible(true);
766
767 // After the window has been made visible, check that it is in the correct place
768 // sometimes java places a window not in the correct place,
769 // but with an offset. If so, we work out what the offset is
770 // and change the desired location to take that into account
771 Point location = g_man.getLocation();
772 int x_offset = bounds.x - location.x;
773 int y_offset = bounds.y - location.y;
774 // If not, offset the window to move it into the correct location
775 if (x_offset > 0 || y_offset > 0) {
776 ///ystem.err.println("changing the location to "+(bounds.x + x_offset)+" "+ (bounds.y + y_offset));
777 g_man.setLocation(bounds.x + x_offset, bounds.y + y_offset);
778 }
779
780 // 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.
781 g_man.afterDisplay();
782 g_man_built = true;
783 }
784 else {
785 g_man.setVisible(true);
786 }
787
788 // Get a list of the core Greenstone classifiers and plugins
789 /*Classifiers.loadClassifiersList(null);
790 Plugins.loadPluginsList(null);
791
792 // If using a remote Greenstone we need to download the collection configurations now
793 if (Gatherer.isGsdlRemote) {
794 if (remoteGreenstoneServer.downloadCollectionConfigurations().equals("")) {
795 // !! Something went wrong downloading the collection configurations
796 System.err.println("Error: Could not download collection configurations.");
797 System.exit(0);
798 }
799 }*/
800
801 // if we're tutorial testing GLI, want names assigned to the GUI components
802 TestingPreparation.setNamesRecursively(g_man);
803
804
805 // If there was a collection left open last time, reopen it
806 if (open_collection_file_path == null || new File(Gatherer.open_collection_file_path).isDirectory()) {
807
808 //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's disabled until the collection finishes loading. They will be enabled in collectionManager.java
809 setMenuBarEnabled(true);
810 } else {
811
812 // If there was a collection left open last time, reopen it
813 c_man.openCollectionFromLastTime();
814 }
815 }
816
817 public static void setMenuBarEnabled(boolean enabled) {
818 g_man.menu_bar.file.setEnabled(enabled);
819 g_man.menu_bar.edit.setEnabled(enabled);
820 }
821
822 /** Exits the Gatherer after ensuring that things needing saving are saved.
823 * @see java.io.FileOutputStream
824 * @see java.io.PrintStream
825 * @see java.lang.Exception
826 * @see javax.swing.JOptionPane
827 * @see org.greenstone.gatherer.Configuration
828 * @see org.greenstone.gatherer.collection.CollectionManager
829 * @see org.greenstone.gatherer.gui.GUIManager
830 */
831 static public void exit(int new_exit_status)
832 {
833 DebugStream.println("In Gatherer.exit()...");
834 exit = true;
835 if (new_exit_status != 0) {
836 // default exit_status is already 0
837 // only remember a new exit status if it is non-trivial
838 exit_status = new_exit_status;
839 }
840
841 // Save the file associations
842 if (assoc_man != null) {
843 assoc_man.save();
844 assoc_man = null;
845 }
846
847 // Get the gui to deallocate
848 if(g_man != null) {
849 g_man.destroy();
850 g_man_built = false;
851 }
852
853 // Flush debug
854 DebugStream.closeDebugStream();
855
856 // If we started a server, we should try to stop it.
857 if (LocalLibraryServer.isRunning() == true) {
858 LocalLibraryServer.stop();
859 }
860
861 // If we're using a remote Greenstone server we need to make sure that all jobs have completed first
862 if (isGsdlRemote) {
863 remoteGreenstoneServer.exit();
864 } else if (GS3) { // stop the local tomcat web server when running GS3
865 // can't call ant stop from its own thread - what if GLI has exited by then?
866 // issue call to ant stop from the main GLI thread
867 //GS3ServerThread thread = new GS3ServerThread(Configuration.gsdl_path, "stop");
868 //thread.start();
869 if(!GS3ServerThread.wasServerLaunchedOutsideGLI()) {
870 GS3ServerThread.stopServer();
871 } else {
872 System.err.println("Tomcat was launched outside GLI. Leaving it running...");
873 }
874
875 }
876
877 // Make sure we haven't started up any processes that are still running
878 if (apps.size() == 0) {
879 // If we're running as an applet we don't actually quit (just hide the main GLI window)
880 if (!Gatherer.isApplet) {
881 // This is the end...
882 System.exit(exit_status);
883 }
884 }
885 else {
886 JOptionPane.showMessageDialog(g_man, Dictionary.get("General.Outstanding_Processes"), Dictionary.get("General.Outstanding_Processes_Title"), JOptionPane.ERROR_MESSAGE);
887 g_man.setVisible(false);
888 }
889 }
890
891 static public void exit()
892 {
893 exit(0);
894 }
895
896 /** Returns the path of the current collect directory. */
897 static public String getCollectDirectoryPath()
898 {
899 if (non_standard_collect_directory_path != null) {
900 return non_standard_collect_directory_path;
901 }
902
903 return getDefaultGSCollectDirectoryPath(true); // file separator appended
904
905 }
906
907 // if we need to know whether the local server we are running is server.exe vs apache web server
908 static public boolean isPersistentServer() {
909 return (!isGsdlRemote && LocalLibraryServer.isPersistentServer());
910 }
911
912 /** Returns the path of the Greenstone "collect" directory. */
913 static public String getDefaultGSCollectDirectoryPath(boolean appendSeparator) {
914 String colDir;
915 if (GS3) {
916 colDir = getSitesDirectoryPath() + Configuration.site_name + File.separator + "collect";
917 }
918 else {
919 colDir = Configuration.gsdl_path + "collect";
920 }
921
922 if(appendSeparator) {
923 colDir += File.separator;
924 }
925 return colDir;
926 }
927
928 /** Returns the path of the GLI directory. */
929 static public String getGLIDirectoryPath()
930 {
931 return gli_directory_path;
932 }
933
934
935 /** Returns the path of the GLI "metadata" directory. */
936 static public String getGLIMetadataDirectoryPath()
937 {
938 return getGLIDirectoryPath() + "metadata" + File.separator;
939 }
940
941
942 /** Returns the path of the GLI user directory. */
943 static public String getGLIUserDirectoryPath()
944 {
945 return gli_user_directory_path;
946 }
947
948
949 /** Returns the path of the GLI user "cache" directory. */
950 static public String getGLIUserCacheDirectoryPath()
951 {
952 return getGLIUserDirectoryPath() + "cache" + File.separator;
953 }
954
955
956 /** Returns the path of the GLI user "log" directory. */
957 static public String getGLIUserLogDirectoryPath()
958 {
959 return getGLIUserDirectoryPath() + "log" + File.separator;
960 }
961
962
963 static public String getSitesDirectoryPath()
964 {
965 return Configuration.gsdl3_path + "sites" + File.separator;
966 }
967
968
969 static public void setCollectDirectoryPath(String collect_directory_path)
970 {
971 non_standard_collect_directory_path = collect_directory_path;
972 if (!non_standard_collect_directory_path.endsWith(File.separator)) {
973 non_standard_collect_directory_path = non_standard_collect_directory_path + File.separator;
974 }
975 }
976
977
978 static public void setGLIDirectoryPath(String gli_directory_path_arg)
979 {
980 gli_directory_path = gli_directory_path_arg;
981 }
982
983
984 static public void setGLIUserDirectoryPath(String gli_user_directory_path_arg)
985 {
986 gli_user_directory_path = gli_user_directory_path_arg;
987
988 // Ensure the GLI user directory exists
989 File gli_user_directory = new File(gli_user_directory_path);
990 if (!gli_user_directory.exists() && !gli_user_directory.mkdirs()) {
991 System.err.println("Error: Unable to make directory: " + gli_user_directory);
992 }
993 }
994
995
996 public static void initCollectDirectoryPath() {
997 String defaultColdir = getDefaultGSCollectDirectoryPath(false); // no file separator at end
998 String coldir = defaultColdir;
999 // If local GS and opening a collection outside the standard GS collect folder,
1000 // need to open the non-standard collect folder that the collection resides in
1001 if (!isGsdlRemote
1002 && !open_collection_file_path.startsWith(defaultColdir))
1003 {
1004 File collectFolder = null;
1005
1006 if(!open_collection_file_path.equals("")) {
1007 if(!open_collection_file_path.endsWith("gli.col")) { // then it's a collect folder
1008 collectFolder = new File(open_collection_file_path);
1009 } else {
1010 // the filepath is a gli.col file. To get the collect folder: the 1st level up
1011 // is the collection folder, 2 two levels up is the containing collect folder
1012 collectFolder = new File(open_collection_file_path).getParentFile().getParentFile();
1013 }
1014
1015 // Need to deal with colgroups as well: while there's an etc/collect.cfg
1016 // in the current collectFolder, move one level up
1017 String cfg_file = (Gatherer.GS3)? Utility.CONFIG_GS3_FILE : Utility.CONFIG_FILE;
1018 if(new File(collectFolder.getAbsolutePath()+File.separator+cfg_file).exists()) { // colgroup
1019 collectFolder = collectFolder.getParentFile();
1020 }
1021
1022 // Inform the user that their collecthome is non-standard (not inside GS installation)
1023 nonStandardCollectHomeMessage(collectFolder.getAbsolutePath(), defaultColdir); // display message
1024 }
1025
1026 if(collectFolder == null || !collectFolder.exists()) {
1027 // if GLI config file specified no collectDir (open_collection_file_path is "")
1028 // OR if dealing with a local server but the collectdir no longer exists,
1029 // use the default greenstone collect directory, and write that to affected files
1030
1031 open_collection_file_path = defaultColdir; // default GS collect dir
1032 // Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(), true, "");
1033 } else { // use the coldir value specified in the flags to GLI or from the last GLI session
1034 coldir = collectFolder.getAbsolutePath();
1035 }
1036 // set it as the current folder
1037 setCollectDirectoryPath(coldir); // will ensure the required file separator at end
1038 }
1039
1040 if(!isGsdlRemote) {
1041 // LocalLibraryServer would already have set glisite.cfg to the correct collecthome for server.exe
1042 // Here we set collecthome in gsdl(3)site.cfg for the GS2 apache web server and GS3 tomcat server
1043 String gsdlsitecfg = getGsdlSiteConfigFile();
1044 // update the gsdlsite config file and store the old value for use when we exit GLI
1045 if(coldir.equals(defaultColdir)) {
1046 gsdlsite_collecthome = Utility.updatePropertyConfigFile(
1047 gsdlsitecfg, "collecthome", null);
1048 } else {
1049 gsdlsite_collecthome = Utility.updatePropertyConfigFile(
1050 gsdlsitecfg, "collecthome", "\""+coldir+"\""); // no file separator
1051 // if gsdlsite.cfg does not exist (if using server.exe for instance), the above method will just return
1052 }
1053 }
1054 }
1055
1056 /** depending on the version of GS being run, return the path to the current GS' installation's gsdl(3)site.cfg */
1057 public static String getGsdlSiteConfigFile() {
1058 if(Gatherer.GS3) { // web/WEB-INF/cgi/gsdl3site.cfg
1059 return Configuration.gsdl3_path + File.separator + "WEB-INF"
1060 + File.separator + "cgi" + File.separator + "gsdl3site.cfg";
1061 } else { // cgi-bin/gsdlsite.cfg
1062 String gsdlarch = System.getenv("GSDLARCH");
1063 if(gsdlarch == null) {
1064 gsdlarch = "";
1065 }
1066 return Configuration.gsdl_path /* + File.separator */
1067 + "cgi-bin" + File.separator + client_operating_system+gsdlarch + File.separator + "gsdlsite.cfg";
1068 }
1069 }
1070
1071 public static void collectDirectoryHasChanged(
1072 String oldCollectPath, String newCollectPath, final Component container)
1073 {
1074 if(oldCollectPath.equals(newCollectPath)) {
1075 return; // nothing to be done
1076 }
1077
1078 // Will use a busy cursor if the process of changing the collect directory takes more
1079 // than half a second/500ms. See http://www.catalysoft.com/articles/busyCursor.html
1080 Cursor originalCursor = container.getCursor();
1081 java.util.TimerTask timerTask = new java.util.TimerTask() {
1082 public void run() {
1083 // set the cursor on the container:
1084 container.setCursor(new Cursor(Cursor.WAIT_CURSOR));
1085 }
1086 };
1087 java.util.Timer timer = new java.util.Timer();
1088
1089 try {
1090 timer.schedule(timerTask, 500);
1091
1092 // first save any open collection in the old location, then close it
1093 if(Gatherer.c_man.getCollection() != null) {
1094 Gatherer.g_man.saveThenCloseCurrentCollection(); // close the current collection first
1095 }
1096
1097 // change to new collect path
1098 if(newCollectPath.equals(getDefaultGSCollectDirectoryPath(true))) {
1099 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
1100 true, "");
1101 } else {
1102 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
1103 true, newCollectPath);
1104 }
1105 Gatherer.setCollectDirectoryPath(newCollectPath);
1106
1107
1108 // refresh the Documents in Greenstone Collections
1109 //WorkspaceTreeModel.refreshGreenstoneCollectionsNode();
1110 Gatherer.g_man.refreshWorkspaceTreeGreenstoneCollections();
1111
1112 // The web server needs to be told where a new (non-standard) collecthome home is.
1113 // The web server reads collecthome from cgi-bin/<OS>/gsdlsite.cfg, where the property
1114 // collecthome can be specified if a non-standard collecthome is to be used. If no
1115 // such property is specified in the file, then it assumes the standard GS collecthome.
1116 // This method does nothing for a remote Greenstone.
1117 if(Gatherer.isGsdlRemote) {
1118 return;
1119 }
1120
1121 // non-destructive update of gsdl(3)site.cfg (comments preserved)
1122 String collectDir = Gatherer.getCollectDirectoryPath();
1123 //collectDir = "\"" + collectDir.substring(0, collectDir.length()-1) + "\""; // remove file separator at end
1124 collectDir = collectDir.substring(0, collectDir.length()-1); // remove file separator at end
1125 if(collectDir != null) {
1126 collectDir = "\""+collectDir+"\"";
1127 }
1128 Utility.updatePropertyConfigFile(getGsdlSiteConfigFile(), "collecthome", collectDir);
1129 // if gsdlsite.cfg does not exist (if using server.exe for instance), the above method will just return
1130
1131 if(!Gatherer.GS3 && Gatherer.isLocalLibrary) {
1132 // for Images in the collection to work, the apache web server
1133 // configuration's COLLECTHOME should be updated on collectdir change.
1134 // Does nothing for server.exe at the moment
1135
1136 LocalLibraryServer.reconfigure();
1137 }
1138 } finally { // Note try-finally section without catch:
1139 // "Java's finally clause is guaranteed to be executed even when
1140 // an exception is thrown and not caught in the current scope."
1141 // See http://www.catalysoft.com/articles/busyCursor.html
1142 // the following code fragment is guaranteed to restore the original
1143 // cursor now the custom actionPerformed() processing is complete, regardless
1144 // of whether the processing method terminates normally or throws an exception
1145 // and regardless of where in the call stack the exception is caught.
1146
1147 timer.cancel();
1148 container.setCursor(originalCursor);
1149 }
1150 }
1151
1152
1153 static public void refresh(int refresh_reason)
1154 {
1155 if (g_man != null) {
1156
1157 g_man.refresh(refresh_reason, c_man.ready());
1158 }
1159
1160 // Now is a good time to force a garbage collect
1161 System.gc();
1162 }
1163
1164
1165 // used to send reload coll messages to the tomcat server
1166 static public void configGS3Server(String site, String command) {
1167
1168 // Do not do configGS3Server for a GS3 solr collection. Not at present at least, when we're stopping
1169 // and starting the GS3 server from GLI for solr cols, since this function clears the solr.xml file.
1170 /*if(Gatherer.c_man.isSolrCollection()) {
1171 return;
1172 }*/
1173
1174 if (Configuration.library_url == null){
1175 System.err.println("Error: you have not provided the Greenstone Library address.");
1176 return;
1177
1178 }
1179
1180 try {
1181 // need to add the servlet name to the exec address
1182 String raw_url = Configuration.library_url.toString() + Configuration.getServletPath() + command;
1183 URL url = new URL(raw_url);
1184 DebugStream.println("Action: " + raw_url);
1185 HttpURLConnection library_connection = (HttpURLConnection) url.openConnection();
1186 int response_code = library_connection.getResponseCode();
1187 if(HttpURLConnection.HTTP_OK <= response_code && response_code < HttpURLConnection.HTTP_MULT_CHOICE) {
1188 DebugStream.println("200 - Complete.");
1189 }
1190 else {
1191 DebugStream.println("404 - Failed.");
1192 }
1193 url = null;
1194 }
1195 catch(java.net.ConnectException connectException) {
1196 JOptionPane.showMessageDialog(g_man, Dictionary.get("Preferences.Connection.Library_Path_Connection_Failure", Configuration.library_url.toString()), Dictionary.get("General.Warning"), JOptionPane.WARNING_MESSAGE);
1197 DebugStream.println(connectException.getMessage());
1198 }
1199 catch (Exception exception) {
1200 DebugStream.printStackTrace(exception);
1201 }
1202 }
1203
1204
1205 /** Used to 'spawn' a new child application when a file is double clicked.
1206 * @param file The file to open
1207 * @see org.greenstone.gatherer.Gatherer.ExternalApplication
1208 */
1209 static public void spawnApplication(File file) {
1210 String [] commands = assoc_man.getCommand(file);
1211 if(commands != null) {
1212 ExternalApplication app = new ExternalApplication(commands);
1213 apps.add(app);
1214 app.start();
1215 }
1216 else {
1217 ///ystem.err.println("No open command available.");
1218 }
1219 }
1220
1221
1222 static public void spawnApplication(String command)
1223 {
1224 ExternalApplication app = new ExternalApplication(command);
1225 apps.add(app);
1226 app.start();
1227 }
1228
1229 static public void spawnApplication(String command, String ID)
1230 {
1231 ExternalApplication app = new ExternalApplication(command, ID);
1232 apps.add(app);
1233 app.start();
1234 }
1235
1236 static public void spawnApplication(String[] commands, String ID)
1237 {
1238 ExternalApplication app = new ExternalApplication(commands, ID);
1239 apps.add(app);
1240 app.start();
1241 }
1242
1243 static public void terminateApplication(String ID) {
1244 for(int i = 0; i < apps.size(); i++) {
1245 ExternalApplication app = (ExternalApplication)apps.get(i);
1246 if(app.getID() != null && app.getID().equals(ID)) {
1247 app.stopExternalApplication();
1248 apps.remove(app);
1249 }
1250 }
1251 }
1252
1253
1254 /** Used to 'spawn' a new browser application or reset an existing one when the preview button is clicked
1255 * @param url The url to open the browser at
1256 * @see org.greenstone.gatherer.Gatherer.BrowserApplication
1257 */
1258 static public void spawnBrowser(String url) {
1259 String command = assoc_man.getBrowserCommand(url);
1260 if (command != null) {
1261 BrowserApplication app = new BrowserApplication(command, url);
1262 apps.add(app);
1263 app.start();
1264 }
1265 else {
1266 ///ystem.err.println("No browser command available.");
1267 }
1268 }
1269
1270
1271 /** Prints a warning message about a missing library path, which means the final collection cannot be previewed in the Gatherer.
1272 */
1273 static public void missingEXEC() {
1274 try {
1275 SwingUtilities.invokeAndWait(new Runnable() {
1276 public void run() {
1277 WarningDialog dialog;
1278 String configPropertyName = "general.library_url"+Configuration.gliPropertyNameSuffix();
1279
1280 if (GS3) {
1281 // Warning dialog with no cancel button and no "turn off warning" checkbox
1282 dialog = new WarningDialog("warning.MissingEXEC", Dictionary.get("MissingEXEC_GS3.Title"), Dictionary.get("MissingEXEC_GS3.Message"), configPropertyName, false, false);
1283 } else { // local case
1284 dialog = new WarningDialog("warning.MissingEXEC", Dictionary.get("MissingEXEC.Title"), Dictionary.get("MissingEXEC.Message"), configPropertyName, false);
1285 }
1286
1287 JTextField field = new URLField.Text(Configuration.getColor("coloring.editable_foreground", false), Configuration.getColor("coloring.editable_background", false));
1288
1289 // Set the default library URL to the tomcat server and port number
1290 // specified in the build.properties located in the gsdl3_src_path
1291 if (GS3) {
1292 // defaults
1293 String host = "localhost";
1294 String port = "8383";
1295 String context = "greenstone3";
1296 String protocol = "http";
1297
1298 File buildPropsFile = new File(Configuration.gsdl3_src_path + File.separator + "build.properties");
1299 if(buildPropsFile.exists()) {
1300 Properties props = new Properties();
1301 try{
1302 props.load(new FileInputStream(buildPropsFile));
1303 host = props.getProperty("tomcat.server", host);
1304 context = props.getProperty("greenstone.context", context);
1305 ProtocolPortProperties protocolPortProps = new ProtocolPortProperties(props); // can throw Exception
1306 // Use ProtocolPortProperties to get the tomcat port and protocol used
1307 protocol = protocolPortProps.getProtocol();
1308 port = protocolPortProps.getPort();
1309 }catch(Exception e){
1310 DebugStream.println("Could not load build.properties file");
1311 System.err.println("Could not load build.properties file");
1312 }
1313 props = null;
1314 }
1315 String defaultURL = protocol+"://"+host+":"+port+"/"+context;
1316 field.setText(defaultURL);
1317 field.selectAll();
1318 }
1319 dialog.setValueField(field);
1320 dialog.display();
1321 dialog.dispose();
1322 dialog = null;
1323
1324 String library_url_string = Configuration.getString(configPropertyName, true);
1325 if (!library_url_string.equals("")) {
1326 try {
1327 // WarningDialog does not allow invalid URLs, so the following is ignored:
1328 // make sure the URL the user provided contains the http:// prefix
1329 // and then save the corrected URL
1330 if(!library_url_string.startsWith("http://")
1331 && !library_url_string.startsWith("https://")) {
1332 library_url_string = "http://"+library_url_string;
1333 Configuration.setString(configPropertyName, true, configPropertyName);
1334 }
1335 Configuration.library_url = new URL(library_url_string);
1336 }
1337 catch (MalformedURLException exception) {
1338 DebugStream.printStackTrace(exception);
1339 }
1340 }
1341 }
1342 });
1343 } catch(Exception e) { //InterruptedException or InvocationTargetException
1344 e.printStackTrace();
1345 }
1346 }
1347
1348 static private Properties loadBuildProperties() {
1349
1350 File buildPropsFile = new File(Configuration.gsdl3_src_path + File.separator + "build.properties");
1351 Properties props = null;
1352 if(buildPropsFile.exists()) {
1353 props = new Properties();
1354 try{
1355 props.load(new FileInputStream(buildPropsFile));
1356 } catch (Exception e) {
1357 System.err.println("couldn't load properties "+e.toString());
1358 props = null;
1359 }
1360 }
1361 return props;
1362 }
1363
1364 /** Prints a warning message about a missing library path, which means the final collection cannot be previewed in the Gatherer.
1365 */
1366 static private void popupFedoraInfo() {
1367 try {
1368 SwingUtilities.invokeAndWait(new Runnable() {
1369 public void run() {
1370 FedoraLogin dialog = new FedoraLogin("Fedora Login", false);
1371
1372 if (Configuration.library_url == null) {
1373
1374 String library_url_string = dialog.getLibraryURL();
1375 if (!library_url_string.equals("")) {
1376 try {
1377 Configuration.library_url = new URL(library_url_string);
1378 }
1379 catch (MalformedURLException exception) {
1380 DebugStream.printStackTrace(exception);
1381 }
1382 }
1383 }
1384
1385 boolean showLogin = true;
1386 do {
1387 if(!dialog.loginRequested()) { // user pressed cancel to exit the FedoraLogin dialog
1388 System.exit(0);
1389 } else {
1390 showLogin = dialog.loginRequested();
1391 String hostname = dialog.getHostname();
1392 String port = dialog.getPort();
1393 String username = dialog.getUsername();
1394 String password = dialog.getPassword();
1395 String protocol = dialog.getProtocol();
1396
1397 Configuration.fedora_info.setHostname(hostname);
1398 Configuration.fedora_info.setPort(port);
1399 Configuration.fedora_info.setUsername(username);
1400 Configuration.fedora_info.setPassword(password);
1401 Configuration.fedora_info.setProtocol(protocol);
1402
1403 String ping_url_str = protocol + "://" + hostname + ":" + port + "/fedora";
1404 String login_str = username + ":" + password;
1405
1406 String login_encoding = Base64.encodeBytes(login_str.getBytes());
1407
1408 try {
1409 URL ping_url = new URL(ping_url_str);
1410 URLConnection uc = ping_url.openConnection();
1411 uc.setRequestProperty ("Authorization", "Basic " + login_encoding);
1412 // Attempt to access some content ...
1413 InputStream content = (InputStream)uc.getInputStream();
1414
1415 // if no exception occurred in the above, we would have come here:
1416 showLogin = false;
1417 dialog.dispose();
1418 }
1419 catch (Exception exception) {
1420 // TODO: move into dictionary
1421 String[] errorMessage = {"Failed to connect to the Fedora server.", "It might not be running, or",
1422 "incorrect username and/or password."};
1423 dialog.setErrorMessage(errorMessage);
1424 //DebugStream.printStackTrace(exception);
1425 // exception occurred, show the dialog again (do this after printing to
1426 // debugStream, else the above does not get done for some reason).
1427 dialog.setVisible(true);
1428 }
1429 }
1430 } while(showLogin);
1431
1432 dialog = null; // no more need of the dialog
1433
1434 // Now we are connected.
1435 }
1436 });
1437 } catch(Exception e) { //InterruptedException or InvocationTargetException
1438 e.printStackTrace();
1439 }
1440 }
1441
1442
1443
1444 static private void requestGLIServerURL()
1445 {
1446 try {
1447 SwingUtilities.invokeAndWait(new Runnable() {
1448 public void run() {
1449 WarningDialog dialog;
1450 String[] defaultURLs = {
1451 "http://localhost:8383/greenstone3/cgi-bin/gliserver.pl",
1452 "http://localhost:8080/gsdl/cgi-bin/gliserver.pl"
1453 };
1454
1455 // Warning dialog with no cancel button and no "turn off warning" checkbox
1456 // (since user-input of the gliserver script is mandatory)
1457 dialog = new WarningDialog("warning.MissingGLIServer", Dictionary.get("MissingGLIServer.Title"), Dictionary.get("MissingGLIServer.Message"), "general.gliserver_url", false, false);
1458
1459 dialog.setValueField(new URLField.DropDown(Configuration.getColor("coloring.editable_foreground", false),
1460 Configuration.getColor("coloring.editable_background", false),
1461 defaultURLs, "general.gliserver_url",
1462 "general.open_collection"+Configuration.gliPropertyNameSuffix(),
1463 "gliserver.pl"));
1464
1465 if (Gatherer.default_gliserver_url!=null){
1466 dialog.setValueField(Gatherer.default_gliserver_url.toString());
1467 }
1468
1469 // A WarningDialog cannot always be made to respond (let alone to exit the program) on close. We
1470 // handle the response of this particular WarningDialog here: a URL for gliserver.pl is a crucial
1471 // piece of user-provided data. Therefore, if no URL was entered for gliserver.pl, it'll exit safely.
1472 dialog.addWindowListener(new WindowAdapter() {
1473 public void windowClosing(WindowEvent e) {
1474 Gatherer.exit();
1475 }
1476 });
1477
1478 dialog.display();
1479 dialog.dispose();
1480 dialog = null;
1481
1482
1483 String gliserver_url_string = Configuration.getString("general.gliserver_url", true);
1484 if (!gliserver_url_string.equals("")) {
1485 try {
1486 Configuration.gliserver_url = new URL(gliserver_url_string);
1487 Configuration.setString("general.gliserver_url", true, gliserver_url_string);
1488 }
1489 catch (MalformedURLException exception) {
1490 DebugStream.printStackTrace(exception);
1491 }
1492 }
1493 }
1494 });
1495 } catch(Exception e) { //InterruptedException or InvocationTargetException
1496 e.printStackTrace();
1497 }
1498 }
1499
1500
1501 /** Prints a warning message about a missing GSDL path, which although not fatal pretty much ensures nothing will work properly in the GLI.
1502 */
1503 static private void missingGSDL() {
1504 try {
1505 SwingUtilities.invokeAndWait(new Runnable() {
1506 public void run() {
1507 WarningDialog dialog = new WarningDialog("warning.MissingGSDL", Dictionary.get("MissingGSDL.Title"), Dictionary.get("MissingGSDL.Message"), null, false);
1508 dialog.display();
1509 dialog.dispose();
1510 dialog = null;
1511 }
1512 });
1513 } catch(Exception e) { //InterruptedException or InvocationTargetException
1514 e.printStackTrace();
1515 }
1516 }
1517
1518 /** Prints a warning message about missing a valid ImageMagick path, which although not fatal means building image collections won't work */
1519 static private void missingImageMagick() {
1520 try {
1521 SwingUtilities.invokeAndWait(new Runnable() {
1522 public void run() {
1523 WarningDialog dialog = new WarningDialog("warning.MissingImageMagick", Dictionary.get("MissingImageMagick.Title"), Dictionary.get("MissingImageMagick.Message"), null, false);
1524 dialog.display();
1525 dialog.dispose();
1526 dialog = null;
1527 }
1528 });
1529 } catch(Exception e) { //InterruptedException or InvocationTargetException
1530 e.printStackTrace();
1531 }
1532 }
1533
1534 /** Prints a message informing the user where they can get PDFBox from to process PDF files of v1.5 and greater */
1535 static private void missingPDFBox(final String zipExtension, final String extFolder) {
1536 try {
1537 SwingUtilities.invokeAndWait(new Runnable() {
1538 public void run() {
1539
1540 // point to the correct version of the PDFBox extension for this Greenstone release
1541 String releaseTag = "";
1542 if(!PROGRAM_VERSION.equals("trunk")) { // assume it's a release version
1543 releaseTag = "main/tags/"+PROGRAM_VERSION+"/";
1544 }
1545
1546 WarningDialog dialog = new WarningDialog("warning.MissingPDFBox", Dictionary.get("MissingPDFBox.Title"), Dictionary.get("MissingPDFBox.Message", new String[]{releaseTag, zipExtension, extFolder}), null, false);
1547 dialog.display();
1548 dialog.dispose();
1549 dialog = null;
1550 }
1551 });
1552 } catch(Exception e) { //InterruptedException or InvocationTargetException
1553 e.printStackTrace();
1554 }
1555 }
1556
1557 /** 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. */
1558 static private void missingPERL() {
1559 try {
1560 SwingUtilities.invokeAndWait(new Runnable() {
1561 public void run() {
1562 WarningDialog dialog = new WarningDialog("warning.MissingPERL", Dictionary.get("MissingPERL.Title"), Dictionary.get("MissingPERL.Message"), null, false);
1563 dialog.display();
1564 dialog.dispose();
1565 dialog = null;
1566 }
1567 });
1568 } catch(Exception e) { //InterruptedException or InvocationTargetException
1569 e.printStackTrace();
1570 }
1571 }
1572
1573 /** Prints a message informing the user that their collecthome is non-standard (not inside GS installation) */
1574 static private void nonStandardCollectHomeMessage(final String open_collection_file_path, final String defaultColDir) {
1575 try {
1576 SwingUtilities.invokeAndWait(new Runnable() {
1577 public void run() {
1578 WarningDialog dialog = new WarningDialog("warning.NonStandardCollectHome", Dictionary.get("NonStandardCollectHome.Title"), Dictionary.get("NonStandardCollectHome.Message", new String[]{open_collection_file_path, defaultColDir}), null, false);
1579 dialog.display();
1580 dialog.dispose();
1581 dialog = null;
1582 }
1583 });
1584 } catch(Exception e) { //InterruptedException or InvocationTargetException
1585 e.printStackTrace();
1586 }
1587 }
1588
1589 /** Prints a warning message about the OS not supporting multiple filename encodings. */
1590 static private void multipleFilenameEncodingsNotSupported() {
1591 try {
1592 SwingUtilities.invokeAndWait(new Runnable() {
1593 public void run() {
1594 WarningDialog dialog = new WarningDialog("warning.NoEncodingSupport",
1595 Dictionary.get("NoEncodingSupport.Title"),
1596 Dictionary.get("NoEncodingSupport.Message"), null, false);
1597 dialog.display();
1598 dialog.dispose();
1599 dialog = null;
1600 }
1601 });
1602 } catch(Exception e) { //InterruptedException or InvocationTargetException
1603 e.printStackTrace();
1604 }
1605 }
1606
1607 /** Sets up the proxy connection by setting JVM Environment flags and creating a new Authenticator.
1608 * @see java.lang.Exception
1609 * @see java.lang.System
1610 * @see java.net.Authenticator
1611 * @see org.greenstone.gatherer.Configuration
1612 * @see org.greenstone.gatherer.GAuthenticator
1613 */
1614 static public void setProxy() {
1615 try {// Can throw several exceptions
1616 boolean use_proxy = Configuration.get("general.use_proxy", true);
1617
1618 setProxyForProtocol("http", use_proxy);
1619 setProxyForProtocol("https", use_proxy);
1620 setProxyForProtocol("ftp", use_proxy);
1621
1622 } catch (Exception error) {
1623 DebugStream.println("Error in Gatherer.initProxy(): " + error);
1624 DebugStream.printStackTrace(error);
1625 }
1626 }
1627
1628 private static void setProxyForProtocol(String protocol, boolean use_proxy) throws Exception {
1629 // These are Java properties, therefore see
1630 // https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
1631 // https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
1632 // https://stackoverflow.com/questions/14243590/proxy-settings-in-java
1633
1634 // Just need to warn the user that we're overriding proxy settings using custom defined proxy settings
1635 // and returning to using the original proxy settings when custom defined proxy settings are turned off
1636 // We don't actually need to store/restore the original settings, as Java system vars like http.proxyHost
1637 // http.proxyPort don't seem to be set even if on GLI startup the env vars like http(s)_proxy were already set.
1638
1639
1640 if(use_proxy) {
1641 if(System.getenv(protocol+"_proxy") != null) {
1642 System.err.println("Overriding original "+protocol+" proxy settings");
1643 }
1644
1645 // set the custom proxy defined through GLI for this protocol
1646 System.setProperty(protocol+".proxyHost", Configuration.getString("general."+protocol.toUpperCase()+"_proxy_host", true));
1647 System.setProperty(protocol+".proxyPort", Configuration.getString("general."+protocol.toUpperCase()+"_proxy_port", true));
1648
1649 // Not sure what proxyType is. And proxySet ceased to exist since JDK 6 or before. See links above.
1650 // But we used to set them both for HTTP before, so still doing so for proxyType, since it may or may not exist
1651 // But proxySet doesn't exist anymore, so not continuing with that.
1652 if(protocol.equals("http")) {
1653 System.setProperty(protocol+".proxyType", "4");
1654 //System.setProperty(protocol+".proxySet", "true");
1655 }
1656
1657 }
1658
1659 else { // use_proxy=false, not using proxy defined through GLI, so
1660 // either unset proxy vars for this protocol, or restore any original settings for them
1661
1662 if(System.getenv(protocol+"_proxy") != null) {
1663 System.err.println("Restoring original "+protocol+" proxy settings");
1664 }
1665
1666 System.setProperty(protocol+".proxyHost", "");
1667 System.setProperty(protocol+".proxyPort", "");
1668 //if(protocol.equals("http")) {
1669 //System.setProperty(protocol+".proxySet", "false");
1670 //}
1671 }
1672 }
1673
1674
1675 /** 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 voluntarily 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. */
1676 static private class ExternalApplication
1677 extends Thread {
1678 private SafeProcess process = null;
1679 /** The initial command string given to this sub-process. */
1680 private String command = null;
1681 private String[] commands = null;
1682
1683 private String ID = null;
1684
1685 /** Constructor.
1686 * @param command The initial command <strong>String</strong>.
1687 */
1688 public ExternalApplication(String command) {
1689 this.command = command;
1690 }
1691
1692 public ExternalApplication(String[] commands) {
1693 this.commands = commands;
1694 }
1695
1696 public ExternalApplication(String command, String ID) {
1697 this.command = command;
1698 this.ID = ID;
1699 }
1700
1701 public ExternalApplication(String[] commands, String ID) {
1702 this.commands = commands;
1703 this.ID = ID;
1704 }
1705
1706 public String getID() {
1707 return ID;
1708 }
1709
1710 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
1711 * @see java.lang.Exception
1712 * @see java.lang.Process
1713 * @see java.lang.Runtime
1714 * @see java.lang.System
1715 * @see java.util.Vector
1716 */
1717 public void run() {
1718 // Call an external process using the args.
1719 try {
1720 if(commands != null) {
1721 StringBuffer whole_command = new StringBuffer();
1722 for(int i = 0; i < commands.length; i++) {
1723 // get rid of any quotes around parameters in file associations
1724 if(commands[i].startsWith("\"") || commands[i].startsWith("\'")) {
1725 commands[i] = commands[i].substring(1);
1726 }
1727 if(commands[i].endsWith("\"") || commands[i].endsWith("\'")) {
1728 commands[i] = commands[i].substring(0, commands[i].length()-1);
1729 }
1730
1731 if (i>0) {
1732 whole_command.append(" ");
1733 }
1734 whole_command.append(commands[i]);
1735 }
1736 DebugStream.println("Running " + whole_command.toString());
1737 process = new SafeProcess(commands);
1738 }
1739 else {
1740 DebugStream.println("Running " + command);
1741 process = new SafeProcess(command);
1742 }
1743 process.runProcess();
1744 }
1745 catch (Exception exception) {
1746 DebugStream.printStackTrace(exception);
1747 }
1748 // Remove ourself from Gatherer list of threads.
1749 apps.remove(this);
1750 // Call exit if we were the last outstanding child process thread.
1751 if (apps.size() == 0 && exit == true) {
1752 // In my opinion (DB) there is no need to exit here,
1753 // the 'run' method ending naturally brings this
1754 // thread to an end. In fact it is potentially
1755 // dangerous to exit here, as the main thread in the
1756 // Gatherer class may be stopped prematurely. As it so
1757 // happens the point at which the ExternalApplication thread
1758 // is asked to stop (Back in the main Gatherer thread) is after
1759 // various configuration files have been saved.
1760 //
1761 // A similar argument holds for BrowserApplication thread below.
1762 System.exit(exit_status);
1763 }
1764 }
1765 public void stopExternalApplication() {
1766 if(process != null) {
1767 SafeProcess.log("*** stopExternalApplication called.");
1768 process.cancelRunningProcess();
1769 }
1770 }
1771 }
1772 /** 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. */
1773 static private class BrowserApplication
1774 extends Thread {
1775 private SafeProcess process = null;
1776 /** The initial command string given to this sub-process. */
1777 private String command = null;
1778 private String url = null;
1779 private String[] commands = null;
1780
1781 public BrowserApplication(String command, String url) {
1782 StringTokenizer st = new StringTokenizer(command);
1783 int num_tokens = st.countTokens();
1784 this.commands = new String [num_tokens];
1785 int i=0;
1786 while (st.hasMoreTokens()) {
1787 commands[i] = st.nextToken();
1788 i++;
1789 }
1790 //this.commands = commands;
1791 this.url = url;
1792 }
1793 /** We start the child process inside a new thread so it doesn't block the rest of Gatherer.
1794 * @see java.lang.Exception
1795 * @see java.lang.Process
1796 * @see java.lang.Runtime
1797 * @see java.lang.System
1798 * @see java.util.Vector
1799 */
1800 public void run() {
1801 // Call an external process using the args.
1802 if(commands == null) {
1803 apps.remove(this);
1804 return;
1805 }
1806 try {
1807 String prog_name = commands[0];
1808 String lower_name = prog_name.toLowerCase();
1809 if (lower_name.indexOf("mozilla") != -1 || lower_name.indexOf("netscape") != -1) {
1810 DebugStream.println("found mozilla or netscape, trying remote it");
1811 // mozilla and netscape, try using a remote command to get things in the same window
1812 String [] new_commands = new String[] {prog_name, "-raise", "-remote", "openURL("+url+",new-tab)"};
1813 printArray(new_commands);
1814
1815 process = new SafeProcess(new_commands);
1816 int exitCode = process.runProcess();
1817 if (exitCode != 0) { // if Netscape or mozilla was not open
1818 DebugStream.println("couldn't do remote, trying original command");
1819 printArray(commands);
1820 process = null;
1821 process = new SafeProcess(commands); // try the original command
1822 process.runProcess();
1823 }
1824 } else {
1825 // just run what we have been given
1826 StringBuffer whole_command = new StringBuffer();
1827 for(int i = 0; i < commands.length; i++) {
1828 whole_command.append(commands[i]);
1829 whole_command.append(" ");
1830 }
1831 DebugStream.println("Running " + whole_command.toString());
1832 process = new SafeProcess(commands);
1833 process.runProcess();
1834 }
1835 }
1836
1837 catch (Exception exception) {
1838 DebugStream.printStackTrace(exception);
1839 }
1840 // Remove ourself from Gatherer list of threads.
1841 apps.remove(this);
1842 // Call exit if we were the last outstanding child process thread.
1843 if (apps.size() == 0 && exit == true) {
1844 System.exit(exit_status);
1845 }
1846 }
1847 public void printArray(String [] array) {
1848 for(int i = 0; i < array.length; i++) {
1849 DebugStream.print(array[i]+" ");
1850 System.err.println(array[i]+" ");
1851 }
1852 }
1853 public void stopBrowserApplication() {
1854 if(process != null) {
1855 SafeProcess.log("*** stopBrowserApplication called.");
1856 process.cancelRunningProcess();
1857 }
1858 }
1859 }
1860
1861
1862 private class ImageMagickTest
1863 {
1864 public boolean found()
1865 {
1866 // at this stage, GLI has already sourced setup.bash, and the necessary
1867 // env variables will be available to the perl process we're about to launch
1868 boolean found = false;
1869
1870
1871 // run the command `/path/to/perl -S gs-magick.pl identify -version`
1872 ArrayList cmd_list = new ArrayList();
1873 if (!Gatherer.isGsdlRemote) {
1874 if(Configuration.perl_path != null) {
1875 cmd_list.add(Configuration.perl_path);
1876 } else {
1877 System.err.println("Warning: ImageMagickTest::found() perl_path not set, calling 'perl' instead.");
1878 cmd_list.add("perl");
1879 }
1880 cmd_list.add("-S");
1881 }
1882 cmd_list.add("gs-magick.pl");
1883 if(Utility.isWindows()) {
1884 cmd_list.add("identify.exe");
1885 } else {
1886 cmd_list.add("identify");
1887 }
1888 cmd_list.add("-version");
1889
1890 String[] command_parts = (String[]) cmd_list.toArray(new String[0]);
1891
1892 String cmd_str = "";
1893 for(int i = 0; i < command_parts.length; i++) {
1894 cmd_str += command_parts[i] + " ";
1895 }
1896 DebugStream.println("***** Running ImageMagickTest command: " + cmd_str);
1897
1898 SafeProcess image_magick_process = new SafeProcess(command_parts);
1899 int exitValue = image_magick_process.runProcess(); // default process iostream handling
1900 //new way of detection of ImageMagick
1901 // Inspect the standard output of the process and seach for two particular occurrences: Version and ImageMagick.
1902 String output = image_magick_process.getStdOutput().toLowerCase();
1903 if (output.indexOf("version") != -1 || output.indexOf("imagemagick") != -1) {
1904 found = true;
1905 } // else found var remains false
1906
1907 return found;
1908 //return (image_magick_process.exitValue() == 0);
1909
1910 }
1911 }
1912
1913
1914 private class PerlTest
1915 {
1916 private String[] command = new String[2];
1917
1918 public PerlTest()
1919 {
1920 command[0] = (Utility.isWindows() ? Utility.PERL_EXECUTABLE_WINDOWS : Utility.PERL_EXECUTABLE_UNIX);
1921 command[1] = "-version";
1922 }
1923
1924 public boolean found()
1925 {
1926 try {
1927 SafeProcess perl_process = new SafeProcess(command);
1928 int exitValue = perl_process.runBasicProcess();
1929 return (exitValue == 0);
1930 }
1931 catch (Exception exception) {
1932 return false;
1933 }
1934 }
1935
1936 public String toString() {
1937 return command[0];
1938 }
1939 }
1940
1941}
Note: See TracBrowser for help on using the repository browser.