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