|
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 |
|