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

Last change on this file since 22806 was 22806, checked in by ak19, 14 years ago

Further changes to ticket 152 (movable collectdir). Need to deal with GLI being started and reading in a non-standard collectdir from config files (stored from a previous GLI session) that now no longer exists. In this case need to revert back to the default Greenstone collectdir. Tested on Windows with the included Apache webserver and server.exe

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