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

Last change on this file since 37312 was 37312, checked in by kjdon, 14 months ago

added dialog to display authentication error to user

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