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

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

All comments referring to glisite.cfg edited to refer to llssite.cfg alone as necessary

  • Property svn:keywords set to Author Date Id Revision
File size: 34.9 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 else {
915 String urlPropertyName = isIndependentGSI() ? GSI_URL : URL;
916 debug("Restore Initial Settings");
917 put(AUTOENTER, autoenter_initial);
918 put(STARTBROWSER, start_browser_initial);
919 remove(urlPropertyName);
920 save();
921 }
922 }
923
924 public void set() {
925 debug("Set Session Settings");
926 if(autoenter_initial == null) {
927 autoenter_initial = (String) get(AUTOENTER);
928 debug("Remember autoenter was: " + autoenter_initial);
929 }
930 put(AUTOENTER, TRUE);
931 if(start_browser_initial == null) {
932 start_browser_initial = (String) get(STARTBROWSER);
933 debug("Remember start_browser was: " + start_browser_initial);
934 }
935 put(STARTBROWSER, FALSE);
936 save();
937 }
938
939 private void debug(String message) {
940 ///ystem.err.println(message);
941 }
942
943 private void save() {
944 debug("Save: " + configFile.getAbsolutePath());
945 try {
946 BufferedWriter out = new BufferedWriter(new FileWriter(configFile, false));
947 for(Iterator keys = keySet().iterator(); keys.hasNext(); ) {
948 String key = (String) keys.next();
949 String value = (String) get(key);
950 out.write(key, 0, key.length());
951 if(value != null) {
952 out.write('=');
953
954 // if the GSI was launched outside of GLI, don't overwrite its default
955 // autoenter and startbrowser values
956 if(isIndependentGSI && (key == GSI_AUTOENTER || key == GSI_STARTBROWSER)) {
957 if(key == GSI_AUTOENTER) {
958 out.write(autoenter_initial, 0, autoenter_initial.length());
959 } else { // GSI_STARTBROWSER
960 out.write(start_browser_initial, 0, start_browser_initial.length());
961 }
962 } else {
963 out.write(value, 0, value.length());
964 }
965 }
966 out.newLine();
967 }
968 out.flush();
969 out.close();
970 }
971 catch (Exception error) {
972 error.printStackTrace();
973 }
974 }
975
976 private static void copyConfigFile(File source_cfg, File dest_cfg, boolean setToGliSiteDefaults) {
977 // source_cfg file should exist
978 // dest_cfg file should not yet exist
979 // If setToGliSiteDefaults is true, then GLIsite.cfg's default configuration
980 // is applied to concerned lines: gli.autoenter=1, and gli.startbrowser=0
981
982 try {
983 BufferedReader in = new BufferedReader(new FileReader(source_cfg));
984 BufferedWriter out = new BufferedWriter(new FileWriter(dest_cfg, false));
985
986 String line = null;
987 while((line = in.readLine()) != null) {
988
989 if(setToGliSiteDefaults) {
990 if(line.startsWith(AUTOENTER)) {
991 line = AUTOENTER+"=1";
992 }
993 else if(line.startsWith(STARTBROWSER)) {
994 line = STARTBROWSER+"=0";
995 }
996 }
997
998 // write out the line
999 out.write(line);
1000 out.newLine();
1001 }
1002
1003 out.flush();
1004 in.close();
1005 out.close();
1006 } catch(Exception e) {
1007 System.err.println("Exception occurred when trying to copy the config file "
1008 + source_cfg.getName() + " to " + dest_cfg.getName() + ": " + e);
1009 e.printStackTrace();
1010 }
1011 }
1012 }
1013}
Note: See TracBrowser for help on using the repository browser.