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

Last change on this file since 23432 was 23432, checked in by ak19, 13 years ago

Helpful message when the port is already in use, instead of the MissingGSDL dialog appearing cryptically due to reasons not immediately apparent.

  • Property svn:keywords set to Author Date Id Revision
File size: 35.2 KB
Line 
1/**
2/**
3 *############################################################################
4 * A component of the Greenstone Librarian Interface, part of the Greenstone
5 * digital library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
9 *
10 * Copyright (C) 2004 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 */
27
28package org.greenstone.gatherer.greenstone;
29
30
31import java.io.*;
32import java.lang.*;
33import java.net.*;
34import java.util.*;
35import javax.swing.*;
36import org.greenstone.gatherer.Configuration;
37import org.greenstone.gatherer.DebugStream;
38import org.greenstone.gatherer.Dictionary;
39import org.greenstone.gatherer.Gatherer;
40import org.greenstone.gatherer.util.PortFinder;
41import org.greenstone.gatherer.util.Utility;
42
43
44public class LocalLibraryServer
45{
46 static final private int WAITING_TIME = 20; // number of seconds to wait for the server to start and stop
47
48 static final private String ADD_COMMAND = "?a=config&cmd=add-collection&c=";
49 static final private String RELEASE_COMMAND = "?a=config&cmd=release-collection&c=";
50 static final private String QUIT_COMMAND = "?a=config&cmd=kill";
51 static final private String RESTART_COMMAND = "?a=config&cmd=restart";
52
53 static private LLSSiteConfig llssite_cfg_file = null;
54 static private File local_library_server_file = null;
55
56 static private boolean running = false;
57 static private String ID = "greenstone-server"; // a sort of process ID
58
59 // Need to use sockets to tell the server program to terminate when on Linux
60 // The socket port number that we will use to communicate the termination
61 static private int port;
62 static private Socket clientSocket = null;
63 static private Writer clientSocketWriter = null;
64
65 // The server is persistent if it does not have to reload all the values
66 // over and over again each time. Tomcat is persistent and fastcgi is too,
67 // but the Apache webserver is not persistent by default.
68 // Change the initialisation of this value depending on whether fastcgi is
69 // on. At the moment, this does not apply to the Apache local library server.
70 static private boolean isPersistentServer = false;
71
72 static public boolean isPersistentServer() {
73 return isPersistentServer;
74 }
75
76 static public void addCollection(String collection_name)
77 {
78 if (isPersistentServer) {
79 config(ADD_COMMAND + collection_name);
80 }
81 }
82
83
84 // Used to send messages to the local library
85 static private void config(String command)
86 {
87 if (!isPersistentServer) {
88 return;
89 }
90 if (Configuration.library_url == null) {
91 System.err.println("Error: Trying to configure local library with null Configuration.library_url!");
92 return;
93 }
94
95 try {
96 URL url = new URL(Configuration.library_url.toString() + command);
97 HttpURLConnection library_connection = (HttpURLConnection) url.openConnection();
98
99 // It's very important that we read the output of the command
100 // This ensures that the command has actually finished
101 // (The response code is returned immediately)
102 InputStream library_is = library_connection.getInputStream();
103 BufferedReader library_in = new BufferedReader(new InputStreamReader(library_is, "UTF-8"));
104 String library_output_line = library_in.readLine();
105 while (library_output_line != null) {
106 DebugStream.println("Local library server output: " + library_output_line);
107 library_output_line = library_in.readLine();
108 }
109 library_in.close();
110
111 int response_code = library_connection.getResponseCode();
112 if (response_code >= HttpURLConnection.HTTP_OK && response_code < HttpURLConnection.HTTP_MULT_CHOICE) {
113 DebugStream.println("200 - Complete.");
114 }
115 else {
116 DebugStream.println("404 - Failed.");
117 }
118 }
119 catch (Exception exception) {
120 DebugStream.printStackTrace(exception);
121 }
122 }
123
124 // Used to send messages to the local library server wrapper to the Apache web server (server.jar)
125 static private boolean sendMessageToServer(String message) {
126 if(isPersistentServer) {
127 return false;
128 }
129
130 if(port == -1) {
131 return false;
132 }
133
134 try {
135 if(clientSocket == null) {
136 clientSocket = new Socket("localhost", port);
137 }
138 if(clientSocketWriter == null) {
139 clientSocketWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
140 }
141 clientSocketWriter.write(message);
142 clientSocketWriter.flush();
143
144 } catch (Exception e) {
145 System.err.println("An exception occurred when trying to send the message: " + message
146 + "\nto the LocalLibraryServer.\n" + e);
147 return false;
148 }
149 return true;
150 }
151
152 static public boolean isRunning()
153 {
154 if (!running) return false; // if the url is pending, then running would also be false (server not started up yet)
155
156 llssite_cfg_file.load(true);
157 String url = llssite_cfg_file.getURL();
158 if (url == null) return false;
159
160 // Called by Gatherer to check whether we need to stop the server.
161 // if the url is pending, then the GSI hasn't started the server up yet
162 // Already covered in !running
163 //if (url.equals(LLSSiteConfig.URL_PENDING)) return false;
164
165 return true;
166 }
167
168 /** collection name can be a group-qualified collect name */
169 static public void releaseCollection(String collection_name)
170 {
171 if (isPersistentServer) {
172 config(RELEASE_COMMAND + collection_name);
173 }
174 }
175
176 static public boolean start(String gsdl_path, String local_library_server_file_path)
177 {
178 // Check the local library server file (server.exe or gs2-server.sh) exists
179 if(local_library_server_file_path == null) {
180 return false;
181 }
182 local_library_server_file = new File(local_library_server_file_path);
183 if (local_library_server_file.exists()) {
184 if(local_library_server_file.getName().equals("server.exe")) {
185 isPersistentServer = true;
186 } // else it may be gs2-web-server.bat
187 }
188 else { // local_library_server_file does not exist
189 DebugStream.println("No local library at given file path.");
190
191 if(Utility.isWindows()) { // test for server.exe and gs2-web-server.bat
192 local_library_server_file = new File(gsdl_path + "server.exe");
193 if (local_library_server_file.exists()) {
194 isPersistentServer = true;
195 } else {
196 local_library_server_file = new File(gsdl_path + "gs2-web-server.bat");
197 if (!local_library_server_file.exists()) {
198 DebugStream.println("No local library at all.");
199 return false;
200 }
201 }
202 } else { // linux
203 local_library_server_file = new File(gsdl_path + "gs2-server.sh");
204 if (!local_library_server_file.exists()) {
205 DebugStream.println("No local library at all.");
206 return false;
207 }
208 }
209 }
210
211 if(!isPersistentServer) {
212 // In the case of the Local Library Server on Linux or on Win where there's no server.exe, do an extra test:
213 // If GS2 was not configured with --enable-apache-httpd, then there is no apache webserver folder,
214 // even though the gs2-server.sh file would still be there. That means if the folder is absent
215 // we still have no local library server.
216
217 File localServerFolder = new File(gsdl_path, "apache-httpd");
218 if (!localServerFolder.exists() && !localServerFolder.isDirectory()) {
219 DebugStream.println("The web server does not exist at "
220 + localServerFolder.getAbsolutePath() + "\nNo local library at all. Trying web library");
221 return false;
222 } // else apache-httpd folder exists
223 }
224
225 llssite_cfg_file = new LLSSiteConfig(local_library_server_file);
226 if(!llssite_cfg_file.isConfigFileSet()) {
227 return false;
228 }
229
230 // from now on return true: we're in local_library_mode (even if the server is not running)
231
232
233 // If the user launched the GSI independent of GLI, but user has not pressed
234 // Enter Library yet, then we will obtain the previewURL later.
235 if(LocalLibraryServer.isURLPending()) {
236 // running is still false when the URL is pending because only GSI is running, not the server
237 return true;
238 } else if(llssite_cfg_file.isIndependentGSI()) {
239 // there is a url, it's not pending, and it is llssite.cfg: meaning GSI has started up
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 glisite_cfg 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 = " " + 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 ConfigFile, check the other configfile for a URL
585 // to see if the server was restarted using that file.
586 // Otherwise need to restart the server again with GLIsite.cfg
587 llssite_cfg_file.save(); // save the configfile, because we may be reloading another
588
589 if(llssite_cfg_file.usingLLS_configFile()) { // if a GSI is already using llssite_cfg, this would have loaded it in
590 url = llssite_cfg_file.getURL(); //if(isURLPending()) {
591 if(url.equals(LLSSiteConfig.URL_PENDING)) {
592 running = false;
593 } else {
594 running = true;
595 }
596 return false; // don't need to launch the server, one has been independently launched
597 } else {
598 // else we try using the glisite configfile
599 llssite_cfg_file.useGLISiteCfg(local_library_server_file);
600 //llssite_cfg_file.set();
601
602 // since we're going to restart the server, make sure to reset all
603 // the client socket and its writer (for communicating with the web server)
604 // will only be reinstantiated if they are first nulled
605 if(clientSocket != null) {
606 clientSocket = null;
607 }
608 if(clientSocketWriter != null) {
609 try{
610 clientSocketWriter.close();
611 clientSocketWriter = null;
612 } catch(Exception e) {
613 System.err.println("Unable to close the client socket outputstream.");
614 } finally {
615 clientSocketWriter = null;
616 }
617 }
618
619 // Spawn local library server process
620 running = false;
621 final String QUOTES = Utility.isWindows() ? "\"" : ""; // need to embed path in quotes on Windows for spaces (interferes on Linux)
622 String local_library_server_command = QUOTES+local_library_server_file.getAbsolutePath()+QUOTES + getExtraLaunchArguments(llssite_cfg_file);
623 if(Utility.isWindows() && !isPersistentServer) { // launching gs2-web-server.bat (Windows) needs cmd start
624 local_library_server_command = "cmd.exe /c start \"GSI\" " + local_library_server_command;
625 }
626 Gatherer.spawnApplication(local_library_server_command, ID);
627 try {
628 testServerRunning(); // don't return until the webserver is up and running
629 serverRestarted = true;
630 } catch (IOException bad_url_connection) {
631 DebugStream.println("Can't connect to server on address " + Configuration.library_url);
632 running = false;
633 }
634 }
635 }
636 return serverRestarted;
637 }
638
639 static private class OneSecondWait
640 {
641 public OneSecondWait()
642 {
643 synchronized(this) {
644 try {
645 wait(1000);
646 }
647 catch (InterruptedException exception) {
648 }
649 }
650 }
651 }
652
653
654 static public class LLSSiteConfig
655 extends LinkedHashMap
656 {
657 private File configFile;
658
659 private File llssite_cfg;
660 private File glisite_cfg;
661 private String autoenter_initial;
662 private String start_browser_initial;
663
664 private long lastModified = 0;
665
666 static final private String AUTOENTER = "autoenter";
667 static final private String COLON = ":";
668 static final private String ENTERLIB = "enterlib";
669 static final private String FALSE = "0";
670 static final private String GLISITE_CFG = "glisite.cfg";
671 static final private String GSDL = "greenstone"; // httpprefix is no longer /gsdl but /greenstone
672 static final private String LLSSITE_CFG = "llssite.cfg";
673 static final private String LOCAL_HOST = "http://localhost";
674 static final private String PORTNUMBER = "portnumber";
675 static final private String SEPARATOR = "/";
676 static final private String SPECIFIC_CONFIG = "--config=";
677 static final private String STARTBROWSER = "start_browser";
678 static final private String TRUE = "1";
679 static final private String URL = "url";
680 static final private String COLLECTHOME = "collecthome";
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 llssite_cfg = new File(server_exe.getParentFile(), LLSSITE_CFG);
689 glisite_cfg = new File(server_exe.getParentFile(), GLISITE_CFG);
690
691 configFile = null;
692
693 autoenter_initial = null;
694 start_browser_initial = null;
695
696 // first test if server was started independently of GLI
697 // if so, the config file we'd be using would be llssite.cfg
698 if(!usingLLS_configFile()) { // if we were using llssite_cfg, this would have loaded it in
699 // else we try using the glisite configfile
700 useGLISiteCfg(server_exe);
701 }
702
703 // GS2. We're in the constructor, so we'll be running the LLS the first time
704 // Set the correct collectdir (from last time) before the server is started up
705
706 String orig_collection_path = Configuration.getString("general.open_collection_gs2", true);
707 String collectDir = Gatherer.getCollectDirectoryPath(); // Gatherer would've set this up
708 String defaultColDir = Gatherer.getDefaultGSCollectDirectoryPath(true); // with file separator at end
709
710 if(orig_collection_path.equals("")) { // default GS collect dir path
711 return;
712 }
713
714 if (!orig_collection_path.startsWith(collectDir) // if coldir would've been changed on startup OR if coldir is non-standard collect folder
715 || !collectDir.equals(defaultColDir))
716 {
717 // if we're running *server.exe* and if the current collect dir at Local Lib's startup is
718 // anything other than the default GS collect dir or if we changed back to the default collect
719 // dir because the non-standard collectDir didn't exist/wasn't specified in the GLI config
720 // file, then write out the new collectDir (minus file separator at end) to the lls site conf in use
721 // Regardless of what collecthome value was in the llssite/glisite file, we end up resetting it here
722 if (isPersistentServer) { // server.exe, so we're dealing with a local GS2
723 put(COLLECTHOME, collectDir);
724 save();
725 lastModified = configFile.lastModified();
726 }
727 } // now the correct current collect dir will get loaded when the server is started up hereafter
728 }
729
730 /** Tries to get a glisite.cfg file and then loads it, setting it as the configFile */
731 public void useGLISiteCfg(File server_exe)
732 {
733 if(!glisite_cfg.exists()) { // create it from the templates or the llssite.cfg file
734
735 File llssite_cfg_in = new File(server_exe.getParentFile(), LLSSITE_CFG+".in");
736 File glisite_cfg_in = new File(server_exe.getParentFile(), GLISITE_CFG+".in");
737
738 // need to generate glisite_cfg from glisite_cfg_in, llssite_cfg or llssite.cfg.in
739 if(glisite_cfg_in.exists()) {
740 copyConfigFile(glisite_cfg_in, glisite_cfg, false);
741 }
742 else if(llssite_cfg_in.exists()) {
743 copyConfigFile(llssite_cfg_in, glisite_cfg_in, true); // adjust for glisite.cfg
744 copyConfigFile(glisite_cfg_in, glisite_cfg, false);
745 }
746 else if(llssite_cfg.exists()) {
747 copyConfigFile(llssite_cfg, glisite_cfg, true); // adjust for glisite.cfg
748 }
749 else {
750 debug("Neither the file glisite.cfg nor llssite.cfg can be found!");
751 }
752 }
753 // use the config file now
754 if(glisite_cfg.exists()) {
755 configFile = glisite_cfg;
756 load(false); // force reload
757 lastModified = configFile.lastModified();
758 }
759 }
760
761 /** Tests whether the server interface is up, running independently of GLI
762 * If so, we don't need to launch the server interface.
763 * The server interface may not have started up the server itself though
764 * (in which case the server URL would be URL_PENDING).
765 * This method returns true if the server interface has already started
766 * and, if so, it would have loaded in the llssite_cfg configFile.
767 */
768 public boolean usingLLS_configFile() {
769 if(!llssite_cfg.exists()) {
770 return false;
771 }
772
773 // Now to check if the configfile contains the URL line
774 configFile = llssite_cfg;
775 load(false); // force load
776
777 if(getURL() == null) {
778 configFile = null;
779 clear(); // we're not using llssite_cfg, so clear the values we just read
780 return false;
781 }
782
783 lastModified = configFile.lastModified();
784 return true;
785 }
786
787 /** To test we've actually instantiated this object meaningfully. If so, then configFile is set */
788 public boolean isConfigFileSet() {
789 return (configFile != null && configFile.exists());
790 }
791
792 /** @return true if GSI was started up independently and outside of GLI.
793 * In such a case, GLI would be using llssite_cfg. */
794 public boolean isIndependentGSI() {
795 return (configFile == llssite_cfg);
796 }
797
798 public boolean exists() {
799 return configFile.exists();
800 }
801
802 public String getLocalHostURL() {
803 StringBuffer url = new StringBuffer(LOCAL_HOST);
804 url.append(COLON);
805 url.append((String)get(PORTNUMBER));
806 String enterlib = (String)get(ENTERLIB);
807 if(!isPersistentServer || enterlib == null || enterlib.length() == 0) {
808 // Use the default /gsdl and hope for the best.
809 url.append(SEPARATOR);
810 url.append(GSDL);
811 }
812 else {
813 if(!enterlib.startsWith(SEPARATOR)) {
814 url.append(SEPARATOR);
815 }
816 url.append(enterlib);
817 }
818 enterlib = null;
819 debug("Found Local Library Address: " + url.toString());
820 return url.toString();
821 }
822
823 /** @return the cmd-line parameter for the configfile used to launch
824 * the server through GLI: --config <glisite.cfg/llssite.cfg file path>. */
825 public String getSiteConfigFilename() {
826 return SPECIFIC_CONFIG + configFile.getAbsolutePath();
827 }
828
829 public String getURL() {
830 // URL is made from url and portnumber
831 String url = (String) get(URL);
832
833 // server interface is already up, independent of GLI
834 // but it has not started the server (hence URL is pending)
835 if(url != null && url.equals(URL_PENDING)) {
836 return url;
837 }
838
839 if(!isPersistentServer) {
840 return url;
841 }
842
843 if(url != null) {
844 StringBuffer temp = new StringBuffer(url);
845 temp.append(COLON);
846 temp.append((String)get(PORTNUMBER));
847 String enterlib = (String)get(ENTERLIB);
848 if(enterlib == null || enterlib.length() == 0) {
849 // Use the default /greenstone prefix and hope for the best.
850 temp.append(SEPARATOR);
851 temp.append(GSDL);
852 }
853 else {
854 if(!enterlib.startsWith(SEPARATOR)) {
855 temp.append(SEPARATOR);
856 }
857 temp.append(enterlib);
858 }
859 enterlib = null;
860 url = temp.toString();
861 }
862 debug("Found Local Library Address: " + url);
863 return url;
864 }
865
866 public void setLastModified() {
867 if(isModified()) {
868 lastModified = configFile.lastModified();
869 }
870 }
871
872 public boolean isModified() {
873 return (lastModified != configFile.lastModified());
874 }
875
876 public void load(boolean reloadOnlyIfModified) {
877
878 if(configFile == null) {
879 debug(configFile.getAbsolutePath() + " cannot be found!");
880 }
881
882 if(isModified()) {
883 lastModified = configFile.lastModified();
884 } else if(reloadOnlyIfModified) {
885 return; // asked to reload only if modified. Don't reload since not modified
886 }
887
888 if(configFile.exists()) {
889 debug("Load: " + configFile.getAbsolutePath());
890 clear();
891 try {
892 BufferedReader in = new BufferedReader(new FileReader(configFile));
893 String line = null;
894 while((line = in.readLine()) != null) {
895 String key = null;
896 String value = null;
897 int index = -1;
898 if((index = line.indexOf("=")) != -1 && line.length() >= index + 1) {
899 key = line.substring(0, index);
900 value = line.substring(index + 1);
901 }
902 else {
903 key = line;
904 }
905 put(key, value);
906 }
907
908 in.close();
909 }
910 catch (Exception error) {
911 error.printStackTrace();
912 }
913 }
914 else {
915 debug(configFile.getAbsolutePath() + " cannot be found!");
916 }
917 }
918
919 /** Restore the autoenter value to its initial value, and remove url if present. */
920 public void restore() {
921 if(configFile != null) {
922 // Delete the file
923 configFile.delete();
924 }
925 else {
926 debug("Restore Initial Settings");
927 put(AUTOENTER, autoenter_initial);
928 put(STARTBROWSER, start_browser_initial);
929 remove(URL);
930 save();
931 }
932 }
933
934 public void set() {
935 debug("Set Session Settings");
936 if(autoenter_initial == null) {
937 autoenter_initial = (String) get(AUTOENTER);
938 debug("Remember autoenter was: " + autoenter_initial);
939 }
940 put(AUTOENTER, TRUE);
941 if(start_browser_initial == null) {
942 start_browser_initial = (String) get(STARTBROWSER);
943 debug("Remember start_browser was: " + start_browser_initial);
944 }
945 put(STARTBROWSER, FALSE);
946 save();
947 }
948
949 private void debug(String message) {
950 ///ystem.err.println(message);
951 }
952
953 private void save() {
954 //debug("Save: " + llssite_cfg.getAbsolutePath());
955 debug("Save: " + configFile.getAbsolutePath());
956 try {
957 //BufferedWriter out = new BufferedWriter(new FileWriter(llssite_cfg, false));
958 BufferedWriter out = new BufferedWriter(new FileWriter(configFile, false));
959 for(Iterator keys = keySet().iterator(); keys.hasNext(); ) {
960 String key = (String) keys.next();
961 String value = (String) get(key);
962 out.write(key, 0, key.length());
963 if(value != null) {
964 out.write('=');
965
966 // if the server is using llssite.cfg, don't overwrite its default
967 // autoenter and startbrowser values
968 if(configFile == llssite_cfg && (key == AUTOENTER || key == STARTBROWSER)) {
969 if(key == AUTOENTER) {
970 out.write(autoenter_initial, 0, autoenter_initial.length());
971 } else { // STARTBROWSER
972 out.write(start_browser_initial, 0, start_browser_initial.length());
973 }
974 } else {
975 out.write(value, 0, value.length());
976 }
977 }
978 out.newLine();
979 }
980 out.flush();
981 out.close();
982 }
983 catch (Exception error) {
984 error.printStackTrace();
985 }
986 }
987
988 private static void copyConfigFile(File source_cfg, File dest_cfg, boolean setToGliSiteDefaults) {
989 // source_cfg file should exist
990 // dest_cfg file should not yet exist
991 // If setToGliSiteDefaults is true, then GLIsite.cfg's default configuration
992 // is applied to concerned lines: autoenter=1, and startbrowser=0
993
994 try {
995 BufferedReader in = new BufferedReader(new FileReader(source_cfg));
996 BufferedWriter out = new BufferedWriter(new FileWriter(dest_cfg, false));
997
998 String line = null;
999 while((line = in.readLine()) != null) {
1000
1001 if(setToGliSiteDefaults) {
1002 if(line.startsWith(AUTOENTER)) {
1003 line = AUTOENTER+"=1";
1004 }
1005 else if(line.startsWith(STARTBROWSER)) {
1006 line = STARTBROWSER+"=0";
1007 }
1008 }
1009
1010 // write out the line
1011 out.write(line);
1012 out.newLine();
1013 }
1014
1015 out.flush();
1016 in.close();
1017 out.close();
1018 } catch(Exception e) {
1019 System.err.println("Exception occurred when trying to copy the config file "
1020 + source_cfg.getName() + " to " + dest_cfg.getName() + ": " + e);
1021 e.printStackTrace();
1022 }
1023 }
1024 }
1025}
Note: See TracBrowser for help on using the repository browser.