source: main/trunk/gli/src/org/greenstone/gatherer/greenstone/LocalLibraryServer.java@ 24906

Last change on this file since 24906 was 24906, checked in by ak19, 12 years ago

The original GLI LocalLibraryServer code called restore() when stopping the LLS. This would delete the configfile if it was not null. This code remained the same throughout the old changes from gsdlsite.cfg to glisite.cfg. However, the more recent change was to merge glisite.cfg with llssite.cfg, and we don't want to delete the file containing the property values. The file now retains the values that I think are important to remember, removes the URL that must be deleted when the server is stopped, additionally removes some values particular to server.exe and finally ensures that some basic defaults are retained if anything goes missing.

  • Property svn:keywords set to Author Date Id Revision
File size: 35.8 KB
Line 
1/**
2 *############################################################################
3 * A component of the Greenstone Librarian Interface, part of the Greenstone
4 * digital library suite from the New Zealand Digital Library Project at the
5 * University of Waikato, New Zealand.
6 *
7 * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
8 *
9 * Copyright (C) 2004 New Zealand Digital Library Project
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *############################################################################
25 */
26
27package org.greenstone.gatherer.greenstone;
28
29
30import java.io.*;
31import java.lang.*;
32import java.net.*;
33import java.util.*;
34import javax.swing.*;
35import org.greenstone.gatherer.Configuration;
36import org.greenstone.gatherer.DebugStream;
37import org.greenstone.gatherer.Dictionary;
38import org.greenstone.gatherer.Gatherer;
39import org.greenstone.gatherer.util.PortFinder;
40import org.greenstone.gatherer.util.Utility;
41
42
43public class LocalLibraryServer
44{
45 static final private int WAITING_TIME = 20; // number of seconds to wait for the server to start and stop
46
47 static final private String ADD_COMMAND = "?a=config&cmd=add-collection&c=";
48 static final private String RELEASE_COMMAND = "?a=config&cmd=release-collection&c=";
49 static final private String QUIT_COMMAND = "?a=config&cmd=kill";
50 static final private String RESTART_COMMAND = "?a=config&cmd=restart";
51
52 static private LLSSiteConfig llssite_cfg_file = null;
53 static private File local_library_server_file = null;
54
55 static private boolean running = false;
56 static private String ID = "greenstone-server"; // a sort of process ID
57
58 // Need to use sockets to tell the server program to terminate when on Linux
59 // The socket port number that we will use to communicate the termination
60 static private int port;
61 static private Socket clientSocket = null;
62 static private Writer clientSocketWriter = null;
63
64 // The server is persistent if it does not have to reload all the values
65 // over and over again each time. Tomcat is persistent and fastcgi is too,
66 // but the Apache webserver is not persistent by default.
67 // Change the initialisation of this value depending on whether fastcgi is
68 // on. At the moment, this does not apply to the Apache local library server.
69 static private boolean isPersistentServer = false;
70
71 static public boolean isPersistentServer() {
72 return isPersistentServer;
73 }
74
75 static public void addCollection(String collection_name)
76 {
77 if (isPersistentServer) {
78 config(ADD_COMMAND + collection_name);
79 }
80 }
81
82
83 // Used to send messages to the local library
84 static private void config(String command)
85 {
86 if (!isPersistentServer) {
87 return;
88 }
89 if (Configuration.library_url == null) {
90 System.err.println("Error: Trying to configure local library with null Configuration.library_url!");
91 return;
92 }
93
94 try {
95 URL url = new URL(Configuration.library_url.toString() + command);
96 HttpURLConnection library_connection = (HttpURLConnection) url.openConnection();
97
98 // It's very important that we read the output of the command
99 // This ensures that the command has actually finished
100 // (The response code is returned immediately)
101 InputStream library_is = library_connection.getInputStream();
102 BufferedReader library_in = new BufferedReader(new InputStreamReader(library_is, "UTF-8"));
103 String library_output_line = library_in.readLine();
104 while (library_output_line != null) {
105 DebugStream.println("Local library server output: " + library_output_line);
106 library_output_line = library_in.readLine();
107 }
108 library_in.close();
109
110 int response_code = library_connection.getResponseCode();
111 if (response_code >= HttpURLConnection.HTTP_OK && response_code < HttpURLConnection.HTTP_MULT_CHOICE) {
112 DebugStream.println("200 - Complete.");
113 }
114 else {
115 DebugStream.println("404 - Failed.");
116 }
117 }
118 catch (Exception exception) {
119 DebugStream.printStackTrace(exception);
120 }
121 }
122
123 // Used to send messages to the local library server wrapper to the Apache web server (server.jar)
124 static private boolean sendMessageToServer(String message) {
125 if(isPersistentServer) {
126 return false;
127 }
128
129 if(port == -1) {
130 return false;
131 }
132
133 try {
134 if(clientSocket == null) {
135 clientSocket = new Socket("localhost", port);
136 }
137 if(clientSocketWriter == null) {
138 clientSocketWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
139 }
140 clientSocketWriter.write(message);
141 clientSocketWriter.flush();
142
143 } catch (Exception e) {
144 System.err.println("An exception occurred when trying to send the message: " + message
145 + "\nto the LocalLibraryServer.\n" + e);
146 return false;
147 }
148 return true;
149 }
150
151 static public boolean isRunning()
152 {
153 if (!running) return false; // if the url is pending, then running would also be false (server not started up yet)
154
155 llssite_cfg_file.load(true);
156 String url = llssite_cfg_file.getURL();
157 if (url == null) return false;
158
159 // Called by Gatherer to check whether we need to stop the server.
160 // if the url is pending, then the GSI hasn't started the server up yet
161 // Already covered in !running
162 //if (url.equals(LLSSiteConfig.URL_PENDING)) return false;
163
164 return true;
165 }
166
167 /** collection name can be a group-qualified collect name */
168 static public void releaseCollection(String collection_name)
169 {
170 if (isPersistentServer) {
171 config(RELEASE_COMMAND + collection_name);
172 }
173 }
174
175 static public boolean start(String gsdl_path, String local_library_server_file_path)
176 {
177 // Check the local library server file (server.exe or gs2-server.sh) exists
178 if(local_library_server_file_path == null) {
179 return false;
180 }
181 local_library_server_file = new File(local_library_server_file_path);
182 if (local_library_server_file.exists()) {
183 if(local_library_server_file.getName().equals("server.exe")) {
184 isPersistentServer = true;
185 } // else it may be gs2-web-server.bat
186 }
187 else { // local_library_server_file does not exist
188 DebugStream.println("No local library at given file path.");
189
190 if(Utility.isWindows()) { // test for server.exe and gs2-web-server.bat
191 local_library_server_file = new File(gsdl_path + "server.exe");
192 if (local_library_server_file.exists()) {
193 isPersistentServer = true;
194 } else {
195 local_library_server_file = new File(gsdl_path + "gs2-web-server.bat");
196 if (!local_library_server_file.exists()) {
197 DebugStream.println("No local library at all.");
198 return false;
199 }
200 }
201 } else { // linux
202 local_library_server_file = new File(gsdl_path + "gs2-server.sh");
203 if (!local_library_server_file.exists()) {
204 DebugStream.println("No local library at all.");
205 return false;
206 }
207 }
208 }
209
210 if(!isPersistentServer) {
211 // In the case of the Local Library Server on Linux or on Win where there's no server.exe, do an extra test:
212 // If GS2 was not configured with --enable-apache-httpd, then there is no apache webserver folder,
213 // even though the gs2-server.sh file would still be there. That means if the folder is absent
214 // we still have no local library server.
215
216 File localServerFolder = new File(gsdl_path, "apache-httpd");
217 if (!localServerFolder.exists() && !localServerFolder.isDirectory()) {
218 DebugStream.println("The web server does not exist at "
219 + localServerFolder.getAbsolutePath() + "\nNo local library at all. Trying web library");
220 return false;
221 } // else apache-httpd folder exists
222 }
223
224 llssite_cfg_file = new LLSSiteConfig(local_library_server_file);
225 if(!llssite_cfg_file.isConfigFileSet()) {
226 return false;
227 }
228
229 // from now on return true: we're in local_library_mode (even if the server is not running)
230
231
232 // If the user launched the GSI independent of GLI, but user has not pressed
233 // Enter Library yet, then we will obtain the previewURL later.
234 if(LocalLibraryServer.isURLPending()) {
235 // running is still false when the URL is pending because only GSI is running, not the server
236 return true;
237 } else if(llssite_cfg_file.isIndependentGSI()) {
238 // There is already a url and it's not pending: meaning the server
239 // has started up and that GSI was launched outside of GLI
240 running = true;
241 return true;
242 }
243
244 // Spawn local library server process
245 final String QUOTES = Utility.isWindows() ? "\"" : ""; // need to embed path in quotes on Windows for spaces (interferes on Linux)
246 String local_library_server_command = QUOTES+local_library_server_file.getAbsolutePath()+QUOTES + getExtraLaunchArguments(llssite_cfg_file);
247 if(Utility.isWindows() && !isPersistentServer) { // launching gs2-web-server.bat (Windows) needs cmd start
248 local_library_server_command = "cmd.exe /c start \"GSI\" " + local_library_server_command;
249 }
250
251 // Check if the server is already running
252 String url = llssite_cfg_file.getURL();
253 if (url != null) {
254 // If it is already running then set the Greenstone web server address and we're done
255 // E.g. if previously GLI was not properly shut down, the URL property (signifying
256 // the server is still running) would still be in the config file.
257 try {
258 Configuration.library_url = new URL(url);
259 running = true;
260
261 // Run the server interface
262 Gatherer.spawnApplication(local_library_server_command, ID);
263 return true;
264 }
265 catch (MalformedURLException exception) {
266 DebugStream.printStackTrace(exception);
267 }
268 }
269
270 // Configure the server for immediate entry
271 //llssite_cfg_file.set();
272
273 // Spawn local library server process
274 Gatherer.spawnApplication(local_library_server_command, ID);
275
276 // Wait until program has started
277 try {
278 //System.err.println("**** testing server...");
279 testServerRunning(); // will set running = true when the server is up and running successfully
280 //System.err.println("**** Is server running: " + running);
281 } catch (IOException bad_url_connection) {
282 try {
283 // If this fails then we try changing the url to be localhost
284 Configuration.library_url = new URL(llssite_cfg_file.getLocalHostURL());
285 DebugStream.println("Try connecting to server on local host: '" + Configuration.library_url + "'");
286 URLConnection connection = Configuration.library_url.openConnection();
287 connection.getContent();
288 running = true;
289
290 } catch (IOException worse_url_connection) {
291 DebugStream.println("Can't connect to server on either address.");
292 Configuration.library_url = null;
293 running = false;
294 }
295 }
296
297 return true;
298 }
299
300 /** Call this when the collect directory has changed. Only works when using
301 * the web server launched by GLI. */
302 static public void reconfigure() {
303 if(isPersistentServer) {
304 // 1st: server may have nulled URL if server was stopped inbetween,
305 // so load that new URL, if GLI conf file modified
306 // Then put the new collectDir into the GLI configfile being used
307 llssite_cfg_file.load(true);
308
309 String collectDir = Gatherer.getCollectDirectoryPath();
310 collectDir = collectDir.substring(0, collectDir.length()-1); // remove file separator at end
311 llssite_cfg_file.put(LLSSiteConfig.COLLECTHOME, collectDir);
312 llssite_cfg_file.save();
313
314 // tell the server to restart, so it will read the new configuration
315
316 // (1) need a server to be running in order for us to send a restart message to it
317 if(checkServerRunning()) { // if true, it wasn't running before, but has now restarted the server. We're done
318 return;
319 }
320 // (2) otherwise the server may already have been running, need to tell it to restart after setting the collect dir
321 if(running) {
322 config(RESTART_COMMAND);
323 }
324 return;
325 }
326
327 // can't control the GSI/server if it was launched independent of GLI
328 if(llssite_cfg_file.isIndependentGSI()) {
329 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.Reconfigure"), Dictionary.get("General.Reconfigure"), JOptionPane.INFORMATION_MESSAGE);
330 return;
331 }
332
333 // someone may have closed the web server
334 if(checkServerRunning()) { // need a server to be running in order for us to send a reconfigure message to it
335 return; // it has reconfigured and restarted the server
336 }
337
338 // If it was already running, tell the server a reconfigure is required on next restart
339 // and then restart
340 if(running && sendMessageToServer("RECONFIGURE\n")) {
341 // restart
342 if(running) {
343 running = false;
344
345 if(sendMessageToServer("RESTART\n")) { //if(sendMessageToServer("RECONFIGURE\n")) {
346 // wait for the server to update the URL in the gli config file
347 llssite_cfg_file.setLastModified();
348
349 int attempt_count = 0;
350 while (!llssite_cfg_file.isModified()) {
351 new OneSecondWait(); // Wait one second (give or take)
352 attempt_count++;
353
354 // After waiting for the specified time, ask the user whether they want to wait for that long again
355 if (attempt_count == WAITING_TIME) {
356 break; // can't be waiting forever, we'll be waiting again below
357 }
358 }
359
360 try {
361 testServerRunning(); // will set running = true when the server is up and running successfully
362 } catch (IOException bad_url_connection) {
363 try {
364 // If this fails then we try changing the url to be localhost
365 Configuration.library_url = new URL(llssite_cfg_file.getLocalHostURL());
366 DebugStream.println("Try connecting to server on local host: '" + Configuration.library_url + "'");
367 URLConnection connection = Configuration.library_url.openConnection();
368 connection.getContent();
369 running = true;
370
371 } catch (IOException worse_url_connection) {
372 DebugStream.println("Can't connect to server on either address.");
373 Configuration.library_url = null;
374 running = false;
375 }
376 }
377 }
378 }
379 } else {
380 System.err.println("GLI was unable to send a reconfigure request to the local library server."
381 + "\nPlease reconfigure and restart the local Greenstone server manually.");
382 }
383 }
384
385
386 static public void stop()
387 {
388 if (!running) {
389 // also the case if the URL is pending in an independently launched GSI
390 return;
391 }
392
393 // don't (can't) shutdown the GSI/server if it was launched independent of GLI
394 if(llssite_cfg_file.isIndependentGSI()) {
395 return;
396 }
397
398 // Send the command for it to exit.
399 if (isPersistentServer) {
400 config(QUIT_COMMAND);
401 } else {
402 boolean success = sendMessageToServer("QUIT\n");
403 try {
404 if(clientSocketWriter != null) {
405 clientSocketWriter.close();
406 clientSocketWriter = null;
407 }
408 clientSocket = null;
409 } catch(Exception e) {
410 System.err.println("An exception occurred when trying to close the socket"
411 + "\nto the LocalLibraryServer.\n" + e);
412 }
413 if(success) {
414 Gatherer.terminateApplication(ID);
415 } else {
416 System.err.println("Unable to stop the server, since there's no communication port to send the quit msg over."
417 + "\nPlease stop the local Greenstone server manually.");
418 }
419 }
420
421 // Wait until program has stopped, by reloading and checking the URL field
422 llssite_cfg_file.load(false);
423 int attempt_count = 0;
424 String url = llssite_cfg_file.getURL();
425 while (url != null && !url.equals(LLSSiteConfig.URL_PENDING)) { // if pending, the server is already stopped (not running)
426 new OneSecondWait(); // Wait one second (give or take)
427 llssite_cfg_file.load(false);
428 attempt_count++;
429
430 // After waiting for the specified time, ask the user whether they want to wait for that long again
431 if (attempt_count == WAITING_TIME) {
432 int try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.QuitTimeOut", Integer.toString(WAITING_TIME)),
433 Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
434 if (try_again == JOptionPane.NO_OPTION) {
435 return;
436 }
437 attempt_count = 0;
438 }
439 // read the url again to see if it's updated
440 url = llssite_cfg_file.getURL();
441 }
442
443 // Restore the llssite_cfg.
444 llssite_cfg_file.restore();
445
446 // If the local server is still running then our changed values will get overwritten.
447 url = llssite_cfg_file.getURL();
448 if (url != null && !url.equals(LLSSiteConfig.URL_PENDING)) {
449 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.QuitManual"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
450 }
451
452 running = false;
453 }
454
455 static private String getExtraLaunchArguments(LLSSiteConfig site_cfg_file) {
456 String args = " " + LLSSiteConfig.GLIMODE + " " + site_cfg_file.getSiteConfigFilename();
457
458 if(isPersistentServer) {
459 return args;
460 }
461
462 // Else, when running the Local Apache Library Server on Linux/Win, need to provide a port argument
463 try {
464 PortFinder portFinder = new PortFinder(50100, 100);
465 port = portFinder.findPortInRange(false); // silent mode
466 } catch(Exception e) {
467 System.err.println("Exception when trying to find an available port: " + e);
468 port = -1;
469 }
470
471 return args + " --quitport=" + port;
472 }
473
474
475 // This method first tests whether there is a URL in the llssite_cfg_file
476 // and after that appears, it tests whether the URL is functional.
477 static private void testServerRunning() throws IOException {
478 // Wait until program has started, by reloading and checking the URL field
479 llssite_cfg_file.load(false);
480 int attempt_count = 0;
481 while (llssite_cfg_file.getURL() == null) {
482 new OneSecondWait(); // Wait one second (give or take)
483 //System.err.println("**** One Second Wait");
484 llssite_cfg_file.load(false);
485 attempt_count++;
486
487 // After waiting for the specified time, ask the user whether they want to wait for that long again
488 if (attempt_count == WAITING_TIME) {
489 int try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.StartUpTimeOut", Integer.toString(WAITING_TIME)),
490 Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
491 if (try_again == JOptionPane.NO_OPTION) {
492 return;
493 }
494 attempt_count = 0;
495 }
496 }
497
498 // Ta-da. Now the url should be available
499 try {
500 Configuration.library_url = new URL(llssite_cfg_file.getURL());
501 }
502 catch (MalformedURLException exception) {
503 DebugStream.printStackTrace(exception);
504 }
505
506 // A quick test involves opening a connection to get the home page for this collection
507 try {
508 DebugStream.println("Try connecting to server on config url: '" + Configuration.library_url + "'");
509 URLConnection connection = Configuration.library_url.openConnection();
510 connection.getContent();
511 running = true;
512 }
513 catch (IOException bad_url_connection) {
514 System.err.println("Unable to open a connection to " + Configuration.library_url
515 + "\nCheck whether the port may already be in use. If so, change your\n"
516 + "Greenstone port number in the Greenstone Server Interface(GSI).");
517 throw bad_url_connection;
518 }
519
520
521 }
522
523 /** Returns true if we're waiting on the user to click on Enter Library button
524 * in an independently launched GSI (one not launched by GLI). */
525 static public boolean isURLPending() {
526 //if(Configuration.library_url != null) {
527 //System.err.println("**** Configuration.library_url: " + Configuration.library_url );
528 //return false; // don't need to do anything as we already have the url
529 //}
530
531 llssite_cfg_file.load(true); // don't force reload, load only if modified
532
533 String url = llssite_cfg_file.getURL();
534
535 if(url != null) {
536 if(url.equals(LLSSiteConfig.URL_PENDING)) {
537 running = false; // imagine if they restarted an external GSI
538 return true;
539 } else {
540 // a valid URL at last
541 try {
542 Configuration.library_url = new URL(url);
543 running = true;
544 }
545 catch (MalformedURLException exception) {
546 running = false;
547 exception.printStackTrace();
548 DebugStream.printStackTrace(exception);
549 }
550 return false;
551 }
552 }
553
554 // If either the URL is null--which means no independent GSI (Greenstone server interface
555 // app) was launched--or if the 'URL' doesn't say it's pending, then we're not waiting
556 return false;
557 }
558
559 /** @returns true if it had to restart the server. Returns false if it didn't restart it. */
560 static public boolean checkServerRunning() {
561 boolean serverRestarted = false;
562
563 if (!running) return false; // don't worry about it if it's not supposed to be running
564 llssite_cfg_file.load(true); // don't force reload, load only if modified
565
566 String url = llssite_cfg_file.getURL();
567 if(url != null) {
568 if(url.equals(LLSSiteConfig.URL_PENDING)) {
569 running = false;
570 return false;
571 }
572
573 // else, valid URL:
574 try {
575 Configuration.library_url = new URL(url);
576 running = true;
577 }
578 catch (MalformedURLException exception) {
579 running = false;
580 DebugStream.printStackTrace(exception);
581 exception.printStackTrace();
582 }
583 }
584 else { // NO URL in current mode of configFile, try other mode (e.g. "gli.url")
585
586 if(llssite_cfg_file.usingGSImode()) { // if a GSI is already using llssite_cfg, this would have loaded it in
587 url = llssite_cfg_file.getURL(); //if(isURLPending()) {
588 if(url.equals(LLSSiteConfig.URL_PENDING)) {
589 running = false;
590 } else {
591 running = true;
592 }
593 return false; // don't need to launch the server, one has been independently launched
594 } else {
595 // else we try using the "gli." prefix to access the url property in the config file
596 llssite_cfg_file.useGLImode();
597 //llssite_cfg_file.set();
598
599 // since we're going to restart the server, make sure to reset all
600 // the client socket and its writer (for communicating with the web server)
601 // will only be reinstantiated if they are first nulled
602 if(clientSocket != null) {
603 clientSocket = null;
604 }
605 if(clientSocketWriter != null) {
606 try{
607 clientSocketWriter.close();
608 clientSocketWriter = null;
609 } catch(Exception e) {
610 System.err.println("Unable to close the client socket outputstream.");
611 } finally {
612 clientSocketWriter = null;
613 }
614 }
615
616 // Spawn local library server process
617 running = false;
618 final String QUOTES = Utility.isWindows() ? "\"" : ""; // need to embed path in quotes on Windows for spaces (interferes on Linux)
619 String local_library_server_command = QUOTES+local_library_server_file.getAbsolutePath()+QUOTES + getExtraLaunchArguments(llssite_cfg_file);
620 if(Utility.isWindows() && !isPersistentServer) { // launching gs2-web-server.bat (Windows) needs cmd start
621 local_library_server_command = "cmd.exe /c start \"GSI\" " + local_library_server_command;
622 }
623 Gatherer.spawnApplication(local_library_server_command, ID);
624 try {
625 testServerRunning(); // don't return until the webserver is up and running
626 serverRestarted = true;
627 } catch (IOException bad_url_connection) {
628 DebugStream.println("Can't connect to server on address " + Configuration.library_url);
629 running = false;
630 }
631 }
632 }
633 return serverRestarted;
634 }
635
636 static private class OneSecondWait
637 {
638 public OneSecondWait()
639 {
640 synchronized(this) {
641 try {
642 wait(1000);
643 }
644 catch (InterruptedException exception) {
645 }
646 }
647 }
648 }
649
650
651 static public class LLSSiteConfig
652 extends LinkedHashMap
653 {
654 private File configFile;
655
656 private String autoenter_initial;
657 private String start_browser_initial;
658
659 private long lastModified = 0;
660 private boolean isIndependentGSI;
661
662 static final private String GLI_PREFIX = "gli";
663 static final private String GSI_AUTOENTER = "autoenter";
664 static final private String AUTOENTER = GLI_PREFIX+"."+"autoenter";
665 static final private String COLON = ":";
666 static final private String ENTERLIB = "enterlib";
667 static final private String FALSE = "0";
668 static final private String GSDL = "greenstone"; // httpprefix is no longer /gsdl but /greenstone
669 static final private String LLSSITE_CFG = "llssite.cfg";
670 static final private String LOCAL_HOST = "http://localhost";
671 static final private String PORTNUMBER = "portnumber";
672 static final private String SEPARATOR = "/";
673 static final private String SPECIFIC_CONFIG = "--config=";
674 static final private String STARTBROWSER = GLI_PREFIX+"."+"start_browser";
675 static final private String GSI_STARTBROWSER = "start_browser";
676 static final private String TRUE = "1";
677 static final private String URL = GLI_PREFIX+"."+"url";
678 static final private String GSI_URL = "url";
679 static final private String COLLECTHOME = "collecthome";
680 static final private String GLIMODE = "--mode="+GLI_PREFIX;
681
682 static final public String URL_PENDING = "URL_pending";
683
684
685 public LLSSiteConfig(File server_exe) {
686 debug("New LLSSiteConfig for: " + server_exe.getAbsolutePath());
687
688 configFile = new File(server_exe.getParentFile(), LLSSITE_CFG);
689 if(!configFile.exists()) { // create it from the template
690 File llssite_cfg_in = new File(server_exe.getParentFile(), LLSSITE_CFG+".in");
691
692 // need to generate llssite_cfg from llssite_cfg_in
693 if(llssite_cfg_in.exists()) {
694 copyConfigFile(llssite_cfg_in, configFile, true); // adjust for gli
695 }
696 else {
697 debug("File llssite.cfg.in can't be found. Can't create llssite.cfg frrom llssite.cfg.in.");
698 }
699 }
700
701 // use the config file now
702 if(configFile.exists()) {
703 // first test if server was started independently of GLI
704 // if so, the config file we'd be using would be llssite.cfg
705 if(!usingGSImode()) { // this step will try to access the url and other
706 // special properties in the config file using the "gli." prefix.
707 useGLImode();
708 }
709
710 } else {
711 System.err.println("**** ERROR. Configfile is null.");
712 configFile = null;
713 }
714
715 autoenter_initial = null;
716 start_browser_initial = null;
717
718 // GS2. We're in the constructor, so we'll be running the LLS the first time
719 // Set the correct collectdir (from last time) before the server is started up
720
721 String orig_collection_path = Configuration.getString("general.open_collection_gs2", true);
722 String collectDir = Gatherer.getCollectDirectoryPath(); // Gatherer would've set this up
723 String defaultColDir = Gatherer.getDefaultGSCollectDirectoryPath(true); // with file separator at end
724
725 if(orig_collection_path.equals("")) { // default GS collect dir path
726 return;
727 }
728
729 if (!orig_collection_path.startsWith(collectDir) // if coldir would've been changed on startup OR if coldir is non-standard collect folder
730 || !collectDir.equals(defaultColDir))
731 {
732 // if we're running *server.exe* and if the current collect dir at Local Lib's startup is
733 // anything other than the default GS collect dir or if we changed back to the default collect
734 // dir because the non-standard collectDir didn't exist/wasn't specified in the GLI config
735 // file, then write out the new collectDir (minus file separator at end) to the lls site conf in use
736 // Regardless of what collecthome value was in the llssite file, we end up resetting it here
737 if (isPersistentServer) { // server.exe, so we're dealing with a local GS2
738 put(COLLECTHOME, collectDir);
739 save();
740 lastModified = configFile.lastModified();
741 }
742 } // now the correct current collect dir will get loaded when the server is started up hereafter
743 }
744
745 /** Changes the mode to GLI mode (since GSI was not launched independently but by GLI): in this
746 * mode, the "gli." prefix is used to access GLI specific properties from the config file */
747 public void useGLImode()
748 {
749 isIndependentGSI = false;
750 load(true); // reload if modified
751 }
752
753 /** Tests whether the server interface is up, running independently of GLI
754 * If so, we don't need to launch the server interface.
755 * The server interface may not have started up the server itself though
756 * (in which case the server URL would be URL_PENDING).
757 * This method returns true if the server interface has already started
758 * and, if so, it would have loaded in the configFile. It sets the mode to
759 * GSI Mode (meaning GSI was launched independently): no prefix is used to
760 * access properties from the config file.
761 */
762 public boolean usingGSImode() {
763 // Now to check if the configfile contains the GSI_URL line
764 load(false); // force load
765 isIndependentGSI = true;
766 if(getURL() == null) {
767 isIndependentGSI = false;
768 return false;
769 }
770
771 lastModified = configFile.lastModified();
772 return true;
773 }
774
775 /** To test we've actually instantiated this object meaningfully. If so, then configFile is set */
776 public boolean isConfigFileSet() {
777 return (configFile != null && configFile.exists());
778 }
779
780 /** @return true if GSI was started up independently and outside of GLI.
781 * In such a case, GLI would be using llssite_cfg. */
782 public boolean isIndependentGSI() {
783 return isIndependentGSI;
784 }
785
786 public boolean exists() {
787 return configFile.exists();
788 }
789
790 public String getLocalHostURL() {
791 StringBuffer url = new StringBuffer(LOCAL_HOST);
792 url.append(COLON);
793 url.append((String)get(PORTNUMBER));
794 String enterlib = (String)get(ENTERLIB);
795 if(!isPersistentServer || enterlib == null || enterlib.length() == 0) {
796 // Use the default /gsdl and hope for the best.
797 url.append(SEPARATOR);
798 url.append(GSDL);
799 }
800 else {
801 if(!enterlib.startsWith(SEPARATOR)) {
802 url.append(SEPARATOR);
803 }
804 url.append(enterlib);
805 }
806 enterlib = null;
807 debug("Found Local Library Address: " + url.toString());
808 return url.toString();
809 }
810
811 /** @return the cmd-line parameter for the configfile used to launch
812 * the server through GLI: --config=<llssite.cfg file path>. */
813 public String getSiteConfigFilename() {
814 return SPECIFIC_CONFIG + configFile.getAbsolutePath();
815 }
816
817 public String getURL() {
818 String urlPropertyName = isIndependentGSI() ? GSI_URL : URL;
819 // URL is made from url and portnumber
820 String url = (String) get(urlPropertyName);
821
822 // server interface is already up, independent of GLI
823 // but it has not started the server (hence URL is pending)
824 if(url != null && url.equals(URL_PENDING)) {
825 return url;
826 }
827
828 if(!isPersistentServer) {
829 return url;
830 }
831
832 if(url != null) {
833 StringBuffer temp = new StringBuffer(url);
834 temp.append(COLON);
835 temp.append((String)get(PORTNUMBER));
836 String enterlib = (String)get(ENTERLIB);
837 if(enterlib == null || enterlib.length() == 0) {
838 // Use the default /greenstone prefix and hope for the best.
839 temp.append(SEPARATOR);
840 temp.append(GSDL);
841 }
842 else {
843 if(!enterlib.startsWith(SEPARATOR)) {
844 temp.append(SEPARATOR);
845 }
846 temp.append(enterlib);
847 }
848 enterlib = null;
849 url = temp.toString();
850 }
851 debug("Found Local Library Address: " + url);
852 return url;
853 }
854
855 public void setLastModified() {
856 if(isModified()) {
857 lastModified = configFile.lastModified();
858 }
859 }
860
861 public boolean isModified() {
862 return (lastModified != configFile.lastModified());
863 }
864
865 public void load(boolean reloadOnlyIfModified) {
866
867 if(configFile == null) {
868 debug(configFile.getAbsolutePath() + " cannot be found!");
869 }
870
871 if(isModified()) {
872 lastModified = configFile.lastModified();
873 } else if(reloadOnlyIfModified) {
874 return; // asked to reload only if modified. Don't reload since not modified
875 }
876
877 if(configFile.exists()) {
878 debug("Load: " + configFile.getAbsolutePath());
879 clear();
880 try {
881 BufferedReader in = new BufferedReader(new FileReader(configFile));
882 String line = null;
883 while((line = in.readLine()) != null) {
884 String key = null;
885 String value = null;
886 int index = -1;
887 if((index = line.indexOf("=")) != -1 && line.length() >= index + 1) {
888 key = line.substring(0, index);
889 value = line.substring(index + 1);
890 }
891 else {
892 key = line;
893 }
894 put(key, value);
895 }
896
897 in.close();
898 }
899 catch (Exception error) {
900 error.printStackTrace();
901 }
902 }
903 else {
904 debug(configFile.getAbsolutePath() + " cannot be found!");
905 }
906 }
907
908 /** Restore the autoenter value to its initial value, and remove url if present. */
909 public void restore() {
910 if(configFile != null) {
911 // Delete the file
912 //configFile.delete();
913
914 // Not restoring nor deleting here. Just removing the URL (which indicates a running server),
915 // so that the file's state indicates the server has stopped, and then saving the property file.
916 // Should all properties not defined in the llssite.cfg.in template be removed below?
917 String urlPropertyName = isIndependentGSI() ? GSI_URL : URL;
918 remove(urlPropertyName);
919
920 remove("gsdlhome");
921 remove("collecthome");
922 remove("gdbmhome");
923 remove("logfilename");
924
925 // For some reason launching GLI with server.exe clobbers autoenter and startbrowser
926 // values for independent GSI in llssite.cfg file, and gli.autoenter and gli.startbrowser.
927 // So set them here.
928 if(get(GSI_AUTOENTER) == null) {
929 put(GSI_AUTOENTER, "0");
930 }
931 if(get(GSI_STARTBROWSER) == null) {
932 put(GSI_STARTBROWSER, "1");
933 }
934 if(get(AUTOENTER) == null) {
935 put(AUTOENTER, "1");
936 }
937 if(get(STARTBROWSER) == null) {
938 put(STARTBROWSER, "0");
939 }
940 save();
941 }
942 else {
943 String urlPropertyName = isIndependentGSI() ? GSI_URL : URL;
944 debug("Restore Initial Settings");
945 put(AUTOENTER, autoenter_initial);
946 put(STARTBROWSER, start_browser_initial);
947 remove(urlPropertyName);
948 save();
949 }
950 }
951
952 public void set() {
953 debug("Set Session Settings");
954 if(autoenter_initial == null) {
955 autoenter_initial = (String) get(AUTOENTER);
956 debug("Remember autoenter was: " + autoenter_initial);
957 }
958 put(AUTOENTER, TRUE);
959 if(start_browser_initial == null) {
960 start_browser_initial = (String) get(STARTBROWSER);
961 debug("Remember start_browser was: " + start_browser_initial);
962 }
963 put(STARTBROWSER, FALSE);
964 save();
965 }
966
967 private void debug(String message) {
968 ///ystem.err.println(message);
969 }
970
971 private void save() {
972 debug("Save: " + configFile.getAbsolutePath());
973 try {
974 BufferedWriter out = new BufferedWriter(new FileWriter(configFile, false));
975 for(Iterator keys = keySet().iterator(); keys.hasNext(); ) {
976 String key = (String) keys.next();
977 String value = (String) get(key);
978 out.write(key, 0, key.length());
979 if(value != null) {
980 out.write('=');
981
982 // if the GSI was launched outside of GLI, don't overwrite its default
983 // autoenter and startbrowser values
984 if(isIndependentGSI && (key == GSI_AUTOENTER || key == GSI_STARTBROWSER)) {
985 if(key == GSI_AUTOENTER) {
986 out.write(autoenter_initial, 0, autoenter_initial.length());
987 } else { // GSI_STARTBROWSER
988 out.write(start_browser_initial, 0, start_browser_initial.length());
989 }
990 } else {
991 out.write(value, 0, value.length());
992 }
993 }
994 out.newLine();
995 }
996 out.flush();
997 out.close();
998 }
999 catch (Exception error) {
1000 error.printStackTrace();
1001 }
1002 }
1003
1004 private static void copyConfigFile(File source_cfg, File dest_cfg, boolean setToGliSiteDefaults) {
1005 // source_cfg file should exist
1006 // dest_cfg file should not yet exist
1007 // If setToGliSiteDefaults is true, then GLIsite.cfg's default configuration
1008 // is applied to concerned lines: gli.autoenter=1, and gli.startbrowser=0
1009
1010 try {
1011 BufferedReader in = new BufferedReader(new FileReader(source_cfg));
1012 BufferedWriter out = new BufferedWriter(new FileWriter(dest_cfg, false));
1013
1014 String line = null;
1015 while((line = in.readLine()) != null) {
1016
1017 if(setToGliSiteDefaults) {
1018 if(line.startsWith(AUTOENTER)) {
1019 line = AUTOENTER+"=1";
1020 }
1021 else if(line.startsWith(STARTBROWSER)) {
1022 line = STARTBROWSER+"=0";
1023 }
1024 }
1025
1026 // write out the line
1027 out.write(line);
1028 out.newLine();
1029 }
1030
1031 out.flush();
1032 in.close();
1033 out.close();
1034 } catch(Exception e) {
1035 System.err.println("Exception occurred when trying to copy the config file "
1036 + source_cfg.getName() + " to " + dest_cfg.getName() + ": " + e);
1037 e.printStackTrace();
1038 }
1039 }
1040 }
1041}
Note: See TracBrowser for help on using the repository browser.