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