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

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

need to work out servlet_path and site_name in the local (not remote) case too - use build.properties to look for greenstone_default_servlet. Also, move initCollectDir to later on, after we have worked out what the site name is

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