/** *############################################################################ * A component of the Greenstone Librarian Interface, part of the Greenstone * digital library suite from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ * * Copyright (C) 2004 New Zealand Digital Library Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *############################################################################ */ package org.greenstone.gatherer.greenstone; import java.io.*; import java.lang.*; import java.net.*; import java.util.*; import javax.swing.*; import org.greenstone.gatherer.Configuration; import org.greenstone.gatherer.DebugStream; import org.greenstone.gatherer.Dictionary; import org.greenstone.gatherer.Gatherer; import org.greenstone.gatherer.util.PortFinder; import org.greenstone.gatherer.util.SafeProcess; import org.greenstone.gatherer.util.Utility; public class LocalLibraryServer { static final private int WAITING_TIME = 20; // number of seconds to wait for the server to start and stop static final private String ADD_COMMAND = "?a=config&cmd=add-collection&c="; static final private String RELEASE_COMMAND = "?a=config&cmd=release-collection&c="; static final private String QUIT_COMMAND = "?a=config&cmd=kill"; static final private String RESTART_COMMAND = "?a=config&cmd=restart"; static private LLSSiteConfig llssite_cfg_file = null; static private File local_library_server_file = null; static private boolean running = false; static private String ID = "greenstone-server"; // a sort of process ID // Need to use sockets to tell the server program to terminate when on Linux // The socket port number that we will use to communicate the termination static private int port; static private Socket clientSocket = null; static private Writer clientSocketWriter = null; // The server is persistent if it does not have to reload all the values // over and over again each time. Tomcat is persistent and fastcgi is too, // but the Apache webserver is not persistent by default. // Change the initialisation of this value depending on whether fastcgi is // on. At the moment, this does not apply to the Apache local library server. static private boolean isPersistentServer = false; static public boolean isPersistentServer() { return isPersistentServer; } static public void addCollection(String collection_name) { if (isPersistentServer) { config(ADD_COMMAND + collection_name); } } // Used to send messages to the local library static private void config(String command) { if (!isPersistentServer) { return; } if (Configuration.library_url == null) { System.err.println("Error: Trying to configure local library with null Configuration.library_url!"); return; } try { URL url = new URL(Configuration.library_url.toString() + command); HttpURLConnection library_connection = (HttpURLConnection) url.openConnection(); // It's very important that we read the output of the command // This ensures that the command has actually finished // (The response code is returned immediately) InputStream library_is = library_connection.getInputStream(); BufferedReader library_in = new BufferedReader(new InputStreamReader(library_is, "UTF-8")); String library_output_line = library_in.readLine(); while (library_output_line != null) { DebugStream.println("Local library server output: " + library_output_line); library_output_line = library_in.readLine(); } library_in.close(); int response_code = library_connection.getResponseCode(); if (response_code >= HttpURLConnection.HTTP_OK && response_code < HttpURLConnection.HTTP_MULT_CHOICE) { DebugStream.println("200 - Complete."); } else { DebugStream.println("404 - Failed."); } } catch (Exception exception) { DebugStream.printStackTrace(exception); } } // Used to send messages to the local library server wrapper to the Apache web server (server.jar) static private boolean sendMessageToServer(String message) { if(isPersistentServer) { return false; } if(port == -1) { return false; } try { if(clientSocket == null) { clientSocket = new Socket("localhost", port); } if(clientSocketWriter == null) { clientSocketWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())); } clientSocketWriter.write(message); clientSocketWriter.flush(); } catch (Exception e) { System.err.println("An exception occurred when trying to send the message: " + message + "\nto the LocalLibraryServer.\n" + e); return false; } return true; } static public boolean isRunning() { if (!running) return false; // if the url is pending, then running would also be false (server not started up yet) llssite_cfg_file.load(true); String url = llssite_cfg_file.getURL(); if (url == null) return false; // Called by Gatherer to check whether we need to stop the server. // if the url is pending, then the GSI hasn't started the server up yet // Already covered in !running //if (url.equals(LLSSiteConfig.URL_PENDING)) return false; return true; } /** collection name can be a group-qualified collect name */ static public void releaseCollection(String collection_name) { if (isPersistentServer) { config(RELEASE_COMMAND + collection_name); } } static public boolean start(String gsdl_path, String local_library_server_file_path) { // Check the local library server file (server.exe or gs2-server.sh) exists if(local_library_server_file_path == null) { return false; } local_library_server_file = new File(local_library_server_file_path); if (local_library_server_file.exists()) { if(local_library_server_file.getName().equals("server.exe")) { isPersistentServer = true; } // else it may be gs2-web-server.bat } else { // local_library_server_file does not exist DebugStream.println("No local library at given file path."); if(Utility.isWindows()) { // test for server.exe and gs2-web-server.bat local_library_server_file = new File(gsdl_path + "server.exe"); if (local_library_server_file.exists()) { isPersistentServer = true; } else { local_library_server_file = new File(gsdl_path + "gs2-web-server.bat"); if (!local_library_server_file.exists()) { DebugStream.println("No local library at all."); return false; } } } else { // linux local_library_server_file = new File(gsdl_path + "gs2-server.sh"); if (!local_library_server_file.exists()) { DebugStream.println("No local library at all."); return false; } } } if(!isPersistentServer) { // In the case of the Local Library Server on Linux or on Win where there's no server.exe, do an extra test: // If GS2 was not configured with --enable-apache-httpd, then there is no apache webserver folder, // even though the gs2-server.sh file would still be there. That means if the folder is absent // we still have no local library server. File localServerFolder = new File(gsdl_path, "apache-httpd"); if (!localServerFolder.exists() && !localServerFolder.isDirectory()) { DebugStream.println("The web server does not exist at " + localServerFolder.getAbsolutePath() + "\nNo local library at all. Trying web library"); return false; } // else apache-httpd folder exists } llssite_cfg_file = new LLSSiteConfig(local_library_server_file); if(!llssite_cfg_file.isConfigFileSet()) { return false; } // from now on return true: we're in local_library_mode (even if the server is not running) // If the user launched the GSI independent of GLI, but user has not pressed // Enter Library yet, then we will obtain the previewURL later. if(LocalLibraryServer.isURLPending()) { // running is still false when the URL is pending because only GSI is running, not the server return true; } else if(llssite_cfg_file.isIndependentGSI()) { // There is already a url and it's not pending: meaning the server // has started up and that GSI was launched outside of GLI running = true; return true; } // Spawn local library server process final String QUOTES = Utility.isWindows() ? "\"" : ""; // need to embed path in quotes on Windows for spaces (interferes on Linux) String local_library_server_command = QUOTES+local_library_server_file.getAbsolutePath()+QUOTES + getExtraLaunchArguments(llssite_cfg_file); if(Utility.isWindows() && !isPersistentServer) { // launching gs2-web-server.bat (Windows) needs cmd start local_library_server_command = "cmd.exe /c start \"GSI\" " + local_library_server_command; } // Check if the server is already running String url = llssite_cfg_file.getURL(); if (url != null) { // If it is already running then set the Greenstone web server address and we're done // E.g. if previously GLI was not properly shut down, the URL property (signifying // the server is still running) would still be in the config file. try { Configuration.library_url = new URL(url); running = true; // Run the server interface Gatherer.spawnApplication(local_library_server_command, ID); return true; } catch (MalformedURLException exception) { DebugStream.printStackTrace(exception); } } // Configure the server for immediate entry //llssite_cfg_file.set(); // Spawn local library server process Gatherer.spawnApplication(local_library_server_command, ID); // Wait until program has started try { //System.err.println("**** testing server..."); testServerRunning(); // will set running = true when the server is up and running successfully //System.err.println("**** Is server running: " + running); } catch (IOException bad_url_connection) { try { // If this fails then we try changing the url to be localhost Configuration.library_url = new URL(llssite_cfg_file.getLocalHostURL()); DebugStream.println("Try connecting to server on local host: '" + Configuration.library_url + "'"); URLConnection connection = Configuration.library_url.openConnection(); connection.getContent(); running = true; } catch (IOException worse_url_connection) { DebugStream.println("Can't connect to server on either address."); Configuration.library_url = null; running = false; } } return true; } /** Call this when the collect directory has changed. Only works when using * the web server launched by GLI. */ static public void reconfigure() { if(isPersistentServer) { // 1st: server may have nulled URL if server was stopped inbetween, // so load that new URL, if GLI conf file modified // Then put the new collectDir into the GLI configfile being used llssite_cfg_file.load(true); String collectDir = Gatherer.getCollectDirectoryPath(); collectDir = collectDir.substring(0, collectDir.length()-1); // remove file separator at end llssite_cfg_file.put(LLSSiteConfig.COLLECTHOME, collectDir); llssite_cfg_file.save(); // tell the server to restart, so it will read the new configuration // (1) need a server to be running in order for us to send a restart message to it if(checkServerRunning()) { // if true, it wasn't running before, but has now restarted the server. We're done return; } // (2) otherwise the server may already have been running, need to tell it to restart after setting the collect dir if(running) { config(RESTART_COMMAND); } return; } // can't control the GSI/server if it was launched independent of GLI if(llssite_cfg_file.isIndependentGSI()) { JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.Reconfigure"), Dictionary.get("General.Reconfigure"), JOptionPane.INFORMATION_MESSAGE); return; } // someone may have closed the web server if(checkServerRunning()) { // need a server to be running in order for us to send a reconfigure message to it return; // it has reconfigured and restarted the server } // If it was already running, tell the server a reconfigure is required on next restart // and then restart if(running && sendMessageToServer("RECONFIGURE\n")) { // restart if(running) { running = false; if(sendMessageToServer("RESTART\n")) { //if(sendMessageToServer("RECONFIGURE\n")) { // wait for the server to update the URL in the gli config file llssite_cfg_file.setLastModified(); int attempt_count = 0; while (!llssite_cfg_file.isModified()) { new OneSecondWait(); // Wait one second (give or take) attempt_count++; // After waiting for the specified time, ask the user whether they want to wait for that long again if (attempt_count == WAITING_TIME) { break; // can't be waiting forever, we'll be waiting again below } } try { testServerRunning(); // will set running = true when the server is up and running successfully } catch (IOException bad_url_connection) { try { // If this fails then we try changing the url to be localhost Configuration.library_url = new URL(llssite_cfg_file.getLocalHostURL()); DebugStream.println("Try connecting to server on local host: '" + Configuration.library_url + "'"); URLConnection connection = Configuration.library_url.openConnection(); connection.getContent(); running = true; } catch (IOException worse_url_connection) { DebugStream.println("Can't connect to server on either address."); Configuration.library_url = null; running = false; } } } } } else { System.err.println("GLI was unable to send a reconfigure request to the local library server." + "\nPlease reconfigure and restart the local Greenstone server manually."); } } static public void stop() { if (!running) { // also the case if the URL is pending in an independently launched GSI return; } // don't (can't) shutdown the GSI/server if it was launched independent of GLI if(llssite_cfg_file.isIndependentGSI()) { return; } // Send the command for it to exit. if (isPersistentServer) { config(QUIT_COMMAND); } else { boolean success = sendMessageToServer("QUIT\n"); try { if(clientSocketWriter != null) { clientSocketWriter.close(); clientSocketWriter = null; } clientSocket = null; } catch(Exception e) { System.err.println("An exception occurred when trying to close the socket" + "\nto the LocalLibraryServer.\n" + e); } if(success) { Gatherer.terminateApplication(ID); } else { System.err.println("Unable to stop the server, since there's no communication port to send the quit msg over." + "\nPlease stop the local Greenstone server manually."); } } // Wait until program has stopped, by reloading and checking the URL field llssite_cfg_file.load(false); int attempt_count = 0; String url = llssite_cfg_file.getURL(); while (url != null && !url.equals(LLSSiteConfig.URL_PENDING)) { // if pending, the server is already stopped (not running) new OneSecondWait(); // Wait one second (give or take) llssite_cfg_file.load(false); attempt_count++; // After waiting for the specified time, ask the user whether they want to wait for that long again if (attempt_count == WAITING_TIME) { int try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.QuitTimeOut", Integer.toString(WAITING_TIME)), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION); if (try_again == JOptionPane.NO_OPTION) { return; } attempt_count = 0; } // read the url again to see if it's updated url = llssite_cfg_file.getURL(); } // Restore the llssite_cfg. llssite_cfg_file.restore(); // If the local server is still running then our changed values will get overwritten. url = llssite_cfg_file.getURL(); if (url != null && !url.equals(LLSSiteConfig.URL_PENDING)) { JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("Server.QuitManual"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE); } running = false; } // This method does the approximate equivalent of util.GSServerThread.stopServer() // On unexpected, unnatural termination of GLI, call this to send the web-stop message the local library server to stop static public void forceStopServer() { SafeProcess p = null; if (Utility.isWindows()) { // cmd /C "cd "C:\path\to\greenstone3" && ant stop" p = new SafeProcess("cmd /C \"cd \"" + Configuration.gsdl_path + File.separator + "\" && gsicontrol.bat web-stop\""); } else { p = new SafeProcess(new String[]{"/bin/bash", "-c", "cd \"" + Configuration.gsdl_path + "\" && ./gsicontrol.sh web-stop"}); } int result = p.runProcess(); if(result == 0) { System.err.println("Successfully stopped GS2 server."); //DebugStream.println("********** SUCCESSFULLY stopped THE GS2 SERVER ON EXIT"); } else { System.err.println("********** FAILED TO SUCCESSFULLY stop THE GS2 SERVER ON EXIT"); } p = null; } static private String getExtraLaunchArguments(LLSSiteConfig site_cfg_file) { String args = " " + LLSSiteConfig.GLIMODE + " " + site_cfg_file.getSiteConfigFilename(); if(isPersistentServer) { return args; } // Else, when running the Local Apache Library Server on Linux/Win, need to provide a port argument try { PortFinder portFinder = new PortFinder(50100, 100); port = portFinder.findPortInRange(false); // silent mode } catch(Exception e) { System.err.println("Exception when trying to find an available port: " + e); port = -1; } return args + " --quitport=" + port; } // This method first tests whether there is a URL in the llssite_cfg_file // and after that appears, it tests whether the URL is functional. static private void testServerRunning() throws IOException { // Wait until program has started, by reloading and checking the URL field llssite_cfg_file.load(false); int attempt_count = 0; while (llssite_cfg_file.getURL() == null) { new OneSecondWait(); // Wait one second (give or take) //System.err.println("**** One Second Wait"); llssite_cfg_file.load(false); attempt_count++; // After waiting for the specified time, ask the user whether they want to wait for that long again if (attempt_count == WAITING_TIME) { int try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("Server.StartUpTimeOut", Integer.toString(WAITING_TIME)), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION); if (try_again == JOptionPane.NO_OPTION) { return; } attempt_count = 0; } } // Ta-da. Now the url should be available try { Configuration.library_url = new URL(llssite_cfg_file.getURL()); } catch (MalformedURLException exception) { DebugStream.printStackTrace(exception); } // A quick test involves opening a connection to get the home page for this collection try { DebugStream.println("Try connecting to server on config url: '" + Configuration.library_url + "'"); URLConnection connection = Configuration.library_url.openConnection(); connection.getContent(); running = true; } catch (IOException bad_url_connection) { System.err.println("Unable to open a connection to " + Configuration.library_url + "\nCheck whether the port may already be in use. If so, change your\n" + "Greenstone port number in the Greenstone Server Interface(GSI)."); throw bad_url_connection; } } /** Returns true if we're waiting on the user to click on Enter Library button * in an independently launched GSI (one not launched by GLI). */ static public boolean isURLPending() { //if(Configuration.library_url != null) { //System.err.println("**** Configuration.library_url: " + Configuration.library_url ); //return false; // don't need to do anything as we already have the url //} llssite_cfg_file.load(true); // don't force reload, load only if modified String url = llssite_cfg_file.getURL(); if(url != null) { if(url.equals(LLSSiteConfig.URL_PENDING)) { running = false; // imagine if they restarted an external GSI return true; } else { // a valid URL at last try { Configuration.library_url = new URL(url); running = true; } catch (MalformedURLException exception) { running = false; exception.printStackTrace(); DebugStream.printStackTrace(exception); } return false; } } // If either the URL is null--which means no independent GSI (Greenstone server interface // app) was launched--or if the 'URL' doesn't say it's pending, then we're not waiting return false; } /** @returns true if it had to restart the server. Returns false if it didn't restart it. */ static public boolean checkServerRunning() { boolean serverRestarted = false; if (!running) return false; // don't worry about it if it's not supposed to be running llssite_cfg_file.load(true); // don't force reload, load only if modified String url = llssite_cfg_file.getURL(); if(url != null) { if(url.equals(LLSSiteConfig.URL_PENDING)) { running = false; return false; } // else, valid URL: try { Configuration.library_url = new URL(url); running = true; } catch (MalformedURLException exception) { running = false; DebugStream.printStackTrace(exception); exception.printStackTrace(); } } else { // NO URL in current mode of configFile, try other mode (e.g. "gli.url") if(llssite_cfg_file.usingGSImode()) { // if a GSI is already using llssite_cfg, this would have loaded it in url = llssite_cfg_file.getURL(); //if(isURLPending()) { if(url.equals(LLSSiteConfig.URL_PENDING)) { running = false; } else { running = true; } return false; // don't need to launch the server, one has been independently launched } else { // else we try using the "gli." prefix to access the url property in the config file llssite_cfg_file.useGLImode(); //llssite_cfg_file.set(); // since we're going to restart the server, make sure to reset all // the client socket and its writer (for communicating with the web server) // will only be reinstantiated if they are first nulled if(clientSocket != null) { clientSocket = null; } if(clientSocketWriter != null) { try{ clientSocketWriter.close(); clientSocketWriter = null; } catch(Exception e) { System.err.println("Unable to close the client socket outputstream."); } finally { clientSocketWriter = null; } } // Spawn local library server process running = false; final String QUOTES = Utility.isWindows() ? "\"" : ""; // need to embed path in quotes on Windows for spaces (interferes on Linux) String local_library_server_command = QUOTES+local_library_server_file.getAbsolutePath()+QUOTES + getExtraLaunchArguments(llssite_cfg_file); if(Utility.isWindows() && !isPersistentServer) { // launching gs2-web-server.bat (Windows) needs cmd start local_library_server_command = "cmd.exe /c start \"GSI\" " + local_library_server_command; } Gatherer.spawnApplication(local_library_server_command, ID); try { testServerRunning(); // don't return until the webserver is up and running serverRestarted = true; } catch (IOException bad_url_connection) { DebugStream.println("Can't connect to server on address " + Configuration.library_url); running = false; } } } return serverRestarted; } static private class OneSecondWait { public OneSecondWait() { synchronized(this) { try { wait(1000); } catch (InterruptedException exception) { } } } } static public class LLSSiteConfig extends LinkedHashMap { private File configFile; private String autoenter_initial; private String start_browser_initial; private long lastModified = 0; private boolean isIndependentGSI; static final private String GLI_PREFIX = "gli"; static final private String GSI_AUTOENTER = "autoenter"; static final private String AUTOENTER = GLI_PREFIX+"."+"autoenter"; static final private String COLON = ":"; static final private String ENTERLIB = "enterlib"; static final private String FALSE = "0"; static final private String GSDL = "greenstone"; // httpprefix is no longer /gsdl but /greenstone static final private String LLSSITE_CFG = "llssite.cfg"; static final private String LOCAL_HOST = "http://localhost"; static final private String PORTNUMBER = "portnumber"; static final private String SEPARATOR = "/"; static final private String SPECIFIC_CONFIG = "--config="; static final private String STARTBROWSER = GLI_PREFIX+"."+"start_browser"; static final private String GSI_STARTBROWSER = "start_browser"; static final private String TRUE = "1"; static final private String URL = GLI_PREFIX+"."+"url"; static final private String GSI_URL = "url"; static final private String COLLECTHOME = "collecthome"; static final private String GLIMODE = "--mode="+GLI_PREFIX; static final public String URL_PENDING = "URL_pending"; public LLSSiteConfig(File server_exe) { debug("New LLSSiteConfig for: " + server_exe.getAbsolutePath()); configFile = new File(server_exe.getParentFile(), LLSSITE_CFG); if(!configFile.exists()) { // create it from the template File llssite_cfg_in = new File(server_exe.getParentFile(), LLSSITE_CFG+".in"); // need to generate llssite_cfg from llssite_cfg_in if(llssite_cfg_in.exists()) { copyConfigFile(llssite_cfg_in, configFile, true); // adjust for gli } else { debug("File llssite.cfg.in can't be found. Can't create llssite.cfg frrom llssite.cfg.in."); } } // use the config file now if(configFile.exists()) { // first test if server was started independently of GLI // if so, the config file we'd be using would be llssite.cfg if(!usingGSImode()) { // this step will try to access the url and other // special properties in the config file using the "gli." prefix. useGLImode(); } } else { System.err.println("**** ERROR. Configfile is null."); configFile = null; } autoenter_initial = null; start_browser_initial = null; // GS2. We're in the constructor, so we'll be running the LLS the first time // Set the correct collectdir (from last time) before the server is started up String orig_collection_path = Configuration.getString("general.open_collection_gs2", true); String collectDir = Gatherer.getCollectDirectoryPath(); // Gatherer would've set this up String defaultColDir = Gatherer.getDefaultGSCollectDirectoryPath(true); // with file separator at end if(orig_collection_path.equals("")) { // default GS collect dir path return; } if (!orig_collection_path.startsWith(collectDir) // if coldir would've been changed on startup OR if coldir is non-standard collect folder || !collectDir.equals(defaultColDir)) { // if we're running *server.exe* and if the current collect dir at Local Lib's startup is // anything other than the default GS collect dir or if we changed back to the default collect // dir because the non-standard collectDir didn't exist/wasn't specified in the GLI config // file, then write out the new collectDir (minus file separator at end) to the lls site conf in use // Regardless of what collecthome value was in the llssite file, we end up resetting it here if (isPersistentServer) { // server.exe, so we're dealing with a local GS2 put(COLLECTHOME, collectDir); save(); lastModified = configFile.lastModified(); } } // now the correct current collect dir will get loaded when the server is started up hereafter } /** Changes the mode to GLI mode (since GSI was not launched independently but by GLI): in this * mode, the "gli." prefix is used to access GLI specific properties from the config file */ public void useGLImode() { isIndependentGSI = false; load(true); // reload if modified } /** Tests whether the server interface is up, running independently of GLI * If so, we don't need to launch the server interface. * The server interface may not have started up the server itself though * (in which case the server URL would be URL_PENDING). * This method returns true if the server interface has already started * and, if so, it would have loaded in the configFile. It sets the mode to * GSI Mode (meaning GSI was launched independently): no prefix is used to * access properties from the config file. */ public boolean usingGSImode() { // Now to check if the configfile contains the GSI_URL line load(false); // force load isIndependentGSI = true; if(getURL() == null) { isIndependentGSI = false; return false; } lastModified = configFile.lastModified(); return true; } /** To test we've actually instantiated this object meaningfully. If so, then configFile is set */ public boolean isConfigFileSet() { return (configFile != null && configFile.exists()); } /** @return true if GSI was started up independently and outside of GLI. * In such a case, GLI would be using llssite_cfg. */ public boolean isIndependentGSI() { return isIndependentGSI; } public boolean exists() { return configFile.exists(); } public String getLocalHostURL() { StringBuffer url = new StringBuffer(LOCAL_HOST); url.append(COLON); url.append((String)get(PORTNUMBER)); String enterlib = (String)get(ENTERLIB); if(!isPersistentServer || enterlib == null || enterlib.length() == 0) { // Use the default /gsdl and hope for the best. url.append(SEPARATOR); url.append(GSDL); } else { if(!enterlib.startsWith(SEPARATOR)) { url.append(SEPARATOR); } url.append(enterlib); } enterlib = null; debug("Found Local Library Address: " + url.toString()); return url.toString(); } /** @return the cmd-line parameter for the configfile used to launch * the server through GLI: --config=. */ public String getSiteConfigFilename() { return SPECIFIC_CONFIG + configFile.getAbsolutePath(); } public String getURL() { String urlPropertyName = isIndependentGSI() ? GSI_URL : URL; // URL is made from url and portnumber String url = (String) get(urlPropertyName); // server interface is already up, independent of GLI // but it has not started the server (hence URL is pending) if(url != null && url.equals(URL_PENDING)) { return url; } if(!isPersistentServer) { return url; } if(url != null) { StringBuffer temp = new StringBuffer(url); temp.append(COLON); temp.append((String)get(PORTNUMBER)); String enterlib = (String)get(ENTERLIB); if(enterlib == null || enterlib.length() == 0) { // Use the default /greenstone prefix and hope for the best. temp.append(SEPARATOR); temp.append(GSDL); } else { if(!enterlib.startsWith(SEPARATOR)) { temp.append(SEPARATOR); } temp.append(enterlib); } enterlib = null; url = temp.toString(); } debug("Found Local Library Address: " + url); return url; } public void setLastModified() { if(isModified()) { lastModified = configFile.lastModified(); } } public boolean isModified() { return (lastModified != configFile.lastModified()); } public void load(boolean reloadOnlyIfModified) { if(configFile == null) { debug(configFile.getAbsolutePath() + " cannot be found!"); } if(isModified()) { lastModified = configFile.lastModified(); } else if(reloadOnlyIfModified) { return; // asked to reload only if modified. Don't reload since not modified } if(configFile.exists()) { debug("Load: " + configFile.getAbsolutePath()); clear(); try { BufferedReader in = new BufferedReader(new FileReader(configFile)); String line = null; while((line = in.readLine()) != null) { String key = null; String value = null; int index = -1; if((index = line.indexOf("=")) != -1 && line.length() >= index + 1) { key = line.substring(0, index); value = line.substring(index + 1); } else { key = line; } put(key, value); } in.close(); } catch (Exception error) { error.printStackTrace(); } } else { debug(configFile.getAbsolutePath() + " cannot be found!"); } } /** Restore the autoenter value to its initial value, and remove url if present. */ public void restore() { if(configFile != null) { // Delete the file //configFile.delete(); // Not restoring nor deleting here. Just removing the URL (which indicates a running server), // so that the file's state indicates the server has stopped, and then saving the property file. // Should all properties not defined in the llssite.cfg.in template be removed below? String urlPropertyName = isIndependentGSI() ? GSI_URL : URL; remove(urlPropertyName); remove("gsdlhome"); remove("collecthome"); remove("gdbmhome"); remove("logfilename"); // For some reason launching GLI with server.exe clobbers autoenter and startbrowser // values for independent GSI in llssite.cfg file, and gli.autoenter and gli.startbrowser. // So set them here. if(get(GSI_AUTOENTER) == null) { put(GSI_AUTOENTER, "0"); } if(get(GSI_STARTBROWSER) == null) { put(GSI_STARTBROWSER, "1"); } if(get(AUTOENTER) == null) { put(AUTOENTER, "1"); } if(get(STARTBROWSER) == null) { put(STARTBROWSER, "0"); } save(); } else { String urlPropertyName = isIndependentGSI() ? GSI_URL : URL; debug("Restore Initial Settings"); put(AUTOENTER, autoenter_initial); put(STARTBROWSER, start_browser_initial); remove(urlPropertyName); save(); } } public void set() { debug("Set Session Settings"); if(autoenter_initial == null) { autoenter_initial = (String) get(AUTOENTER); debug("Remember autoenter was: " + autoenter_initial); } put(AUTOENTER, TRUE); if(start_browser_initial == null) { start_browser_initial = (String) get(STARTBROWSER); debug("Remember start_browser was: " + start_browser_initial); } put(STARTBROWSER, FALSE); save(); } private void debug(String message) { ///ystem.err.println(message); } private void save() { debug("Save: " + configFile.getAbsolutePath()); try { BufferedWriter out = new BufferedWriter(new FileWriter(configFile, false)); for(Iterator keys = keySet().iterator(); keys.hasNext(); ) { String key = (String) keys.next(); String value = (String) get(key); out.write(key, 0, key.length()); if(value != null) { out.write('='); // if the GSI was launched outside of GLI, don't overwrite its default // autoenter and startbrowser values if(isIndependentGSI && (key == GSI_AUTOENTER || key == GSI_STARTBROWSER)) { if(key == GSI_AUTOENTER) { out.write(autoenter_initial, 0, autoenter_initial.length()); } else { // GSI_STARTBROWSER out.write(start_browser_initial, 0, start_browser_initial.length()); } } else { out.write(value, 0, value.length()); } } out.newLine(); } out.flush(); out.close(); } catch (Exception error) { error.printStackTrace(); } } private static void copyConfigFile(File source_cfg, File dest_cfg, boolean setToGliSiteDefaults) { // source_cfg file should exist // dest_cfg file should not yet exist // If setToGliSiteDefaults is true, then GLIsite.cfg's default configuration // is applied to concerned lines: gli.autoenter=1, and gli.startbrowser=0 try { BufferedReader in = new BufferedReader(new FileReader(source_cfg)); BufferedWriter out = new BufferedWriter(new FileWriter(dest_cfg, false)); String line = null; while((line = in.readLine()) != null) { if(setToGliSiteDefaults) { if(line.startsWith(AUTOENTER)) { line = AUTOENTER+"=1"; } else if(line.startsWith(STARTBROWSER)) { line = STARTBROWSER+"=0"; } } // write out the line out.write(line); out.newLine(); } out.flush(); in.close(); out.close(); } catch(Exception e) { System.err.println("Exception occurred when trying to copy the config file " + source_cfg.getName() + " to " + dest_cfg.getName() + ": " + e); e.printStackTrace(); } } } }