001/** 002 * MainTester.java 003 * jCOLIBRI2 framework. 004 * @author Juan A. Recio-Garc�a. 005 * GAIA - Group for Artificial Intelligence Applications 006 * http://gaia.fdi.ucm.es 007 * 03/07/2007 008 */ 009package es.ucm.fdi.gaia.jcolibri.test.main; 010 011import java.awt.BorderLayout; 012import java.awt.HeadlessException; 013import java.awt.event.ActionEvent; 014import java.awt.event.ActionListener; 015import java.awt.event.WindowAdapter; 016import java.awt.event.WindowEvent; 017import java.io.BufferedReader; 018import java.io.ByteArrayOutputStream; 019import java.io.FilterOutputStream; 020import java.io.IOException; 021import java.io.InputStreamReader; 022import java.io.OutputStream; 023import java.io.PrintStream; 024import java.lang.reflect.Method; 025import java.net.URL; 026import java.util.ArrayList; 027import java.util.Collection; 028import java.util.List; 029 030import javax.swing.BorderFactory; 031import javax.swing.Box; 032import javax.swing.BoxLayout; 033import javax.swing.JButton; 034import javax.swing.JEditorPane; 035import javax.swing.JFrame; 036import javax.swing.JLabel; 037import javax.swing.JList; 038import javax.swing.JPanel; 039import javax.swing.JScrollPane; 040import javax.swing.JSplitPane; 041import javax.swing.JTabbedPane; 042import javax.swing.JTextArea; 043import javax.swing.JWindow; 044import javax.swing.ListSelectionModel; 045import javax.swing.UIManager; 046import javax.swing.event.HyperlinkEvent; 047import javax.swing.event.HyperlinkListener; 048import javax.swing.event.ListSelectionEvent; 049import javax.swing.event.ListSelectionListener; 050 051import org.apache.log4j.ConsoleAppender; 052import org.apache.log4j.Layout; 053import org.apache.log4j.LogManager; 054import org.apache.log4j.Logger; 055import org.apache.log4j.WriterAppender; 056 057import es.ucm.fdi.gaia.jcolibri.util.FileIO; 058 059/** 060 * Main tester application that executes all the examples 061 * showing also related documentation to each one. 062 * 063 * @author Juan A. Recio-Garcia 064 * @version 1.0 065 */ 066public class MainTester extends JFrame 067{ 068 private static final long serialVersionUID = 1L; 069 070 JList<?> list; 071 List<ExampleInfo> info; 072 JTabbedPane tabPane; 073 JTextArea displayPane; 074 JButton run; 075 076 077 /** 078 * Constructor that creates the tester using a given config file 079 */ 080 public MainTester(String configfile) 081 { 082 info = parseExampleInfo(configfile); 083 084 085 try 086 { 087 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 088 } catch (Exception e1) 089 { 090 } 091 092 //this.setSize(new Dimension(800,600)); 093 this.setTitle("jCOLIBRI Tester"); 094// Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); 095// setBounds((screenSize.width - this.getWidth()) / 2, 096// (screenSize.height - this.getHeight()) / 2, 097// getWidth(), 098// getHeight()); 099 100 JPanel panelUp = new JPanel(); 101 panelUp.setBorder(BorderFactory.createTitledBorder("Available Tests")); 102 JPanel panelDown = new JPanel(); 103 panelDown.setBorder(BorderFactory.createTitledBorder("Execution log")); 104 105 JPanel topLeft = new JPanel(); 106 topLeft.setLayout(new BorderLayout()); 107 108 Object[] data = new Object[info.size()]; 109 int i=0; 110 for(ExampleInfo ei: info) 111 data[i++]=ei.getName(); 112 list = new JList<Object>(data); 113 list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 114 list.setLayoutOrientation(JList.VERTICAL); 115 JScrollPane listScroller = new JScrollPane(list); 116 117 topLeft.add(listScroller, BorderLayout.CENTER); 118 119 run = new JButton("Execute"); 120 121 run.addActionListener(new ActionListener(){ 122 public void actionPerformed(ActionEvent e) 123 { 124 runExample(); 125 } 126 }); 127 128// mapDialog = new JDialog(this,true); 129// mapDialog.getContentPane().add(new HTMLBrowser(FileIO.findFile("es/ucm/fdi/gaia/jcolibri/test/main/map.html"))); 130// mapDialog.setSize(new Dimension(800,600)); 131// mapDialog.setTitle("jCOLIBRI Examples Map"); 132// mapDialog.setBounds((screenSize.width - mapDialog.getWidth()) / 2, 133// (screenSize.height - mapDialog.getHeight()) / 2, 134// mapDialog.getWidth(), 135// mapDialog.getHeight()); 136// JButton map = new JButton("Map"); 137// map.addActionListener(new ActionListener(){ 138// public void actionPerformed(ActionEvent e) 139// { 140// mapDialog.setVisible(true); 141// } 142// }); 143 144 JPanel buttonsPanel = new JPanel(); 145 buttonsPanel.setLayout(new BorderLayout(2,1)); 146 buttonsPanel.add(run,BorderLayout.CENTER); 147 //buttonsPanel.add(map,BorderLayout.EAST); 148 149 topLeft.add(buttonsPanel, BorderLayout.SOUTH); 150 151 panelUp.setLayout(new BorderLayout()); 152 panelUp.add(topLeft, BorderLayout.WEST); 153 154 tabPane = new JTabbedPane(); 155 panelUp.add(tabPane, BorderLayout.CENTER); 156 157 158 list.addListSelectionListener(new ListSelectionListener(){ 159 160 public void valueChanged(ListSelectionEvent e) { 161 if (e.getValueIsAdjusting() == true) 162 return; 163 if (list.getSelectedIndex() == -1) 164 return; 165 int i = list.getSelectedIndex(); 166 setExample(i); 167 } 168 }); 169 170 this.addWindowListener(new WindowAdapter(){ 171 public void windowClosing(WindowEvent e){ 172 System.exit(0); 173 } 174 }); 175 176 displayPane = new JTextArea(); 177 displayPane.setEditable(false); 178 panelDown.setLayout(new BorderLayout()); 179 panelDown.add(new JScrollPane(displayPane)); 180 181 PrintStream aPrintStream = 182 new PrintStream( 183 new FilteredStream( 184 new ByteArrayOutputStream())); 185 System.setOut(aPrintStream); 186 System.setErr(aPrintStream); 187 188 ConsoleAppender a = (ConsoleAppender) Logger.getRootLogger().getAllAppenders().nextElement(); 189 Layout l = a.getLayout(); 190 Logger.getRootLogger().addAppender(new WriterAppender(l,aPrintStream)); 191 Logger.getRootLogger().removeAppender(a); 192 193 JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT,panelUp, panelDown); 194 split.setDividerLocation(0.6); 195 this.getContentPane().add(split); 196 pack(); 197 setExtendedState(java.awt.Frame.MAXIMIZED_BOTH); 198 199 } 200 201 /** 202 * Runs a test in a different thread. 203 */ 204 public void runExample() 205 { 206 run.setEnabled(false); 207 try 208 { 209 int i = list.getSelectedIndex(); 210 if(i==-1) 211 return; 212 213 displayPane.setText(""); 214 215 ExampleInfo ei = this.info.get(i); 216 217 MethodRunner mr = null; 218 Class<?> c = ei.getMainClass(); 219 Method[] methods = c.getMethods(); 220 for(Method m: methods) 221 if(m.getName().equals("main")) 222 mr=new MethodRunner(m); 223 if(mr==null) 224 return; 225 Thread executionThread = new Thread(mr); 226 executionThread.start(); 227 228 } catch (Exception e) 229 { 230 LogManager.getLogger(this.getClass()).error(e); 231 } 232 } 233 234 /** 235 * Thread for running a test 236 * @author Juan A. Recio-Garcia 237 * @version 1.0 238 */ 239 class MethodRunner implements Runnable 240 { 241 Method method; 242 243 MethodRunner(Method m) 244 { 245 method = m; 246 } 247 248 public void run() 249 { 250 Object[] args = new Object[1]; 251 args[0] = null; 252 try 253 { 254 method.invoke(null, args); 255 } catch (Exception e) 256 { 257 LogManager.getLogger(this.getClass()).error(e); 258 e.printStackTrace(); 259 } 260 LogManager.getLogger(MainTester.class).info("Test execution finished"); 261 run.setEnabled(true); 262 } 263 } 264 265 /** 266 * Shows an example in the window. 267 */ 268 public void setExample(int i) 269 { 270 try 271 { 272 ExampleInfo ei = this.info.get(i); 273 tabPane.removeAll(); 274 275 JEditorPane ep = new JEditorPane(); 276 ep.setContentType("text/html"); 277 ep.setText("<font face=\"verdana, arial, helvetica\"><b>"+ei.getDescription()+"</b></font>"); 278 ep.setEditable(false); 279 tabPane.add("Description", new JScrollPane(ep)); 280 281 ep = new JEditorPane(ei.getSource()); 282 ep.setContentType("text/html"); 283 ep.setEditable(false); 284 tabPane.add("Source", new JScrollPane(ep)); 285 286 for(URL url: ei.getDoc()) 287 { 288 int b = url.getFile().lastIndexOf('/')+1; 289 int e = url.getFile().lastIndexOf(".html"); 290 String name = url.getFile().substring(b,e); 291 if(name.equals("package-summary")) 292 { 293 String aux = url.getFile().substring(0,b-1); 294 int x = aux.lastIndexOf('/')+1; 295 name = aux.substring(x); 296 } 297 tabPane.add("[Doc]"+name, new HTMLBrowser(url)); 298 } 299 } catch (IOException e) 300 { 301 LogManager.getLogger(this.getClass()).error(e.getLocalizedMessage()); 302 } 303 } 304 305 /** 306 * Main method 307 */ 308 public static void main(String[] args) 309 { 310 MainTester main = new MainTester("es/ucm/fdi/gaia/jcolibri/test/main/examples.config"); 311 main.setVisible(true); 312 main.new LogoFrame(es.ucm.fdi.gaia.jcolibri.util.FileIO.findFile("/es/ucm/fdi/gaia/jcolibri/test/main/colibri-cycle-title.png"),2000); 313 314 } 315 316 /** 317 * Parses the information in the config file 318 */ 319 public List<ExampleInfo> parseExampleInfo(String file) 320 { 321 ArrayList<ExampleInfo> info = new ArrayList<ExampleInfo>(); 322 323 try 324 { 325 BufferedReader br = null; 326 br = new BufferedReader( new InputStreamReader(FileIO.findFile(file).openStream())); 327 //if (br == null) 328 // throw new Exception("Error opening file: " + file); 329 String line = ""; 330 ExampleInfo ei; 331 while ((line = br.readLine()) != null) { 332 ei = new ExampleInfo(); 333 ei.setName(line); 334 ei.setDescription(br.readLine()); 335 ei.setMainClass(Class.forName(br.readLine())); 336 ei.setSource(FileIO.findFile(br.readLine())); 337 while(!(line= br.readLine()).equals("<example>")) 338 ei.addDoc(FileIO.findFile(line)); 339 info.add(ei); 340 } 341 br.close(); 342 } catch (Exception e) 343 { 344 LogManager.getLogger(this.getClass()).error(e); 345 } 346 return info; 347 } 348 349 /** 350 * Bean that stores the information in the config file. 351 * @author Juan A. Recio-Garcia 352 * @version 1.0 353 * 354 */ 355 class ExampleInfo 356 { 357 String name; 358 String description; 359 Collection<URL> doc; 360 URL source; 361 Class<?> mainClass; 362 363 public ExampleInfo() 364 { 365 doc = new ArrayList<URL>(); 366 } 367 public ExampleInfo(String name, String description, Collection<URL> doc) 368 { 369 super(); 370 this.name = name; 371 this.description = description; 372 this.doc = doc; 373 } 374 375 376 377 /** 378 * @return Returns the mainClass. 379 */ 380 public Class<?> getMainClass() 381 { 382 return mainClass; 383 } 384 /** 385 * @param mainClass The mainClass to set. 386 */ 387 public void setMainClass(Class<?> mainClass) 388 { 389 this.mainClass = mainClass; 390 } 391 /** 392 * @return Returns the source. 393 */ 394 public URL getSource() 395 { 396 return source; 397 } 398 /** 399 * @param source The source to set. 400 */ 401 public void setSource(URL source) 402 { 403 this.source = source; 404 } 405 /** 406 * @return Returns the description. 407 */ 408 public String getDescription() 409 { 410 return description; 411 } 412 413 /** 414 * @param description The description to set. 415 */ 416 public void setDescription(String description) 417 { 418 this.description = description; 419 } 420 421 /** 422 * @return Returns the doc. 423 */ 424 public Collection<URL> getDoc() 425 { 426 return doc; 427 } 428 429 /** 430 * @param doc The doc to set. 431 */ 432 public void setDoc(Collection<URL> doc) 433 { 434 this.doc = doc; 435 } 436 437 public void addDoc(URL url) 438 { 439 this.doc.add(url); 440 } 441 442 /** 443 * @return Returns the name. 444 */ 445 public String getName() 446 { 447 return name; 448 } 449 450 /** 451 * @param name The name to set. 452 */ 453 public void setName(String name) 454 { 455 this.name = name; 456 } 457 458 459 } 460 461 /** 462 * A HTML browser panel 463 * @author Juan A. Recio-Garcia 464 * @version 1.0 465 * 466 */ 467 class HTMLBrowser extends JPanel 468 { 469 private static final long serialVersionUID = 1L; 470 471 JEditorPane doc; 472 URL originalURL; 473 474 public HTMLBrowser(URL file) 475 { 476 originalURL = file; 477 JPanel top = new JPanel(); 478 top.setLayout(new BoxLayout(top,BoxLayout.X_AXIS)); 479 480 JButton prev = new JButton("Back"); 481 prev.addActionListener(new ActionListener(){ 482 483 public void actionPerformed(ActionEvent e) 484 { 485 try 486 { 487 doc.setPage(originalURL); 488 } catch (IOException e1) 489 { 490 LogManager.getLogger(this.getClass()).error(e1); 491 } 492 } 493 }); 494 495 JLabel urlInfo = new JLabel(file.toString()); 496 497 top.add(prev); 498 top.add(Box.createHorizontalGlue()); 499 top.add(urlInfo); 500 501 doc = new JEditorPane(); 502 doc.setContentType("text/html"); 503 doc.setEditable(false); 504 doc.addHyperlinkListener(new HyperlinkListener() { 505 506 public void hyperlinkUpdate(HyperlinkEvent e) 507 { 508 try 509 { 510 if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) 511 doc.setPage(e.getURL()); 512 513 } catch (IOException e1) 514 { 515 LogManager.getLogger(this.getClass()).error(e1); 516 } 517 } 518 519 }); 520 try 521 { 522 doc.setPage(file); 523 } catch (IOException e) 524 { 525 LogManager.getLogger(this.getClass()).error(e); 526 LogManager.getLogger(this.getClass()).error(file); 527 528 } 529 530 this.setLayout(new BorderLayout()); 531 this.add(top, BorderLayout.NORTH); 532 this.add(new JScrollPane(doc), BorderLayout.CENTER); 533 } 534 535 } 536 537 /** 538 * This class redirects System.out to the log text area. 539 * @author Juan A. Recio-Garcia 540 * @version 1.0 541 */ 542 class FilteredStream extends FilterOutputStream { 543 public FilteredStream(OutputStream aStream) { 544 super(aStream); 545 } 546 547 public void write(byte b[]) throws IOException { 548 String aString = new String(b); 549 displayPane.append(aString); 550 displayPane.setCaretPosition( displayPane.getDocument().getLength() ); 551 } 552 553 public void write(byte b[], int off, int len) throws IOException { 554 String aString = new String(b , off , len); 555 displayPane.append(aString); 556 displayPane.setCaretPosition( displayPane.getDocument().getLength() ); 557 } 558 } 559 560 /** 561 * Shows the logo screen 562 * @author Juan A. Recio-Garcia 563 * @version 1.0 564 * 565 */ 566 public class LogoFrame extends JWindow implements Runnable { 567 private static final long serialVersionUID = 1L; 568 569 long time; 570 public LogoFrame(URL image, long time) throws HeadlessException { 571 try { 572 573 this.time = time; 574 JLabel jLabel1 = new JLabel(); 575 jLabel1.setIcon(new javax.swing.ImageIcon(image)); 576 jLabel1.setBorder(BorderFactory.createRaisedBevelBorder()); 577 this.getContentPane().add(jLabel1, BorderLayout.CENTER); 578 this.pack(); 579 580 java.awt.Dimension screenSize = java.awt.Toolkit 581 .getDefaultToolkit().getScreenSize(); 582 setBounds((screenSize.width - this.getWidth()) / 2, 583 (screenSize.height - this.getHeight()) / 2, getWidth(), 584 getHeight()); 585 586 this.setVisible(true); 587 Thread thread = new Thread(this); 588 thread.start(); 589 } catch (Exception e) { 590 e.printStackTrace(); 591 } 592 } 593 594 public void run() 595 { 596 try 597 { 598 Thread.sleep(2000); 599 } catch (InterruptedException e) 600 { 601 LogManager.getLogger(this.getClass()).error(e); 602 603 } 604 this.dispose(); 605 } 606 } 607}