Changeset 5000


Ignore:
Timestamp:
2003-07-22T13:23:35+12:00 (21 years ago)
Author:
jmt12
Message:

GLI will now accept arguments with spaces in them. Plus connecting to local library will now timeout.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gli/src/org/greenstone/gatherer/Gatherer.java

    r4676 r5000  
    1 package org.greenstone.gatherer;
    21/**
    32 *#########################################################################
     
    76 * University of Waikato, New Zealand.
    87 *
    9  * <BR><BR>
    10  *
    118 * Author: John Thompson, Greenstone Digital Library, University of Waikato
    129 *
    13  * <BR><BR>
    14  *
    1510 * Copyright (C) 1999 New Zealand Digital Library Project
    16  *
    17  * <BR><BR>
    1811 *
    1912 * This program is free software; you can redistribute it and/or modify
     
    2215 * (at your option) any later version.
    2316 *
    24  * <BR><BR>
    25  *
    2617 * This program is distributed in the hope that it will be useful,
    2718 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2819 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2920 * GNU General Public License for more details.
    30  *
    31  * <BR><BR>
    3221 *
    3322 * You should have received a copy of the GNU General Public License
     
    3625 *########################################################################
    3726 */
     27package org.greenstone.gatherer;
     28/**************************************************************************************
     29 * Written:      ??/??/02
     30 * Revised:      ??/??/02 - Commented
     31 *               ??/??/03 - Added support for local library server
     32 *               20/07/03 - Rewrote argument parsing so that spaces no longer cause GLI to die. Also added time out when starting local library.
     33 **************************************************************************************/
     34
    3835import com.l2fprod.gui.*;
    3936import com.l2fprod.gui.plaf.skin.*;
    4037import com.l2fprod.util.*;
    41 
    4238import java.awt.*;
     39import java.awt.event.*;
    4340import java.io.*;
    4441import java.lang.*;
     
    4744import javax.swing.*;
    4845import javax.swing.plaf.*;
     46import javax.swing.text.*;
    4947import org.greenstone.gatherer.Configuration;
    5048import org.greenstone.gatherer.GAuthenticator;
     
    6058import org.greenstone.gatherer.util.ArrayTools;
    6159import org.greenstone.gatherer.util.GSDLSiteConfig;
     60import org.greenstone.gatherer.util.StaticStrings;
    6261import org.greenstone.gatherer.util.Utility;
    6362import sun.misc.*;
     
    6766 */
    6867public class Gatherer {
     68
     69    static final private String SKIN_DEFINITION_FILE = "lib/greenaqua/greenaqua.xml";
     70
    6971    /** Has the exit flag been set? <i>true</i> if so, <i>false</i> otherwise. */
    7072    public boolean exit = false;
     
    105107    /** The name of the Gatherers configuration file. */
    106108    static private String CONFIG_FILE_NAME = "gatherer.cfg";
     109
     110    /** Magic to allow Enter to fire the default button. */
     111    static {
     112      KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
     113      Keymap map = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
     114      map.removeKeyStrokeBinding(enter);
     115    }
     116
     117
     118
    107119    /** Constructor. Make the three main modules, c_man, f_man and g_man, and any other necessary classes such as Dictionary.
    108120     * @param size The desired size of the Gatherer window as a <strong>Dimension</strong>.
     
    134146
    135147    // This will hopefully catch ctrl-c and terminate, and exit gracefully. However it is platform specific, and may not be supported by some JVMs.
    136     /** It does, but I get bloddy sick of it working when the Gatherer hangs.
     148    /** It does, but I get bloody sick of it working when the Gatherer hangs.
    137149        CTRLCHandler handler = new CTRLCHandler();
    138150        Signal.handle(new Signal("INT"), handler);
     
    405417    }
    406418
    407     /** Some startup arguments to the Gatherer have been encoded, where ' ' is replaced with '%', in order to allow arguments containing spaces to be parsed correctly by the JVM, and this method restores these arguments to thier original state.
    408      * @param encoded An encoded <strong>String</strong>.
    409      * @return The decoded <strong>String</strong>.
    410      */
    411     static public String decode(String encoded) {
    412     return encoded.replace('%', ' ');
    413     }
    414419    /** The entry point into the Gatherer. Parses arguments.
    415420     * @param args A collection of arguments that may include: initial screen size, dictionary, path to the GSDL etc.
     
    421426     * @see org.greenstone.gatherer.Gatherer
    422427     * @see org.greenstone.gatherer.gui.Splash
     428     * @see org.greenstone.gatherer.util.StaticStrings
    423429     */
    424430    static public void main(String[] args) {
     
    439445    String perl_path = null;
    440446    // Parse arguments
    441     for(int i = 0; i < args.length; i++) {
    442         if(args[i].equals("-gsdl")) {
    443         gsdl_path = decode(args[i+1]);
    444         if(!gsdl_path.endsWith(File.separator)) {
    445             gsdl_path = gsdl_path + File.separator;
    446         }
    447         }
    448         if(args[i].equals("-load")) {
    449         filename = decode(args[i+1]);
    450         }
    451         else if(args[i].equals("-library") && (i + 1) < args.length) {
    452         exec_path = args[i+1];
    453         // If we are on a non-windows system, and thus the local server is unavailable, we can append http:// if no protocol found.
    454         if(exec_path.lastIndexOf(":", 5) == -1) {
    455             exec_path = "http://" + exec_path;
    456         }
    457         // If the user has given us an address, but it ends with a '/' we assume we're using the greenstone library.cgi
    458         if(exec_path.startsWith("http://") && exec_path.endsWith("/")) {
    459             exec_path = exec_path + "library";
    460         }
    461         }
    462         else if(args[i].equals("-perl")) {
    463         perl_path = decode(args[i+1]);
    464         // Test whether this points to the Perl bin directory or the Perl executable itself.
    465         File perl_file = new File(perl_path);
    466         if(perl_file.isDirectory()) {
    467             // If this is windows we create a child file perl.exe, otherwise we create perl
    468             if(Utility.isWindows()) {
    469             perl_file = new File(perl_file, Utility.PERL_EXECUTABLE_WINDOWS);
    470             }
    471             else {
    472             perl_file = new File(perl_file, Utility.PERL_EXECUTABLE_UNIX);
    473             }
    474             // And store this new path.
    475             perl_path = perl_file.getAbsolutePath();
    476             perl_file = null;
    477         }
    478         // Otherwise its fine as it is
    479         ///ystem.err.println("Perl executable is: " + perl_path);
    480         }
    481         else if(args[i].equals("--help") || args[i].equals("-help") || args[i].equals("?") || args[i].equals("/?") || args[i].equals("/help")) {
    482         printUsage(dictionary);
    483         System.exit(0);
    484         }
    485         else if(args[i].equals("--debug") || args[i].equals("-debug")) {
    486         debug = true;
    487         }
    488                 // Don't load any previous collection. Convenient for me
    489         else if(args[i].equals("-no_load")) {
    490         no_load = true;
    491         }
    492                 // Check if they want it skinned.
    493         else if(args[i].equals("-skinlf")) {
    494         // SkinLF
    495         try {
    496             SkinLookAndFeel.setSkin(SkinLookAndFeel.loadThemePackDefinition(SkinUtils.toURL(new File("lib/greenaqua/greenaqua.xml"))));
    497             SkinLookAndFeel.enable();
    498         }
    499         catch (Exception error) {
    500             ///ystem.err.println("Error: " + error);
    501             error.printStackTrace();
    502         }
    503         }
    504     }
     447    int argument_index = 0;
     448    String next_token = null;
     449    while(argument_index < args.length) {
     450        // 1. We start by attempting to parse an argument name. An argument must start with a '-', and should not contain spaces. If anything else is encountered it is ignored.
     451        String argument_name = null;
     452        if(next_token == null) {
     453            next_token = args[argument_index];
     454            argument_index++;
     455        }
     456        if(next_token.startsWith(StaticStrings.MINUS_CHARACTER)) {
     457            // Trim second '-' just to be kind to Unixy-type people
     458            if(next_token.startsWith(StaticStrings.MINUS_CHARACTER + StaticStrings.MINUS_CHARACTER)) {
     459                argument_name = next_token.substring(1);
     460            }
     461            else {
     462                argument_name = next_token;
     463            }
     464        }
     465        next_token = null;
     466        // 2. If we now have an argument name we continue by attempting to parse a value. A value is taken to be the sequence of space seperated Strings between the last argument name and up to but not including the next argument name. Of course an argument needn't have any value (ie -debug, -help), in which case value will be null.
     467        if(argument_name != null) {
     468            String argument_value = null;
     469            StringBuffer argument_value_buffer = new StringBuffer("");
     470            while(argument_index < args.length && next_token == null) {
     471                next_token = args[argument_index];
     472                argument_index++;
     473                // If we just parsed an arbitary String then append it to value, followed by a single space
     474                if(!next_token.startsWith(StaticStrings.MINUS_CHARACTER)) {
     475                    argument_value_buffer.append(next_token);
     476                    argument_value_buffer.append(StaticStrings.SPACE_CHARACTER);
     477                    next_token = null;
     478                }
     479                // If the argument token retrieved is an argument name, then leave it in next_token, which will cause the argument parsing process to move onto the next step.
     480            }
     481            // If a value now exists in argument buffer, retrieve it. Remove the last character as it will be an erroneous space.
     482            if(argument_value_buffer.length() > 0) {
     483                argument_value = argument_value_buffer.substring(0, argument_value_buffer.length() - 1);
     484            }
     485
     486            // 3. We now have the argument name, and any associated value. We are ready to store the data in the appropriate variables.
     487            Gatherer.println("Parsed Argument: name=" + argument_name + (argument_value != null ? (", value=" + argument_value) : ", no value"));
     488            // 3a. First those arguments that have no associated value
     489            if(argument_value == null) {
     490                if(argument_name.equals(StaticStrings.HELP_ARGUMENT)) {
     491                    printUsage(dictionary);
     492                    System.exit(0);
     493                }
     494                // Run GLI in debug mode. Produces debug log plus extra messages.
     495                else if(argument_name.equals(StaticStrings.DEBUG_ARGUMENT)) {
     496                    debug = true;
     497                }
     498                // Forces no loading on previous collection.
     499                else if(argument_name.equals(StaticStrings.NO_LOAD_ARGUMENT)) {
     500                    no_load = true;
     501                    filename = null;
     502                }
     503                // Specify the use of Greenstone LAF.
     504                else if(argument_name.equals(StaticStrings.SKIN_ARGUMENT)) {
     505                    // SkinLF
     506                    try {
     507                        SkinLookAndFeel.setSkin(SkinLookAndFeel.loadThemePackDefinition(SkinUtils.toURL(new File(SKIN_DEFINITION_FILE))));
     508                        SkinLookAndFeel.enable();
     509                    }
     510                    catch (Exception error) {
     511                        ///ystem.err.println("Error: " + error);
     512                        error.printStackTrace();
     513                    }
     514                }
     515            }
     516            // 3b. Now for those that do
     517            else {
     518                // Parse the path to the GSDL. Required argument.
     519                if(argument_name.equals(StaticStrings.GSDL_ARGUMENT)) {
     520                    if(argument_value.endsWith(File.separator)) {
     521                        gsdl_path = argument_value;
     522                    }
     523                    else {
     524                        gsdl_path = argument_value + File.separator;
     525                    }
     526                }
     527                // Specify a collection to load initially. Could be used for file associations.
     528                else if(argument_name.equals(StaticStrings.LOAD_ARGUMENT)) {
     529                    filename = argument_value;
     530                    no_load = false;
     531                }
     532                // Parse the url to a running web server, or a file path to the local library server.
     533                else if(argument_name.equals(StaticStrings.LIBRARY_ARGUMENT)) {
     534                    exec_path = argument_value;
     535                    // If there is no colon in first five characters of the exec_path (which would either be an existing protocol, or a windows file path to say a local library), we can append the protocol http://.
     536                    if(argument_value.lastIndexOf(StaticStrings.COLON_CHARACTER, 5) == -1) {
     537                        exec_path = StaticStrings.HTTP_PROTOCOL_STR + argument_value;
     538                    }
     539                    else {
     540                        exec_path = argument_value;
     541                    }
     542                    // If the user has given us an address, but it ends with a '/' we assume we're using the greenstone library.cgi
     543                    if(exec_path.startsWith(StaticStrings.HTTP_PROTOCOL_STR) && exec_path.endsWith(StaticStrings.URL_SEPARATOR_CHARACTER)) {
     544                        exec_path = exec_path + StaticStrings.LIBRARY_STR;
     545                    }
     546                }
     547                // Parse the path to PERL. If not provided its assumes perl should be availble on the PATH.
     548                else if(argument_name.equals(StaticStrings.PERL_ARGUMENT)) {
     549                    perl_path = argument_value;
     550                    // Test whether this points to the Perl bin directory or the Perl executable itself.
     551                    File perl_file = new File(perl_path);
     552                    if(perl_file.isDirectory()) {
     553                        // If this is windows we create a child file perl.exe, otherwise we create perl
     554                        if(Utility.isWindows()) {
     555                        perl_file = new File(perl_file, Utility.PERL_EXECUTABLE_WINDOWS);
     556                        }
     557                        else {
     558                        perl_file = new File(perl_file, Utility.PERL_EXECUTABLE_UNIX);
     559                        }
     560                        // And store this new path.
     561                        perl_path = perl_file.getAbsolutePath();
     562                        perl_file = null;
     563                    }
     564                    // Otherwise its fine as it is
     565                }
     566            }
     567        }
     568        // Argument name was null, nothing to be done.
     569    }
     570    next_token = null;
     571    // Arguments all parsed.
    505572
    506573    // Splash screen.
     
    509576    // We take appropriate action when an empty gsdl_path is detected.
    510577    if(gsdl_path == null) {
    511                 // Check for the presence of the path.cfg file.
     578        // Check for the presence of the path.cfg file.
    512579        File path_file = new File("path.cfg");
    513580        if(path_file.exists()) {
     
    664731
    665732    private void startServerEXE() {
    666     if(config.exec_file != null && config.exec_address == null && Utility.isWindows()) {
    667         // First of all we create a GSDLSiteCFG object and check if a URL is already present, in which case the server is already running.
    668         gsdlsite_cfg = new GSDLSiteConfig(config.exec_file);
    669         String url = gsdlsite_cfg.getURL();
    670         // If its already running then set exec address.
    671         if(url != null) {
    672         try {
    673             config.exec_address = new URL(url);
    674         }
    675         catch(Exception error) {
    676         }
    677         }
    678         // Otherwise its time to run the server in a spawned process.
    679         if(config.exec_address == null && config.exec_file.exists()) {
    680         // Configure for immediate entry. Note that this only works if the gsdlsite.cfg file exists.
    681         gsdlsite_cfg.set();
    682         // Spawn server
    683         String[] command = new String[2];
    684         command[0] = config.exec_file.getAbsolutePath();
    685         command[1] = gsdlsite_cfg.getSiteConfigFilename();
    686         server = new ExternalApplication(command);
    687         server.start();
    688         command = null;
    689         // Now we have to wait until program has started. We do this by reloading and checking
    690         try {
    691             gsdlsite_cfg.load();
    692             while((url = gsdlsite_cfg.getURL()) == null) {
    693             synchronized(this) {
    694                 wait(1000);
     733        if(config.exec_file != null && config.exec_address == null && Utility.isWindows()) {
     734            // First of all we create a GSDLSiteCFG object and check if a URL is already present, in which case the server is already running.
     735            gsdlsite_cfg = new GSDLSiteConfig(config.exec_file);
     736            String url = gsdlsite_cfg.getURL();
     737            // If its already running then set exec address.
     738            if(url != null) {
     739                try {
     740                    config.exec_address = new URL(url);
     741                }
     742                catch(Exception error) {
     743                }
     744            }
     745            // Otherwise its time to run the server in a spawned process.
     746            if(config.exec_address == null && config.exec_file.exists()) {
     747                // Configure for immediate entry. Note that this only works if the gsdlsite.cfg file exists.
     748                gsdlsite_cfg.set();
     749                // Spawn server
     750                String[] command = new String[2];
     751                command[0] = config.exec_file.getAbsolutePath();
     752                command[1] = gsdlsite_cfg.getSiteConfigFilename();
     753                server = new ExternalApplication(command);
     754                server.start();
     755                command = null;
     756                // Now we have to wait until program has started. We do this by reloading and checking
     757                ///ystem.err.print("Waiting until the local library has loaded");
     758                try {
     759                    gsdlsite_cfg.load();
     760
     761                    int try_again = JOptionPane.YES_OPTION;
     762                    int attempt_count = 0;
     763                    while(gsdlsite_cfg.getURL() == null && try_again == JOptionPane.YES_OPTION) {
     764                        ///ystem.err.print(".");
     765                        if(attempt_count == 60) {
     766                            try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, dictionary.get("Server.QuitTimeOut"), dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
     767                        }
     768                        else {
     769                            synchronized(this) {
     770                                wait(1000); // Wait one second (give or take)
     771                            }
     772                            gsdlsite_cfg.load();
     773                            attempt_count++;
     774                        }
     775                    }
     776
     777                    if(gsdlsite_cfg.getURL() != null) {
     778                        // Ta-da. Now the url should be available.
     779                        config.exec_address = new URL(url);
     780
     781                        // A quick test involves opening a connection to get the home page  for this collection. If this fails then we try changing the url to be localhost.
     782                        try {
     783                            Gatherer.println("Try connecting to server on config url.");
     784                            URLConnection connection = config.exec_address.openConnection();
     785                            connection.getContent();
     786                        }
     787                        catch(IOException bad_url_connection) {
     788                            try {
     789                                Gatherer.println("Try connecting to server on local host.");
     790                                config.exec_address = new URL(gsdlsite_cfg.getLocalHostURL  ());
     791                                URLConnection connection = config.exec_address.openConnection();
     792                                connection.getContent();
     793                            }
     794                            catch(IOException worse_url_connection) {
     795                                Gatherer.println("Can't connect to server on either address.");
     796                                config.exec_address = null;
     797                                config.exec_file = null;
     798                            }
     799                        }
     800                    }
     801                    // Unable to start local library. Show appropriate message.
     802                    else {
     803                        missingEXEC(dictionary);
     804                    }
     805                }
     806                catch (Exception error) {
     807                    error.printStackTrace();
     808                }
    695809            }
    696             gsdlsite_cfg.load();
    697             }
    698             // Ta-da. Now the url should be available.
    699             config.exec_address = new URL(url);
    700 
    701             // A quick test involves opening a connection to get the home page for this collection. If this fails then we try changing the url to be localhost.
    702             try {
    703             Gatherer.println("Try connecting to server on config url.");
    704             URLConnection connection = config.exec_address.openConnection();
    705             connection.getContent();
    706             }
    707             catch(IOException bad_url_connection) {
    708             try {
    709                 Gatherer.println("Try connecting to server on local host.");
    710                 config.exec_address = new URL(gsdlsite_cfg.getLocalHostURL());
    711                 URLConnection connection = config.exec_address.openConnection();
    712                 connection.getContent();
    713             }
    714             catch(IOException worse_url_connection) {
    715                 Gatherer.println("Can't connect to server on either address.");
    716                 config.exec_address = null;
    717                 config.exec_file = null;
    718             }
    719             }
    720         }
    721         catch (Exception error) {
    722             error.printStackTrace();
    723         }
    724         }
    725810        // Can't do a damb thing.
    726     }
    727     Gatherer.println("Having started server.exe, exec_address is: " + config.exec_address);
     811        }
     812        Gatherer.println("Having started server.exe, exec_address is: " + config.exec_address);
    728813    }
    729814
     
    739824            gsdlsite_cfg.load();
    740825            int try_again = JOptionPane.YES_OPTION;
    741             while(try_again == JOptionPane.YES_OPTION) {
    742826            int attempt_count = 0;
    743             while(gsdlsite_cfg.getURL() != null && attempt_count < 60) {
    744                 synchronized(this) {
    745                 wait(1000); // Wait one second (give or take)
    746                 }
    747                 gsdlsite_cfg.load();
    748                 attempt_count++;
     827            while(gsdlsite_cfg.getURL() != null && try_again == JOptionPane.YES_OPTION) {
     828                if(attempt_count == 60) {
     829                    try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, dictionary.get("Server.QuitTimeOut"), dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
     830                }
     831                else {
     832                    synchronized(this) {
     833                        wait(1000); // Wait one second (give or take)
     834                    }
     835                    gsdlsite_cfg.load();
     836                    attempt_count++;
     837                }
    749838            }
    750             if(attempt_count == 60) {
    751                 try_again = JOptionPane.showConfirmDialog(Gatherer.g_man, dictionary.get("Server.QuitTimeOut"), dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION);
    752             }
    753             else {
    754                 try_again = JOptionPane.NO_OPTION;
    755             }
    756             }
    757             if(gsdlsite_cfg.getURL() != null) {
    758             JOptionPane.showMessageDialog(Gatherer.g_man, dictionary.get("Server.QuitManual"), dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
    759             }
     839            //if(gsdlsite_cfg.getURL() != null) {
     840            //JOptionPane.showMessageDialog(Gatherer.g_man, dictionary.get("Server.QuitManual"), dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
     841            //}
    760842        }
    761843        catch (Exception error) {
Note: See TracChangeset for help on using the changeset viewer.