| Main |

    1   /*
    2    *  Main.java
    3    *
    4    *  Copyright (c) 1998-2001, The University of Sheffield.
    5    *
    6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
    7    *  software, licenced under the GNU Library General Public License,
    8    *  Version 2, June 1991 (in the distribution as file licence.html,
    9    *  and also available at http://gate.ac.uk/gate/licence.html).
    10   *
    11   *  Hamish Cunningham, 1/Nov/00
    12   *
    13   *  $Id: Main.java,v 1.30 2001/11/29 17:21:18 hamish Exp $
    14   */
    15
    16  package gate;
    17
    18  import java.util.*;
    19  import java.awt.Dimension;
    20  import java.awt.Toolkit;
    21  import java.awt.Font;
    22  import java.awt.GraphicsEnvironment;
    23  import java.io.*;
    24  import java.net.*;
    25  import java.awt.Color;
    26
    27  import javax.swing.*;
    28
    29  import gnu.getopt.*;
    30
    31  import gate.util.*;
    32  import gate.gui.*;
    33
    34
    35  /** Top-level entry point for the GATE command-line and GUI interfaces.
    36    * <P>
    37    */
    38  public class Main {
    39
    40    /** Debug flag */
    41    private static final boolean DEBUG = false;
    42
    43    /** Status flag for normal exit. */
    44    private static final int STATUS_NORMAL = 0;
    45
    46    /** Status flag for error exit. */
    47    private static final int STATUS_ERROR = 1;
    48
    49    /** Main routine for GATE.
    50      * Command-line arguments:
    51      * <UL>
    52      * <LI>
    53      * <B>-h</B> display a short help message
    54      * <LI>
    55      * <B>-d URL</B> define URL to be a location for CREOLE resoures
    56      * <LI>
    57      * <B>-i file</B> additional initialisation file (probably called
    58      *   <TT>gate.xml</TT>). Used for site-wide initialisation by the
    59      *   start-up scripts.
    60      * </UL>
    61      */
    62    public static void main(String[] args) throws GateException {
    63      // check we have a useable JDK
    64      if(
    65        System.getProperty("java.version").compareTo(Gate.getMinJdkVersion())
    66        < 0
    67      ) {
    68        throw new GateException(
    69          "GATE requires JDK " + Gate.getMinJdkVersion() + " or newer"
    70        );
    71      }
    72
    73      // process command-line options
    74      processArgs(args);
    75
    76      // GATE builtins should be loaded from the jar (or classes dir), not
    77      // from a web server (we load them over the web during testing to
    78      // make sure that users can load their own that way)
    79      Gate.setNetConnected(false);
    80      Gate.setLocalWebServer(false);
    81
    82
    83      // run the interface or do batch processing
    84      if(batchMode) {
    85        if(DEBUG) Out.prln("running batch process");
    86        batchProcess();
    87      } else {
    88        runGui();
    89      }
    90    } // main
    91
    92    /** Register any CREOLE URLs that we got on the command line */
    93    private static void registerCreoleUrls() {
    94      CreoleRegister reg = Gate.getCreoleRegister();
    95      Iterator iter = pendingCreoleUrls.iterator();
    96      while(iter.hasNext()) {
    97        URL u = (URL) iter.next();
    98        try {
    99          reg.registerDirectories(u);
    100       } catch(GateException e) {
    101         Err.prln("Couldn't register CREOLE directory: " + u);
    102         Err.prln(e);
    103         System.exit(STATUS_ERROR);
    104       }
    105     }
    106   } // registerCreoleUrls()
    107
    108   /** Main Frame of the GUI; null when no GUI running */
    109   private static MainFrame frame;
    110
    111   /** The splash shown when Gate starts*/
    112   private static Splash splash;
    113
    114   /**
    115    * Get the main frame of the GUI. If the GUI isn't running, it
    116    * is started.
    117    */
    118   public static MainFrame getMainFrame() throws GateException {
    119     if(frame == null)
    120       runGui();
    121     return frame;
    122   } // getMainFrame()
    123
    124   /** Run the user interface. */
    125   private static void runGui() throws GateException {
    126
    127     Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
    128     //show the splash
    129     SwingUtilities.invokeLater(new Runnable(){
    130       public void run(){
    131         //build the Spash
    132         JPanel splashBox = new JPanel();
    133         splashBox.setLayout(new BoxLayout(splashBox, BoxLayout.Y_AXIS));
    134         splashBox.setBackground(Color.white);
    135
    136         JLabel gifLbl = new JLabel(new ImageIcon(Main.class.getResource(
    137             "/gate/resources/img/gateSplash.gif")));
    138         Box box = new Box(BoxLayout.X_AXIS);
    139         box.add(Box.createHorizontalGlue());
    140         box.add(gifLbl);
    141         box.add(Box.createHorizontalGlue());
    142         splashBox.add(box);
    143         gifLbl = new JLabel(new ImageIcon(Main.class.getResource(
    144             "/gate/resources/img/gateHeader.gif")));
    145         box = new Box(BoxLayout.X_AXIS);
    146         box.add(Box.createHorizontalGlue());
    147         box.add(gifLbl);
    148         box.add(Box.createHorizontalGlue());
    149         splashBox.add(box);
    150         splashBox.add(Box.createVerticalStrut(15));
    151         splash = new Splash(splashBox);
    152         splash.show();
    153       }
    154     });
    155
    156     // initialise the library and load user CREOLE directories
    157     Gate.init();
    158     registerCreoleUrls();
    159
    160     //create the main frame, show it and hide the splash
    161     SwingUtilities.invokeLater(new Runnable(){
    162       public void run(){
    163         //this needs to run before any GUI component is constructed.
    164         //the initial gate splash is exempted from this rule.
    165         applyUserPreferences();
    166
    167         //all the defaults tables have been updated; build the GUI
    168         frame = new MainFrame();
    169         if(DEBUG) Out.prln("constructing GUI");
    170
    171         // run the GUI
    172         frame.setTitle(name + " " + version + " build " + build);
    173
    174         // Validate frames that have preset sizes
    175         frame.validate();
    176
    177         // Center the window
    178         Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    179         Dimension frameSize = frame.getSize();
    180         if (frameSize.height > screenSize.height) {
    181           frameSize.height = screenSize.height;
    182         }
    183         if (frameSize.width > screenSize.width) {
    184           frameSize.width = screenSize.width;
    185         }
    186         frame.setLocation((screenSize.width - frameSize.width) / 2,
    187                           (screenSize.height - frameSize.height) / 2);
    188
    189         frame.setVisible(true);
    190         splash.hide();
    191
    192         //load session if required and available;
    193         //do everything from a new thread.
    194         Runnable runnable = new Runnable(){
    195           public void run(){
    196             try{
    197               File sessionFile = new File(Gate.getUserSessionFileName());
    198               if(sessionFile.exists()){
    199                 gate.util.persistence.PersistenceManager.loadObjectFromFile(sessionFile);
    200               }
    201             }catch(Exception e){
    202               Err.prln("Failed to load session data:");
    203               e.printStackTrace(Err.getPrintWriter());
    204             }
    205           }
    206         };
    207         Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
    208                                    runnable, "Session loader");
    209         thread.setPriority(Thread.MIN_PRIORITY);
    210         thread.start();
    211       }
    212     });
    213   } // runGui()
    214
    215   /**
    216    * Reads the user config data and applies the required settings.
    217    */
    218   protected static void applyUserPreferences(){
    219     //look and feel
    220     String lnfClassName = Gate.getUserConfig().
    221                           getString(GateConstants.LOOK_AND_FEEL);
    222     if(lnfClassName == null){
    223       lnfClassName = UIManager.getSystemLookAndFeelClassName();
    224       Gate.getUserConfig().put(GateConstants.LOOK_AND_FEEL, lnfClassName);
    225     }
    226     try {
    227       UIManager.setLookAndFeel(lnfClassName);
    228     } catch(Exception e) {
    229       throw new gate.util.GateRuntimeException(e.toString());
    230     }
    231
    232     //read the user config data
    233     OptionsMap userConfig = Gate.getUserConfig();
    234
    235     //text font
    236     Font font = userConfig.getFont(GateConstants.TEXT_COMPONENTS_FONT);
    237     if(font == null){
    238       String fontName = Gate.guessUnicodeFont();
    239       if(fontName != null){
    240         font = new Font(fontName, Font.PLAIN, 12);
    241       }else{
    242         font = UIManager.getFont("TextPane.font");
    243       }
    244     }
    245
    246     if(font != null){
    247       OptionsDialog.setTextComponentsFont(font);
    248     }
    249
    250     //menus font
    251     font = userConfig.getFont(GateConstants.MENUS_FONT);
    252     if(font == null){
    253       String fontName = Gate.guessUnicodeFont();
    254       if(fontName != null){
    255         font = new Font(fontName, Font.PLAIN, 12);
    256       }else{
    257         font = UIManager.getFont("Menu.font");
    258       }
    259     }
    260
    261     if(font != null){
    262       OptionsDialog.setMenuComponentsFont(font);
    263     }
    264
    265     //other gui font
    266     font = userConfig.getFont(GateConstants.OTHER_COMPONENTS_FONT);
    267     if(font == null){
    268       String fontName = Gate.guessUnicodeFont();
    269       if(fontName != null){
    270         font = new Font(fontName, Font.PLAIN, 12);
    271       }else{
    272         font = UIManager.getFont("Button.font");
    273       }
    274     }
    275
    276     if(font != null){
    277       OptionsDialog.setComponentsFont(font);
    278     }
    279
    280
    281   }
    282
    283
    284
    285   // find out the version and build numbers
    286   static {
    287     // find out the version number
    288     try {
    289       InputStream ver = Files.getGateResourceAsStream("version.txt");
    290       if (ver==null) {
    291         throw new IOException();
    292       }
    293       BufferedReader reader = new BufferedReader(new InputStreamReader(ver));
    294       Main.version = reader.readLine();
    295     } catch(IOException ioe) {
    296       Main.version = "2.0";
    297     }
    298
    299     // find out the build number
    300     try{
    301       InputStream build = Files.getGateResourceAsStream("build.txt");
    302       if (build==null) {
    303         throw new IOException();
    304       }
    305       BufferedReader reader = new BufferedReader(new InputStreamReader(build));
    306       Main.build = reader.readLine();
    307     } catch(IOException ioe) {
    308       Main.build = "0000";
    309     }
    310   } // static initialiser finding build and version
    311
    312
    313 /**
    314
    315 <BR>
    316 <B>Options processing: </B>
    317
    318 <BR>
    319 <TABLE>
    320   <TR>
    321     <TH ALIGN=left COLSPAN=15>
    322     -a annotator arg(s)
    323     </TH>
    324     <TH ALIGN=left>
    325     A CREOLE annotator to run on the collection, with zero or more
    326     arguments. The set of such annotators will be run in the sequence
    327     they appear in the arguments list. The arguments list must end with the
    328     start of another option; otherwise add a "-" after the arguments to
    329     terminate the list.
    330     </TH>
    331   </TR>
    332   <TR>
    333     <TH ALIGN=left COLSPAN=15>
    334     -b
    335     </TH>
    336     <TH ALIGN=left>
    337     Batch mode. Don't start the GUI, just process options and exit after
    338     any actions (e.g. running annotators).
    339     </TH>
    340   </TR>
    341   <TR>
    342     <TH ALIGN=left COLSPAN=15>
    343     -c collname
    344     </TH>
    345     <TH ALIGN=left>
    346     Name of the collection to use. If the collection already exists then
    347     it will be used as it stands, otherwise it will be created. See also
    348     -f.
    349     </TH>
    350   </TR>
    351   <TR>
    352     <TH ALIGN=left COLSPAN=15>
    353     -d
    354     </TH>
    355     <TH ALIGN=left>
    356     Destroy the collection after use. (The default is to save it to
    357     disk.)
    358     </TH>
    359   </TR>
    360   <TR>
    361     <TH ALIGN=left COLSPAN=15>
    362     -f file(s)
    363     </TH>
    364     <TH ALIGN=left>
    365     One or more files to create a collection with. If the collection
    366     being used (see -c) already exists, these files are ignored.
    367     Otherwise they are used to create the collection.
    368     </TH>
    369   </TR>
    370   <TR>
    371     <TH ALIGN=left COLSPAN=15>
    372     -h
    373     </TH>
    374     <TH ALIGN=left>
    375     Print a usage message and exit.
    376     </TH>
    377   </TR>
    378   <TR>
    379     <TH ALIGN=left COLSPAN=15>
    380     -p creolepath
    381     </TH>
    382     <TH ALIGN=left>
    383     Sets the search path for CREOLE modules.
    384     </TH>
    385   </TR>
    386   <TR>
    387     <TH ALIGN=left COLSPAN=15>
    388     -v classname(s)
    389     </TH>
    390     <TH ALIGN=left>
    391     Verbose: turns on debugging output. Takes zero or more class names
    392     to debug.
    393     </TH>
    394   </TR>
    395 </TABLE>
    396
    397 */
    398   /** Name of the collection we were asked to process. */
    399   private static String collName;
    400
    401   /** Search path for CREOLE modules. */
    402   private static String creolePath;
    403
    404   /** List of files we were asked to build a collection from. */
    405   private static List fileNames = new ArrayList();
    406
    407   /** List of annotators we were asked to run on the collection. */
    408   private static List annotatorNames = new ArrayList();
    409
    410   /** Map of annotator arguments. */
    411   private static Map annotatorArgsMap = new HashMap();
    412
    413   /** List of classes we were asked to debug. */
    414   private static List debugNames = new ArrayList();
    415
    416   /** Are we in batch mode? */
    417   public static boolean batchMode = false;
    418
    419   /** Don't save collection after batch? */
    420   private static boolean destroyColl = false;
    421
    422   /** Verbose? */
    423   private static boolean verbose = false;
    424
    425   private static boolean runCorpusBenchmarkTool = false;
    426
    427   public static String name = "Gate";
    428   public static String version;
    429   public static String build;
    430
    431   /** Process arguments and set up member fields appropriately.
    432     * Will shut down the process (via System.exit) if there are
    433     * incorrect arguments, or if the arguments ask for something
    434     * simple like printing the help message.
    435     */
    436   public static void processArgs(String[] args) {
    437
    438     Getopt g = new Getopt("GATE main", args, "hd:ei:");
    439     int c;
    440     while( (c = g.getopt()) != -1 )
    441       switch(c) {
    442         // -h
    443         case 'h':
    444           help();
    445           usage();
    446           System.exit(STATUS_NORMAL);
    447           break;
    448         // -d creole-dir
    449         case 'd':
    450           String urlString = g.getOptarg();
    451           URL u = null;
    452           try {
    453             u = new URL(urlString);
    454           } catch(MalformedURLException e) {
    455             Err.prln("Bad URL: " + urlString);
    456             Err.prln(e);
    457             System.exit(STATUS_ERROR);
    458           }
    459           pendingCreoleUrls.add(u);
    460           Out.prln(
    461             "CREOLE Directory " + urlString + " queued for registration"
    462           );
    463           break;
    464         // -i gate.xml site-wide init file
    465         case 'i':
    466           String optionString = g.getOptarg();
    467           URL u2 = null;
    468           File f = new File(optionString);
    469           try {
    470             u2 = f.toURL();
    471           } catch(MalformedURLException e) {
    472             Err.prln("Bad initialisation file: " + optionString);
    473             Err.prln(e);
    474             System.exit(STATUS_ERROR);
    475           }
    476           Gate.setSiteConfigFile(f);
    477           if(DEBUG)
    478       Out.prln(
    479         "Initialisation file " + optionString +
    480         " recorded for initialisation"
    481       );
    482           break;
    483         // -e runs the CorpusBenchmarkTool (e for evaluate)
    484         case 'e':
    485           try {
    486             CorpusBenchmarkTool.main(args);
    487           } catch (GateException ex) {
    488             Out.prln("Error running the evaluation tool: " + ex.getMessage());
    489             System.exit(-1);
    490           }
    491           break;
    492
    493
    494
    495 /*
    496         // -c collname
    497         case '-c':
    498           collName = g.getOptarg();
    499           break;
    500
    501         // -b
    502         case '-b':
    503           batchMode = true;
    504           break;
    505
    506         // -a annotator(s)
    507         case '-a':
    508           if(++i == args.length) { usage(); return; }
    509           String annotatorName = g.getOptarg();
    510           annotatorNames.add(annotatorName);
    511 // collect any args for the annotator
    512           break;
    513
    514         // -d
    515         case '-d':
    516           destroyColl = true;
    517           break;
    518
    519         // -f file(s)
    520         case '-f':
    521           while(++i < args.length)
    522             if(args[i].toCharArray()[0] == '-') { // start of another option
    523               i--;
    524               break;
    525             }
    526             else
    527               fileNames.add(args[i]);
    528           break;
    529
    530         // -p creolepath
    531         case '-p':
    532           if(++i < args.length)
    533             creolePath = args[i];
    534           else
    535             { usage(); return; }
    536           break;
    537
    538         // -v classname(s)
    539         case '-v':
    540           verbose = true;
    541           Debug.setDebug(true);
    542           while(++i < args.length) {
    543             if(args[i].toCharArray()[0] == '-') { // start of another option
    544               i--;
    545               break;
    546             }
    547             else
    548               debugNames.add(args[i]);
    549           } // while
    550           break;
    551 */
    552
    553         case '?':
    554           // leave the warning to getopt
    555           System.exit(STATUS_ERROR);
    556           break;
    557
    558         default:
    559           // shouldn't happen!
    560           Err.prln("getopt() returned " + c + "\n");
    561           System.exit(STATUS_ERROR);
    562           break;
    563       } // getopt switch
    564
    565   } // processArgs()
    566
    567   /** Run commands as a batch process. */
    568   private static void batchProcess() throws GateException{
    569     // initialise the library and load user CREOLE directories
    570     Gate.init();
    571     registerCreoleUrls();
    572
    573 /*
    574     // turn debugging on where requested
    575     if(verbose) {
    576       for(ArrayIterator i = debugNames.begin(); ! i.atEnd(); i.advance()) {
    577         try { Debug.setDebug(Class.forName(((String) i.get())), true); }
    578         catch(ClassNotFoundException e) {
    579           System.err.println(
    580             "can't debug class " + (String) i.get() + ": " + e.toString()
    581           );
    582         }
    583       } // for
    584     } // debugging on
    585
    586     // collection: does it exist and can we open it?
    587     if(collName == null) {
    588       System.err.println("no collection name given");
    589       usage();
    590       return;
    591     }
    592     File collDir = new File(collName);
    593     JdmCollection coll = null;
    594     if(collDir.exists()) { // open collection
    595       Debug.prnl("opening collection " + collName);
    596       try {
    597         coll = new JdmCollection(collName);
    598       } catch (JdmException e) {
    599         System.err.println(
    600           "Couldn't open collection " + collName + " " + e.toString()
    601         );
    602         return;
    603       }
    604     } else { // create collection and add documents
    605       Debug.prnl("creating collection " + collName);
    606       JdmAttributeSequence attrs = new JdmAttributeSequence();
    607       try {
    608         coll = new JdmCollection(collName, attrs);
    609       } catch (JdmException e) {
    610         System.err.println(
    611           "Couldn't create collection " + collName + " " + e.toString()
    612         );
    613         return;
    614       }
    615
    616       // add the documents to the collection
    617       for(ArrayIterator i = fileNames.begin(); ! i.atEnd(); i.advance()) {
    618         Debug.prnl("adding document " + (String) i.get());
    619         try {
    620           JdmDocument doc = coll.createDocument(
    621             (String) i.get(),
    622             null,
    623             new JdmAnnotationSet(),
    624             new JdmAttributeSequence()
    625           );
    626         } catch (JdmException e) {
    627           System.err.println(
    628              "Can't add document " + (String) i.get() + ": " + e.toString()
    629           );
    630         } // catch
    631       } // for each filename
    632     } // collection create
    633
    634     // run the annotators on each document in the collection
    635     // for each document
    636     JdmDocument doc = null;
    637     if(coll.length() > 0)
    638       try{ doc = coll.firstDocument(); } catch(JdmException e) { }
    639     for(int i = 0; i<coll.length(); i++) {
    640       if(doc == null) continue; // first and next doc shouldn't throw excptns!
    641
    642       // for each annotator
    643       for(ArrayIterator j = annotatorNames.begin(); !j.atEnd(); j.advance()) {
    644         String annotatorName = (String) j.get();
    645         Debug.prnl(
    646           "calling annotator " + annotatorName + " on doc " + doc.getId()
    647         );
    648
    649         // load the annotator class
    650         Annotator annotator = null;
    651         Class annotatorClass = null;
    652         try {
    653           // cheat and assume that all annotators are on CLASSPATH
    654           annotatorClass = Class.forName(annotatorName);
    655         } catch (Exception ex) {
    656           System.err.println(
    657             "Could load class for CREOLE object " + annotatorName + ": " +
    658             ex.toString()
    659           );
    660           continue;
    661         }
    662
    663         // construct the annotator
    664         try {
    665           annotator = (Annotator) annotatorClass.newInstance();
    666         } catch (Throwable ex) { // naughty chap
    667           System.err.println(
    668             "Could create instance of CREOLE object " + annotatorName + ": " +
    669             ex.toString()
    670           );
    671           continue;
    672         }
    673
    674         // annotate this document
    675         String[] args = (String[]) annotatorArgsMap.get(annotatorName);
    676         if(args == null) args = new String[0];
    677         annotator.annotate(doc, args);
    678       } // for each annotator
    679
    680       doc = null;
    681       try { doc = coll.nextDocument(); } catch(JdmException e) { }
    682     } // for each doc, annotate
    683
    684     // save collection?
    685     if(! destroyColl) {
    686       Debug.prnl("saving the collection");
    687       try {
    688         coll.sync();
    689       } catch (JdmException e) {
    690         System.err.println(
    691           "Can't save collection " + collName + ": " + e.toString()
    692         );
    693       }
    694     } else {
    695       Debug.prnl("destroying collection");
    696       try { coll.destroy(); } catch(JdmException e) {
    697         // if we didn't sync we can't destroy, but that's not an error
    698       }
    699     }
    700
    701     Debug.prnl("done batch process");
    702 */
    703   } // batchProcess()
    704
    705   /** Display a usage message */
    706   public static void usage() {
    707     Out.prln(
    708       "Usage: java gate.Main " +
    709       "[ -h [-d CREOLE-URL]" +
    710       ""
    711     );
    712   } // usage()
    713
    714   /** Display a help message */
    715   public static void help() {
    716     String nl = Strings.getNl();
    717     Out.prln(
    718       "For help on command-line options and other information " + nl +
    719       "see the user manual in your GATE distribution or at " + nl +
    720       "http://gate.ac.uk/gate/doc/userguide.html"
    721     );
    722   } // help()
    723
    724   /** The list of pending URLs to add to the CREOLE register */
    725   private static List pendingCreoleUrls = new ArrayList();
    726
    727 } // class Main
    728

| Main |