View Javadoc

1   /*
2    * $Id: XMLHammer.java,v 1.69 2008/03/05 22:13:43 edankert Exp $
3    *
4    * The contents of this file are subject to the Mozilla Public License 
5    * Version 1.1 (the "License"); you may not use this file except in 
6    * compliance with the License. You may obtain a copy of the License at 
7    * http://www.mozilla.org/MPL/ 
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis, 
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
11   * for the specific language governing rights and limitations under the License.
12   *
13   * The Original Code is XML Hammer code. (org.xmlhammer.*)
14   *
15   * The Initial Developer of the Original Code is Edwin Dankert. Portions created 
16   * by the Initial Developer are Copyright (C) 2005 - 2006 the Initial Developer. 
17   * All Rights Reserved.
18   *
19   * Contributor(s): Edwin Dankert <edankert@gmail.com>
20   */
21  
22  package org.xmlhammer.gui;
23  
24  import java.awt.BorderLayout;
25  import java.awt.Color;
26  import java.awt.Component;
27  import java.awt.Cursor;
28  import java.awt.Dimension;
29  import java.awt.Insets;
30  import java.awt.KeyboardFocusManager;
31  import java.awt.Point;
32  import java.awt.event.ActionEvent;
33  import java.awt.event.ActionListener;
34  import java.awt.event.KeyAdapter;
35  import java.awt.event.KeyEvent;
36  import java.awt.event.MouseAdapter;
37  import java.awt.event.WindowAdapter;
38  import java.awt.event.WindowEvent;
39  import java.beans.PropertyChangeEvent;
40  import java.beans.PropertyChangeListener;
41  import java.io.File;
42  import java.io.FileNotFoundException;
43  import java.io.IOException;
44  import java.io.InputStream;
45  import java.io.OutputStream;
46  import java.net.InetAddress;
47  import java.net.ServerSocket;
48  import java.net.Socket;
49  import java.net.URI;
50  import java.net.URISyntaxException;
51  import java.util.ArrayList;
52  import java.util.List;
53  import java.util.Stack;
54  
55  import javax.swing.AbstractAction;
56  import javax.swing.Box;
57  import javax.swing.ImageIcon;
58  import javax.swing.JButton;
59  import javax.swing.JComponent;
60  import javax.swing.JFrame;
61  import javax.swing.JMenu;
62  import javax.swing.JMenuBar;
63  import javax.swing.JOptionPane;
64  import javax.swing.JPanel;
65  import javax.swing.JSplitPane;
66  import javax.swing.JToolBar;
67  import javax.swing.JTree;
68  import javax.swing.KeyStroke;
69  import javax.swing.SwingUtilities;
70  import javax.swing.UIManager;
71  import javax.swing.event.ChangeEvent;
72  import javax.swing.event.ChangeListener;
73  import javax.swing.event.MenuEvent;
74  import javax.swing.event.MenuListener;
75  import javax.swing.plaf.basic.BasicSplitPaneUI;
76  import javax.swing.text.JTextComponent;
77  import javax.xml.bind.JAXBException;
78  import javax.xml.transform.TransformerException;
79  
80  import org.apache.log4j.ConsoleAppender;
81  import org.apache.log4j.FileAppender;
82  import org.apache.log4j.HTMLLayout;
83  import org.apache.log4j.Level;
84  import org.apache.log4j.Logger;
85  import org.apache.log4j.PatternLayout;
86  import org.bounce.MenuUtilities;
87  import org.bounce.image.ImageLoader;
88  import org.bounce.image.ImageUtilities;
89  import org.bounce.util.URIUtils;
90  import org.xmlhammer.Identity;
91  import org.xmlhammer.PreferencesHandler;
92  import org.xmlhammer.gui.actions.CloseAction;
93  import org.xmlhammer.gui.actions.CloseAllAction;
94  import org.xmlhammer.gui.actions.CopyAction;
95  import org.xmlhammer.gui.actions.CutAction;
96  import org.xmlhammer.gui.actions.ExecuteAction;
97  import org.xmlhammer.gui.actions.ExitAction;
98  import org.xmlhammer.gui.actions.FindAction;
99  import org.xmlhammer.gui.actions.HelpContentsAction;
100 import org.xmlhammer.gui.actions.HelpIndexAction;
101 import org.xmlhammer.gui.actions.HelpQuickStartAction;
102 import org.xmlhammer.gui.actions.HelpSearchAction;
103 import org.xmlhammer.gui.actions.HelpTOCAction;
104 import org.xmlhammer.gui.actions.NewCompositeAction;
105 import org.xmlhammer.gui.actions.NewXMLValidatorAction;
106 import org.xmlhammer.gui.actions.OpenAction;
107 import org.xmlhammer.gui.actions.OpenBrowserAction;
108 import org.xmlhammer.gui.actions.OpenPreviousProjectAction;
109 import org.xmlhammer.gui.actions.PageHelpAction;
110 import org.xmlhammer.gui.actions.PasteAction;
111 import org.xmlhammer.gui.actions.PreferencesAction;
112 import org.xmlhammer.gui.actions.PropertiesAction;
113 import org.xmlhammer.gui.actions.RedoAction;
114 import org.xmlhammer.gui.actions.SaveAction;
115 import org.xmlhammer.gui.actions.SaveAllAction;
116 import org.xmlhammer.gui.actions.SaveAsAction;
117 import org.xmlhammer.gui.actions.SelectAllAction;
118 import org.xmlhammer.gui.actions.ShowAboutDialogAction;
119 import org.xmlhammer.gui.actions.StopAction;
120 import org.xmlhammer.gui.actions.UndoAction;
121 import org.xmlhammer.gui.help.HelpPanel;
122 import org.xmlhammer.gui.history.HistoryUtilities;
123 import org.xmlhammer.gui.output.OutputPanel;
124 import org.xmlhammer.gui.output.ResultPanel;
125 import org.xmlhammer.gui.overview.OverviewsPanel;
126 import org.xmlhammer.gui.schemavalidator.NewSchemaValidatorAction;
127 import org.xmlhammer.gui.schemavalidator.SchemaValidatorProjectView;
128 import org.xmlhammer.gui.status.StatusPanel;
129 import org.xmlhammer.gui.stylesheetvalidator.NewStylesheetValidatorAction;
130 import org.xmlhammer.gui.stylesheetvalidator.StylesheetValidatorProjectView;
131 import org.xmlhammer.gui.util.ExtensionClassLoader;
132 import org.xmlhammer.gui.util.ExternalApplicationLauncher;
133 import org.xmlhammer.gui.util.SelectablePanelGroup;
134 import org.xmlhammer.gui.util.UIAppender;
135 import org.xmlhammer.gui.xpath.NewXPathAction;
136 import org.xmlhammer.gui.xpath.XPathSearchProjectView;
137 import org.xmlhammer.gui.xslt.NewXSLTAction;
138 import org.xmlhammer.gui.xslt.XSLTProjectView;
139 import org.xmlhammer.model.preferences.Menu;
140 import org.xmlhammer.model.preferences.Preferences;
141 import org.xmlhammer.model.preferences.Menu.Menuitem;
142 import org.xmlhammer.model.preferences.Preferences.Classpath.Jar;
143 import org.xmlhammer.model.project.Project;
144 
145 import com.apple.eawt.Application;
146 import com.apple.eawt.ApplicationEvent;
147 import com.apple.eawt.ApplicationListener;
148 
149 /***
150  * The main class for the XML Hammer UI. 
151  * 
152  * @version $Revision: 1.69 $, $Date: 2008/03/05 22:13:43 $
153  * @author Edwin Dankert <edankert@gmail.com>
154  */
155 
156 public class XMLHammer extends JFrame {
157 	private static final long serialVersionUID = 3762251941761462835L;
158 
159 	private static final String PREFERENCES_DIR = System.getProperty("user.home")+File.separator+".xmlhammer"+File.separator;
160     public static final String HTML_LOG = PREFERENCES_DIR+"log.html";
161 
162     private static final ImageIcon ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/hammer.gif");
163     private static final ImageIcon CLOSE_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/close.gif");
164     private static final ImageIcon CLOSE_PRESSED_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/close_pressed.gif");
165     private static final ImageIcon CLOSE_ROLLOVER_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/close_rollover.gif");
166 	
167     private ExtensionClassLoader classLoader = null;
168     
169     private Stack<Boolean> threads = null;
170 
171     private UndoAction undoAction = null;
172 	private RedoAction redoAction = null;
173     
174 	private CutAction cutAction = null;
175 	private CopyAction copyAction = null;
176 	private PasteAction pasteAction = null;
177 	private SelectAllAction selectAllAction = null;
178 	private FindAction findAction = null;
179 
180 	// actions...
181     private NewXPathAction newXPathAction = null;
182     private NewXSLTAction newXSLTAction = null;
183     private NewXMLValidatorAction newXMLValidatorAction = null;
184     private NewSchemaValidatorAction newSchemaValidatorAction = null;
185     private NewStylesheetValidatorAction newStylesheetValidatorAction = null;
186     private ShowAboutDialogAction showAboutDialogAction = null;
187 	private OpenAction openAction = null;
188 	private ExitAction exitAction = null;
189 	private SaveAction saveAction = null;
190     private SaveAllAction saveAllAction = null;
191 	private SaveAsAction saveAsAction = null;
192 	private CloseAction closeAction = null;
193 	private CloseAllAction closeAllAction = null;
194 	private PropertiesAction propertiesAction = null;
195 	private ExecuteAction executeAction = null;
196 	private PreferencesAction preferencesAction = null;
197     private StopAction stopAction = null;
198     
199     private HelpSearchAction helpSearchAction = null;
200     private HelpIndexAction helpIndexAction = null;
201     private HelpTOCAction helpTOCAction = null;
202     private HelpQuickStartAction helpQuickStartAction = null;
203     private HelpContentsAction helpContentsAction = null;
204     private PageHelpAction dynamicHelpAction = null;
205 		
206 	private WaitGlassPane waitPane = null;
207 	private ProjectsView projectsView = null;
208     private StatusPanel statusPanel = null;
209     private HelpPanel helpPanel = null;
210     private JPanel workPanel = null;
211 
212 	private OutputPanel outputPanel = null;
213 	
214 	private JSplitPane split = null;
215 	private JSplitPane horizontalSplit = null;
216     private JSplitPane helpSplit = null;
217 	
218 	private JMenu fileMenu = null;
219     
220     private JComponent lastSelectedComponent = null;
221     
222     private OverviewsPanel overviewsPanel = null;
223     
224     /***
225 	 * XMLHammer constructor.
226 	 */
227 	public XMLHammer(boolean splashEnabled) {
228         threads = new Stack<Boolean>();
229         
230         classLoader = new ExtensionClassLoader(getClass().getClassLoader());
231         updateExtensionClassPath();
232 
233         Thread.currentThread().setContextClassLoader( classLoader);
234 
235         // Set the context class loader on the AWT event dispatch thread, to be used by 
236         // all threads created from this thread!
237         SwingUtilities.invokeLater( new Runnable() {
238             public void run() {
239                 Thread.currentThread().setContextClassLoader( classLoader);
240             }
241         });
242         
243         Splash splash = null;
244         
245         if (splashEnabled) {
246             // Start the splash screen...
247             splash = new Splash(this, Identity.getInstance(), ImageUtilities.createSilhouetteImage(ICON, new Color(255, 255, 255)));
248             splash.setForeground(new Color( 51, 102, 153));
249             splash.setBackground(new Color( 255, 255, 255));
250             splash.setSize(450, 250);
251     
252             splash.start();
253     
254             // Load properties.
255             splash.showStatus("Loading preferences ...", 0);
256         }
257 
258         setupUIAppender();
259         
260 		Preferences preferences = PreferencesHandler.getInstance().getPreferences();
261         String laf = preferences.getLaf();
262         
263         if (laf != null && laf.length() > 0) {
264             try {
265                 UIManager.setLookAndFeel(laf);
266                 UIManager.getLookAndFeelDefaults().put("ClassLoader", classLoader);
267             } catch (Exception e) {
268                 Logger.getLogger("org.xmlhammer.gui.XMLHammer").error(e);
269             }
270         }
271 
272         PreferencesHandler.getInstance().updateProxy();
273         PreferencesHandler.getInstance().updateCatalogProperties();
274         
275         ExternalApplicationLauncher.getInstance().setBrowserExtensions(preferences.getExternalApplication().getBrowserExtensions());
276         ExternalApplicationLauncher.getInstance().setDefaultCommand(preferences.getExternalApplication().getDefaultCommand());
277         ExternalApplicationLauncher.getInstance().setEditorCommand(preferences.getExternalApplication().getEditorCommand());
278 
279         if (splashEnabled) {
280             splash.showStatus("Creating user-interface ...", 10);
281         }
282 
283         waitPane = new WaitGlassPane();
284         setGlassPane(waitPane);
285 
286         overviewsPanel = new OverviewsPanel();
287 		projectsView = new ProjectsView( this);
288 		outputPanel = new OutputPanel();
289         statusPanel = new StatusPanel();
290 		
291 		SelectablePanelGroup group = new SelectablePanelGroup();
292 		group.add( projectsView);
293 		group.add( outputPanel);
294 		group.add( overviewsPanel);
295         
296         getRootPane().getActionMap().put("helpAction", new AbstractAction() {
297             private static final long serialVersionUID = -6931927193561857562L;
298 
299             public void actionPerformed(ActionEvent e) {
300                 showContextHelp();
301             }
302         });
303         getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0, false), "helpAction");
304 
305         workPanel = new JPanel(new BorderLayout());
306         workPanel.add(projectsView, BorderLayout.CENTER);
307         
308 		horizontalSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, overviewsPanel, workPanel);
309 		horizontalSplit.setResizeWeight( 0);
310         horizontalSplit.setOneTouchExpandable( true);
311 
312 		Object ui = horizontalSplit.getUI();
313 		if (ui instanceof BasicSplitPaneUI) {
314 			((BasicSplitPaneUI)ui).getDivider().setBorder(null);
315             ((BasicSplitPaneUI)ui).getDivider().setDividerSize(((BasicSplitPaneUI)ui).getDivider().getDividerSize()-4);
316 		}
317 		horizontalSplit.setBorder( null);
318 		horizontalSplit.setDividerLocation( preferences.getFrame().getSplit().getHorizontal());
319 
320 		split = new JSplitPane( JSplitPane.VERTICAL_SPLIT, horizontalSplit, outputPanel);
321 		split.setResizeWeight( 1);
322         split.setOneTouchExpandable( true);
323 
324 		ui = split.getUI();
325 		if (ui instanceof BasicSplitPaneUI) {
326 			((BasicSplitPaneUI) ui).getDivider().setBorder(null);
327             ((BasicSplitPaneUI)ui).getDivider().setDividerSize(((BasicSplitPaneUI)ui).getDivider().getDividerSize()-4);
328 		}
329 		split.setBorder( null);
330 		split.setDividerLocation( preferences.getFrame().getSplit().getVertical());
331 		
332         if (splashEnabled) {
333             splash.showStatus("Positioning user-interface ...", 20);
334         }
335 
336         setSize( new Dimension( preferences.getFrame().getWidth(), preferences.getFrame().getHeight()));
337 		setLocation( new Point( preferences.getFrame().getXPos(), preferences.getFrame().getYPos()));
338 		
339 		setTitle("XML Hammer");
340 		setIconImage(ICON.getImage());
341         
342         if (splashEnabled) {
343             splash.showStatus("Creating menu-bar ...", 30);
344         }
345         
346 		setJMenuBar(createMenuBar());
347 		
348         if (splashEnabled) {
349             splash.showStatus("Creating tool-bar ...", 40);
350         }
351         
352         JPanel main = new JPanel( new BorderLayout());
353 
354         main.add( createToolBar(), BorderLayout.NORTH);
355 		main.add( split, BorderLayout.CENTER);
356         
357         main.add( statusPanel, BorderLayout.SOUTH);
358 		
359 		projectsView.addChangeListener( new ChangeListener() {
360 			public void stateChanged( ChangeEvent e) {
361 				ProjectView view = projectsView.getSelectedView();
362                 updateTitle();
363 				
364 				if ( view != null) {
365                     outputPanel.showView( view);
366 					overviewsPanel.showView( view);
367                     statusPanel.showView( view);
368 
369                     getHelpPanel().showID(view.getSelectedPage().getHelpID());
370 					
371                     getSaveAction().setEnabled(true);					
372                     getSaveAllAction().setEnabled(true);                   
373 
374 					getUndoAction().setView(view);
375                     getRedoAction().setView(view);
376 					getSaveAsAction().setEnabled(true);
377 					getStopAction().setModuleThread(view.getModuleThread());
378                     getExecuteAction().setModuleThread(view.getModuleThread());
379 					getCloseAction().setEnabled(true);
380 					getCloseAllAction().setEnabled(true);
381 					getPropertiesAction().setEnabled(true);
382 					getCopyAction().setEnabled(true);
383 					getCutAction().setEnabled(true);
384 					getPasteAction().setEnabled(true);
385 					getSelectAllAction().setEnabled(true);
386 				} else {
387                     getSaveAction().setEnabled(false);
388                     getSaveAllAction().setEnabled(false);
389 					getSaveAsAction().setEnabled(false);
390 					getExecuteAction().setEnabled(false);
391 					getStopAction().setModuleThread(null);
392 					getCloseAction().setEnabled(false);
393 					getCloseAllAction().setEnabled(false);
394 					getPropertiesAction().setEnabled(false);
395 					getCopyAction().setEnabled(false);
396 					getCutAction().setEnabled(false);
397 					getPasteAction().setEnabled(false);
398 					getSelectAllAction().setEnabled(false);
399                     getRedoAction().setView(null);
400 					getUndoAction().setView(null);
401 				}
402 			}
403 		});
404 
405         if (splashEnabled) {
406             splash.showStatus("Setting content-pane ...", 50);
407         }
408         
409 		setContentPane( main);
410 		
411 		addWindowListener( new WindowAdapter() {
412             @Override
413             public void windowActivated(WindowEvent event) {
414                 Logger.getLogger(getClass()).debug("windowActivated("+event+")");
415                 
416                 ProjectView view = getProjectsView().getSelectedView();
417                 if (view != null) {
418                     view.checkForUpdate();
419                 }
420             }
421 
422             @Override
423             public void windowClosing( WindowEvent event) {
424 				stop();
425 			}
426 		});
427         
428         setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
429         
430         KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
431 
432         focusManager.addPropertyChangeListener( "permanentFocusOwner", 
433             new PropertyChangeListener() {
434                 public void propertyChange(PropertyChangeEvent e) {
435                     Component comp = (Component)e.getNewValue();
436                     
437                     if (comp instanceof JTextComponent) {
438                         lastSelectedComponent = (JComponent)comp;
439 
440                         getCopyAction().setEnabled(true);
441                         getSelectAllAction().setEnabled(true);
442                         getCutAction().setEnabled(true);
443                         getPasteAction().setEnabled(true);
444                     } else if (comp instanceof JTree) {
445                         Component parent = comp.getParent();
446                         
447                         while (parent != null && !(parent instanceof ResultPanel)) {
448                             parent = parent.getParent();
449                         }
450                         
451                         if (parent != null) {
452                             lastSelectedComponent = (JComponent)parent;
453 
454                             getCopyAction().setEnabled(true);
455                             getSelectAllAction().setEnabled(false);
456                             getCutAction().setEnabled(false);
457                             getPasteAction().setEnabled(false);
458                         } else {
459                             lastSelectedComponent = null;
460 
461                             getCopyAction().setEnabled(false);
462                             getSelectAllAction().setEnabled(false);
463                             getCutAction().setEnabled(false);
464                             getPasteAction().setEnabled(false);
465                         }
466                     } else if (comp != null) {
467                         Component parent = comp;
468 
469                         while (parent != null) {
470                             if (parent instanceof JToolBar) {
471                                 return;
472                             }
473 
474                             parent = parent.getParent();
475                         }
476                         
477                         getCopyAction().setEnabled(false);
478                         getSelectAllAction().setEnabled(false);
479                         getCutAction().setEnabled(false);
480                         getPasteAction().setEnabled(false);
481 
482                         lastSelectedComponent = null;
483                     }
484                 }
485             }
486         );
487         
488         List<String> paths = preferences.getViews().getView();
489         int openedProjects = 0;
490         
491         for (int i = 0; i < paths.size(); i++) {
492             URI uri = URIUtils.createURI(paths.get(i));
493             
494             if (splashEnabled) {
495                 splash.showStatus("Loading "+URIUtils.getName(uri)+" ...", 50 + ((50/paths.size()+1)*i+1));
496             }
497             
498             try {
499             	open(uri, false);
500             	openedProjects++;
501             } catch (JAXBException e) {
502             	Logger.getLogger(XMLHammer.class).error("JAXB Error", e);
503             } catch (TransformerException e) {
504             	Logger.getLogger(XMLHammer.class).error("Transformer Error", e);
505             }
506         }
507         
508         if (preferences.getViews().getSelected() != null && openedProjects > preferences.getViews().getSelected()) {
509             getProjectsView().setSelectedViewIndex(preferences.getViews().getSelected());
510         }
511         
512         // For Mac OSX
513         if (System.getProperty("mrj.version") != null) {
514             new ApplicationAdapter(this);
515         }
516         
517         if (splashEnabled) {
518             splash.showStatus( "Finished.", 100);
519             splash.stop( 3000);
520         }
521 	}
522     
523     private void setupUIAppender() {
524         Logger.getRootLogger().addAppender(new UIAppender( this));
525     }
526 
527     private static void setupGlobalAppenders() {
528         Logger logger = Logger.getRootLogger();
529         try {
530             logger.setLevel(Level.DEBUG);
531             logger.addAppender(new FileAppender(new PatternLayout("%r [%t] %-5p %c - %m%n"), PREFERENCES_DIR+"log.txt", false));
532             logger.addAppender(new FileAppender(new HTMLLayout(), HTML_LOG, false));
533         } catch (IOException e) {
534             logger.addAppender(new ConsoleAppender(new PatternLayout("%r [%t] %-5p %c - %m%n"), "System.err"));
535             Logger.getLogger(XMLHammer.class).error("Unable to create Log file. Logging to console instead.", e);
536         }
537     }
538     
539     public void updateTitle() {
540         ProjectView view = projectsView.getSelectedView();
541         
542         if (view != null) {
543             String name = view.getName();
544             
545             if (view.isChanged()) {
546                 name = "*"+name;
547             }
548 
549             setTitle(name+" - XML Hammer");
550         } else {
551             setTitle("XML Hammer");
552         }
553     }
554     
555 	/***
556 	 * Returns the last selected component in a view.
557 	 * 
558 	 * @return the last selected component.
559 	 */
560     public JComponent getLastSelectedComponent() {
561         return lastSelectedComponent;
562     }
563     
564     /***
565      * Fires a WINDOW_CLOSING event.
566      */
567 	public void fireClosingEvent() {
568 		processWindowEvent( new WindowEvent( this, WindowEvent.WINDOW_CLOSING));
569 	}
570 	
571     private void open(String path) throws TransformerException, JAXBException {
572         Logger.getLogger(this.getClass()).debug("open("+path+")");
573 
574         File file = new File(path);
575         
576         open(file.toURI(), true);
577         
578         toFront();
579     }
580 
581     private void open(URI uri, boolean history) throws TransformerException, JAXBException {
582         Logger.getLogger(this.getClass()).debug("open("+uri+")");
583         
584         openProject(uri, OpenAction.open(uri), history);
585     }
586 
587     /***
588      * Opens a new project.
589      * 
590      * Leave both uri and project null to create a new project.
591      * 
592      * @param uri the uri of the project document.
593      * @param project the project.
594      */
595     public void openProject(URI uri, Project project) {
596         openProject(uri, project, true);
597     }
598 
599 	private void openProject(URI uri, Project project, boolean history) {
600         Logger.getLogger(this.getClass()).debug("openProject( "+uri+", "+project+")");
601 
602         if (history) {
603             HistoryUtilities.getInstance().addOpenedProject(uri);
604         }
605 		
606 		for ( int i = 0; i < projectsView.getViewCount(); i++) { 
607 			ProjectView panel = projectsView.getViewAt( i);
608 			
609             if ( panel.getURI() != null && panel.getURI().equals( uri)) { // already open!
610                 projectsView.setSelectedViewIndex(i);
611 				return;
612 			}
613 		}
614 
615 		ProjectView view = createView( projectsView, project, uri);
616         
617         if (view != null) {
618     		outputPanel.addView( view);
619     		overviewsPanel.addView( view);
620     		projectsView.addView( view);
621             statusPanel.addView( view);
622     
623             try {
624                 view.setProject( project);
625             } catch (Exception e) {
626                 // could not load the project!
627                 Logger.getLogger("org.xmlhammer.gui.XMLHammer").debug(e);
628             }
629         }
630 	}
631 
632 	public void removeView( ProjectView view) {
633         Logger.getLogger(this.getClass()).debug("removeView("+view.getName()+")");
634 
635         if (view.getURI() != null) {
636             PreferencesHandler.getInstance().getPreferences().getViews().getView().add(0, URIUtils.toString(view.getURI()));
637         }
638 
639         projectsView.removeView( view);
640 		outputPanel.removeView( view);
641 		overviewsPanel.removeView( view);
642         statusPanel.removeView( view);
643         
644         view.dispose();
645 	}
646 
647 	/***
648 	 * @return the projects view.
649 	 */
650     public ProjectsView getProjectsView() {
651         return projectsView;
652     }
653 
654     /***
655      * @return the help panel.
656      */
657     public HelpPanel getHelpPanel() {
658         if (helpPanel == null) {
659             helpPanel = new HelpPanel();
660             helpPanel.addCloseActionListener(new ActionListener() {
661                 public void actionPerformed(ActionEvent arg0) {
662                     hideHelpPanel();
663                 }
664             });
665         }
666         
667         return helpPanel;
668     }
669 
670     public void showContextHelp() {
671         showHelpPanel();
672         getHelpPanel().showContext();
673     }
674 
675     public void showHelpContents() {
676         showHelpPanel();
677         getHelpPanel().showContents();
678     }
679 
680     public void showHelpQuickStart() {
681         showHelpPanel();
682         getHelpPanel().showQuickStart();
683     }
684 
685     public void showHelpSearch() {
686         showHelpPanel();
687         getHelpPanel().showSearch();
688     }
689 
690     public void showHelpIndex() {
691         showHelpPanel();
692         getHelpPanel().showIndex();
693     }
694 
695     public void showHelpTOC() {
696         showHelpPanel();
697         getHelpPanel().showTOC();
698     }
699 
700     /***
701      * Show the help panel (preferred-size) if not already shown.
702      */
703     private void showHelpPanel() {
704         if (helpSplit == null) {
705             helpSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, projectsView, getHelpPanel());
706             helpSplit.setResizeWeight(1);
707             helpSplit.setOneTouchExpandable(true);
708             Object ui = helpSplit.getUI();
709             if (ui instanceof BasicSplitPaneUI) {
710                 ((BasicSplitPaneUI)ui).getDivider().setBorder(null);
711                 ((BasicSplitPaneUI)ui).getDivider().setDividerSize(((BasicSplitPaneUI)ui).getDivider().getDividerSize()-4);
712             }
713             helpSplit.setBorder(null);
714             
715             workPanel.add(helpSplit, BorderLayout.CENTER);
716             workPanel.revalidate();
717             workPanel.repaint();
718 
719             int location = PreferencesHandler.getInstance().getPreferences().getFrame().getSplit().getHelp();
720             
721             if (location > 0) {
722                 helpSplit.setDividerLocation(location);
723             } else {
724                 helpSplit.setDividerLocation(helpSplit.getDividerLocation() - getHelpPanel().getPreferredSize().width);
725             }
726         }
727     }
728 
729     public void hideHelpPanel() {
730         updateHelpSplitPreferences();
731         helpSplit = null;
732         
733         workPanel.removeAll();
734         workPanel.add(projectsView, BorderLayout.CENTER);
735         workPanel.revalidate();
736         workPanel.repaint();
737         
738         this.transferFocus();
739     }
740 
741     private void updateHelpSplitPreferences() {
742         if (getHelpPanel().isVisible() && getHelpPanel().getSize().width > 10 && helpSplit != null) {
743             PreferencesHandler.getInstance().getPreferences().getFrame().getSplit().setHelp(helpSplit.getDividerLocation());            
744         }
745     }
746 
747     /***
748      * @return the status panel.
749      */
750     public StatusPanel getStatusPanel() {
751         return statusPanel;
752     }
753 
754     /***
755 	 * Sets the wait cursor on the XMLToolBox Frame.
756 	 *
757 	 * @param enabled true when wait is enabled.
758 	 */
759 	public void setWait(final boolean enabled) {
760         if (enabled) {
761             threads.push(enabled);
762         } else {
763             threads.pop();
764         }
765 
766         if (enabled || threads.size() == 0) {
767             SwingUtilities.invokeLater(new Runnable() {
768     			public void run() {
769     				waitPane.setVisible(enabled);
770     			}
771     		});
772         }
773 	}
774     
775     public void firePreferrencesUpdated() {
776         updateExtensionClassPath();
777         PreferencesHandler.getInstance().updateProxy();
778         PreferencesHandler.getInstance().updateCatalogProperties();
779         
780         ExternalApplicationLauncher.getInstance().setBrowserExtensions(
781                 PreferencesHandler.getInstance().getPreferences().getExternalApplication().getBrowserExtensions());
782         ExternalApplicationLauncher.getInstance().setDefaultCommand(
783                 PreferencesHandler.getInstance().getPreferences().getExternalApplication().getDefaultCommand());
784         ExternalApplicationLauncher.getInstance().setEditorCommand(
785                 PreferencesHandler.getInstance().getPreferences().getExternalApplication().getEditorCommand());
786 
787         projectsView.firePreferencesUpdated();
788     }
789     
790 	private JMenuBar createMenuBar() {
791 		JMenuBar menubar = new JMenuBar();
792 		menubar.add( createFileMenu());
793 		menubar.add( createEditMenu());
794 		menubar.add( createToolsMenu());
795 		menubar.add( createHelpMenu());
796 
797         if (System.getProperty("mrj.version") == null) {
798             menubar.add( Box.createHorizontalGlue());
799             JButton button = new JButton(getCloseAction());
800             button.setIcon( CLOSE_ICON);
801             button.setPressedIcon( CLOSE_PRESSED_ICON);
802             button.setRolloverIcon( CLOSE_ROLLOVER_ICON);
803             button.setText("");
804             button.setMargin(new Insets( 0, 0, 0, 0));
805             button.setBounds(0, 0, 0, 0);
806             menubar.add(button);
807         }
808 		return menubar;
809 	}
810 
811 	// create the menu bar...
812 	private JMenu createFileMenu() {
813 		// >>> File Menu
814 		fileMenu = new JMenu("File");
815 		fileMenu.setMnemonic('F');
816 		fileMenu.addMenuListener(new MenuListener() {
817 			public void menuCanceled(MenuEvent e) {
818 			}
819 			public void menuSelected(MenuEvent e) {
820 				updateFileMenu();
821 			}
822 			public void menuDeselected(MenuEvent e) {
823 			}
824 		});
825 
826 		updateFileMenu();
827 
828 		// <<< File Menu
829 		return fileMenu;
830 	}
831 
832 	private JMenu createToolsMenu() {
833 		JMenu toolsMenu = new JMenu( "Tools");
834 		toolsMenu.setMnemonic( 'T');
835 
836 		toolsMenu.add( getExecuteAction());
837 		toolsMenu.add( getStopAction());
838 		toolsMenu.addSeparator();
839 		toolsMenu.add( getPreferencesAction());
840 
841 		MenuUtilities.alignMenu( toolsMenu);
842 
843 		return toolsMenu;
844 	}
845 
846 	private JMenu createEditMenu() {
847 		JMenu editMenu = new JMenu( "Edit");
848 		editMenu.setMnemonic( 'E');
849 		editMenu.add( getUndoAction());
850 		editMenu.add( getRedoAction());
851 		editMenu.addSeparator();
852 		editMenu.add( getCutAction());
853 		editMenu.add( getCopyAction());
854 		editMenu.add( getPasteAction());
855 		editMenu.add( getSelectAllAction());
856 		editMenu.addSeparator();
857 		editMenu.add( getFindAction());
858 
859 		MenuUtilities.alignMenu( editMenu);
860 
861 		return editMenu;
862 	}
863 
864 	private JMenu createHelpMenu() {
865 		JMenu helpMenu = new JMenu( "Help");
866 		helpMenu.setMnemonic( 'H');
867         
868         helpMenu.add(getHelpContentsAction());
869         helpMenu.add(getDynamicHelpAction());
870         helpMenu.add(getHelpQuickStartAction());
871         helpMenu.addSeparator();
872         helpMenu.add(getHelpTOCAction());
873         helpMenu.add(getHelpIndexAction());
874         helpMenu.add(getHelpSearchAction());
875         helpMenu.addSeparator();
876 
877         List<Menu> menusPrefs = PreferencesHandler.getInstance().getPreferences().getHelpmenu().getMenu();
878         for (Menu menuPref : menusPrefs) {
879             JMenu menu = new JMenu(menuPref.getTitle());
880             
881             for (Menuitem item : menuPref.getMenuitem()) {
882                 try {
883                     menu.add(new OpenBrowserAction(item.getTitle(), new URI(item.getSrc())));
884                 } catch (URISyntaxException e) {
885                     // do not add the item!
886                     Logger.getLogger(getClass()).debug(e);
887                 }
888             }
889             
890             helpMenu.add(menu);
891         }
892 
893         helpMenu.addSeparator();
894 		helpMenu.add(getShowAboutDialogAction());
895 
896         MenuUtilities.alignMenu(helpMenu);
897 
898         return helpMenu;
899 	}
900 
901 	private void updateFileMenu() {
902 		if (fileMenu.getItemCount() > 0) {
903 			fileMenu.removeAll();
904 		}
905 
906         JMenu newMenu = new JMenu( "New");
907         newMenu.setMnemonic( 'N');
908         newMenu.add(getNewXMLValidatorAction());
909         newMenu.add(getNewXPathAction());
910         newMenu.add(getNewXSLTAction());
911         newMenu.add(getNewSchemaValidatorAction());
912         newMenu.add(getNewStylesheetValidatorAction());
913         
914 		fileMenu.add( newMenu);
915 		fileMenu.add( getOpenAction());
916 		fileMenu.add( getCloseAction());
917 		fileMenu.add( getCloseAllAction());
918 		fileMenu.addSeparator();
919 		fileMenu.add( getSaveAction());
920 		fileMenu.add( getSaveAsAction());
921         fileMenu.add( getSaveAllAction());
922 		fileMenu.addSeparator();
923 		fileMenu.add( getPropertiesAction());
924 
925 		Preferences prefs = PreferencesHandler.getInstance().getPreferences();
926 		List<String> links = prefs.getHistory().getProjects().getValue();
927 
928 		if ( links.size() > 0) {
929 			fileMenu.addSeparator();
930 			int index = 1;
931 
932 			for ( String link: links) {
933 				URI uri = null;
934 
935 				try {
936                     uri = URIUtils.createURI( link);
937                 } catch (IllegalArgumentException e) {
938                     Logger.getLogger(this.getClass()).error("URI Syntax Exception", e);
939                 }
940 
941 				fileMenu.add( new OpenPreviousProjectAction( this, uri, index));
942 				index++;
943 			}
944 		}
945 
946 		fileMenu.addSeparator();
947 		fileMenu.add( getExitAction());
948 		
949 		MenuUtilities.alignMenu( fileMenu);
950 	}
951 
952 //	private NewAction getNewAction() {
953 //		if ( newAction == null) {
954 //			newAction = new NewAction( this);
955 //		}
956 //		
957 //		return newAction;
958 //	}
959 
960     public NewXPathAction getNewXPathAction() {
961         if ( newXPathAction == null) {
962             newXPathAction = new NewXPathAction( this);
963         }
964         
965         return newXPathAction;
966     }
967 
968     public NewXSLTAction getNewXSLTAction() {
969         if (newXSLTAction == null) {
970             newXSLTAction = new NewXSLTAction( this);
971         }
972         
973         return newXSLTAction;
974     }
975 
976     public NewXMLValidatorAction getNewXMLValidatorAction() {
977         if ( newXMLValidatorAction == null) {
978             newXMLValidatorAction = new NewXMLValidatorAction( this);
979         }
980         
981         return newXMLValidatorAction;
982     }
983 
984     public NewSchemaValidatorAction getNewSchemaValidatorAction() {
985         if ( newSchemaValidatorAction == null) {
986             newSchemaValidatorAction = new NewSchemaValidatorAction( this);
987         }
988         
989         return newSchemaValidatorAction;
990     }
991 
992     public NewStylesheetValidatorAction getNewStylesheetValidatorAction() {
993         if (newStylesheetValidatorAction == null) {
994             newStylesheetValidatorAction = new NewStylesheetValidatorAction( this);
995         }
996         
997         return newStylesheetValidatorAction;
998     }
999 
1000     public OpenAction getOpenAction() {
1001 		if ( openAction == null) {
1002 			openAction = new OpenAction( this);
1003 		}
1004 		
1005 		return openAction;
1006 	}
1007 
1008 	public SaveAction getSaveAction() {
1009 		if ( saveAction == null) {
1010 			saveAction = new SaveAction( this);
1011 		}
1012 		
1013 		return saveAction;
1014 	}
1015 
1016     public SaveAllAction getSaveAllAction() {
1017         if ( saveAllAction == null) {
1018             saveAllAction = new SaveAllAction( this);
1019         }
1020         
1021         return saveAllAction;
1022     }
1023 
1024     public CloseAction getCloseAction() {
1025 		if ( closeAction == null) {
1026 			closeAction = new CloseAction( this);
1027 		}
1028 		
1029 		return closeAction;
1030 	}
1031 
1032 	public CloseAllAction getCloseAllAction() {
1033 		if ( closeAllAction == null) {
1034 			closeAllAction = new CloseAllAction( this);
1035 		}
1036 		
1037 		return closeAllAction;
1038 	}
1039 
1040 	public SaveAsAction getSaveAsAction() {
1041 		if ( saveAsAction == null) {
1042 			saveAsAction = new SaveAsAction( this);
1043 		}
1044 		
1045 		return saveAsAction;
1046 	}
1047 
1048     public ExitAction getExitAction() {
1049 		if ( exitAction == null) {
1050 			exitAction = new ExitAction( this);
1051 		}
1052 		
1053 		return exitAction;
1054 	}
1055 
1056 	public ExecuteAction getExecuteAction() {
1057 		if ( executeAction == null) {
1058 			executeAction = new ExecuteAction( this);
1059 		}
1060 		
1061 		return executeAction;
1062 	}
1063 
1064     public PreferencesAction getPreferencesAction() {
1065 		if ( preferencesAction == null) {
1066 			preferencesAction = new PreferencesAction( this);
1067 		}
1068 		
1069 		return preferencesAction;
1070 	}
1071 
1072     public ShowAboutDialogAction getShowAboutDialogAction() {
1073         if (showAboutDialogAction == null) {
1074             showAboutDialogAction = new ShowAboutDialogAction(this);
1075         }
1076         
1077         return showAboutDialogAction;
1078     }
1079 
1080     /***
1081 	 * @return the stop action.
1082 	 */
1083 	public StopAction getStopAction() {
1084         if ( stopAction == null) {
1085             stopAction = new StopAction();
1086         }
1087         
1088         return stopAction;
1089     }
1090 
1091 	/***
1092 	 * @return the undo action.
1093 	 */
1094     public UndoAction getUndoAction() {
1095         if ( undoAction == null) {
1096             undoAction = new UndoAction();
1097         }
1098         
1099         return undoAction;
1100     }
1101 
1102     public RedoAction getRedoAction() {
1103         if ( redoAction == null) {
1104             redoAction = new RedoAction();
1105         }
1106         
1107         return redoAction;
1108     }
1109 
1110     public CutAction getCutAction() {
1111         if ( cutAction == null) {
1112         	cutAction = new CutAction( this);
1113         }
1114         
1115         return cutAction;
1116     }
1117 
1118     public CopyAction getCopyAction() {
1119         if ( copyAction == null) {
1120         	copyAction = new CopyAction( this);
1121         }
1122         
1123         return copyAction;
1124     }
1125 
1126     public PasteAction getPasteAction() {
1127         if ( pasteAction == null) {
1128         	pasteAction = new PasteAction( this);
1129         }
1130         
1131         return pasteAction;
1132     }
1133 
1134     public SelectAllAction getSelectAllAction() {
1135         if ( selectAllAction == null) {
1136         	selectAllAction = new SelectAllAction( this);
1137         }
1138         
1139         return selectAllAction;
1140     }
1141 
1142     public FindAction getFindAction() {
1143         if ( findAction == null) {
1144         	findAction = new FindAction(this);
1145         }
1146         
1147         return findAction;
1148     }
1149 
1150     public PropertiesAction getPropertiesAction() {
1151 		if ( propertiesAction == null) {
1152 			propertiesAction = new PropertiesAction( this);
1153 		}
1154 		
1155 		return propertiesAction;
1156 	}
1157 
1158     public HelpSearchAction getHelpSearchAction() {
1159         if (helpSearchAction == null) {
1160             helpSearchAction = new HelpSearchAction(this);
1161         }
1162         
1163         return helpSearchAction;
1164     }
1165 
1166     public HelpTOCAction getHelpTOCAction() {
1167         if (helpTOCAction == null) {
1168             helpTOCAction = new HelpTOCAction(this);
1169         }
1170         
1171         return helpTOCAction;
1172     }
1173 
1174     public HelpContentsAction getHelpContentsAction() {
1175         if (helpContentsAction == null) {
1176             helpContentsAction = new HelpContentsAction(this);
1177         }
1178         
1179         return helpContentsAction;
1180     }
1181 
1182     public HelpQuickStartAction getHelpQuickStartAction() {
1183         if (helpQuickStartAction == null) {
1184             helpQuickStartAction = new HelpQuickStartAction(this);
1185         }
1186         
1187         return helpQuickStartAction;
1188     }
1189 
1190     public HelpIndexAction getHelpIndexAction() {
1191         if (helpIndexAction == null) {
1192             helpIndexAction = new HelpIndexAction(this);
1193         }
1194         
1195         return helpIndexAction;
1196     }
1197 
1198     public PageHelpAction getDynamicHelpAction() {
1199         if (dynamicHelpAction == null) {
1200             dynamicHelpAction = new PageHelpAction(this);
1201         }
1202         
1203         return dynamicHelpAction;
1204     }
1205 
1206     //
1207 	private class WaitGlassPane extends JPanel {
1208 		private static final long serialVersionUID = 3689065127823422257L;
1209 
1210 		/***
1211 		 * A Glass pane that can be used to show a wait cursor.
1212 		 */
1213 		public WaitGlassPane() {
1214 			setOpaque(false);
1215 			addKeyListener(new KeyAdapter() {});
1216 			addMouseListener( new MouseAdapter() {});
1217 			super.setCursor( Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1218 		}
1219 	}
1220 		
1221 	private JToolBar createToolBar() {
1222 		JToolBar toolbar = new JToolBar();
1223 		toolbar.setFloatable(false);
1224 		toolbar.setRollover(true);
1225         
1226         NewCompositeAction action = new NewCompositeAction();
1227 
1228         action.add(getNewXMLValidatorAction());
1229         action.add(getNewXPathAction());
1230         action.add(getNewXSLTAction());
1231         action.add(getNewSchemaValidatorAction());
1232         action.add(getNewStylesheetValidatorAction());
1233         
1234         toolbar.add(action);
1235 //		toolbar.add(getNewXPathAction());
1236 //        toolbar.add(getNewXSLTAction());
1237 //        toolbar.add(getNewSchemaValidatorAction());
1238 
1239         toolbar.addSeparator();
1240 		
1241         toolbar.add(getOpenAction());
1242 		toolbar.add(getSaveAction());
1243 		toolbar.add(getSaveAsAction());
1244 		
1245         toolbar.addSeparator();
1246         toolbar.add( getUndoAction());
1247         toolbar.add( getRedoAction());
1248         toolbar.addSeparator();
1249         toolbar.add( getCutAction());
1250         toolbar.add( getCopyAction());
1251         toolbar.add( getPasteAction());
1252         toolbar.addSeparator();
1253 //        editMenu.add( getSelectAllAction());
1254 
1255         JButton execute = toolbar.add( getExecuteAction());
1256         execute.setText( "Execute");
1257         execute.setHorizontalTextPosition( JButton.RIGHT);
1258         
1259         JButton stop = toolbar.add( getStopAction());
1260         stop.setText( "Stop");
1261         stop.setHorizontalTextPosition( JButton.RIGHT);
1262 		
1263 		return toolbar;
1264 	}
1265 
1266 	private void stop() {
1267         Preferences preferences = PreferencesHandler.getInstance().getPreferences();
1268         preferences.getViews().getView().clear();
1269         preferences.getViews().setSelected(getProjectsView().getSelectedViewIndex());
1270         
1271         if (CloseAllAction.execute(this) == JOptionPane.CANCEL_OPTION) {
1272             return;
1273         }
1274 
1275         // Make sure all views have been closed!
1276 		while (getProjectsView().getViewCount() > 0) {
1277             try {
1278                 Thread.sleep(100);
1279             } catch (InterruptedException e) {
1280                 // do nothing
1281             }
1282         }
1283         
1284         try {
1285             PreferencesHandler.getInstance().storePreferences(this, split, horizontalSplit);
1286             updateHelpSplitPreferences();
1287         } catch ( JAXBException e) {
1288             Logger.getLogger(this.getClass()).error("JAXB Error", e);
1289         } catch ( FileNotFoundException e) {
1290             Logger.getLogger(this.getClass()).error("File Not Found Error", e);
1291         }
1292 
1293         exit(0);
1294 	}
1295     
1296     protected void exit(int level) {
1297         System.exit(level);
1298     }
1299 
1300     private static ProjectView createView(ProjectsView parent, Project project, URI uri) {
1301         if (project != null) {
1302     		if (project.getXPath() != null) {
1303     			return new XPathSearchProjectView(parent, uri);
1304             } else if (project.getXSLT() != null) {
1305                 return new XSLTProjectView(parent, uri);
1306             } else if (project.getSchemaValidator() != null) {
1307                 return new SchemaValidatorProjectView(parent, uri);
1308     		} else if (project.getParser() != null){
1309                 return new XMLValidatorProjectView(parent, uri);
1310             } else {
1311                 return new StylesheetValidatorProjectView(parent, uri);
1312             }
1313         }
1314         
1315         return null;
1316 	}
1317     
1318     public void updateExtensionClassPath() {
1319         List<Jar> jars = PreferencesHandler.getInstance().getPreferences().getClasspath().getJar();
1320         List<Jar> temp = new ArrayList<Jar>(jars);
1321         for (Jar jar : temp) {
1322             if (jar.getSrc() != null) {
1323                 if (jar.isActive()) {
1324                     classLoader.add(new File(jar.getSrc()));
1325                 }
1326             } else {
1327                 jars.remove(jar);
1328             }
1329         }
1330     }
1331     
1332     /***
1333      * The main method to create the XMLHammer GUI.
1334      * 
1335      * @param args the arguments.
1336      */
1337     public static void main(String[] args) {
1338         System.setProperty("apple.laf.useScreenMenuBar", "true");
1339         System.setProperty("com.apple.macos.useScreenMenuBar", "true");
1340         System.setProperty("com.apple.mrj.application.apple.menu.about.name", "XML Hammer");
1341         System.setProperty("com.apple.mrj.application.live-resize", "true");
1342         System.setProperty("com.apple.macos.smallTabs", "true");
1343 
1344         String v = System.getProperty( "java.class.version","48.0");
1345 
1346         // make sure the JDK used is JDK 1.5!
1347         if ( "49.0".compareTo(v) > 0) {
1348             JOptionPane.showMessageDialog(  null, 
1349                                             "The XML Hammer application needs Java 5.0 or higher to run!\n"+
1350                                             "Please download the latest version of Java from:\n"+
1351                                             "http://java.sun.com/javase/",
1352                                             "Incompatible Java Version", 
1353                                             JOptionPane.ERROR_MESSAGE);
1354             
1355             System.exit(1);
1356             return;
1357         }
1358         
1359         setupGlobalAppenders();
1360         
1361         if (args.length > 0) {
1362             launch(args[0]);
1363         } else {
1364             launch(null);
1365         }
1366     }
1367 
1368     private static void launch(String path) {
1369         Logger.getLogger(XMLHammer.class).debug("launch("+path+")");
1370         Preferences preferences = PreferencesHandler.getInstance().getPreferences();
1371         
1372         if (preferences.getSocket().isServer()) {
1373             try {
1374                 Socket socket = new Socket(InetAddress.getLocalHost(), preferences.getSocket().getPort());
1375     
1376                 if ( path != null) {
1377                     OutputStream stream = socket.getOutputStream();
1378                     byte[] bytes = path.getBytes();
1379                     stream.write(bytes.length);
1380                     stream.write(bytes);
1381                     stream.close();
1382                 }
1383             } catch (IOException e) {
1384                 try {
1385                     // no server running, start-up server-socket!
1386                     ServerSocket server = new ServerSocket(preferences.getSocket().getPort());
1387                     
1388                     final XMLHammer hammer = new XMLHammer(true);
1389         
1390                     Thread listener = new ServerSocketThread(server, hammer);
1391                     listener.start();
1392                     
1393                     if (path != null) {
1394                     	try {
1395                     		hammer.open(path);
1396                         } catch (JAXBException x) {
1397                         	Logger.getLogger(XMLHammer.class).error( "JAXB Error", x);
1398                         } catch (TransformerException x) {
1399                         	Logger.getLogger(XMLHammer.class).error( "Transformer Error", x);
1400                         }
1401                     }
1402 
1403                     SwingUtilities.invokeLater( new Runnable() {
1404                         public void run() {
1405                             hammer.setVisible(true);
1406                             hammer.toFront();
1407                         }
1408                     });
1409                 } catch (IOException x) {
1410                     // should never happen
1411                 }
1412             }
1413         } else {
1414             final XMLHammer hammer = new XMLHammer(true);
1415             
1416             if (path != null) {
1417             	try {
1418             		hammer.open(path);
1419                 } catch (JAXBException e) {
1420                 	Logger.getLogger(XMLHammer.class).error( "JAXB Error", e);
1421                 } catch (TransformerException e) {
1422                 	Logger.getLogger(XMLHammer.class).error( "Transformer Error", e);
1423                 }
1424             }
1425             
1426             SwingUtilities.invokeLater( new Runnable() {
1427                 public void run() {
1428                     hammer.setVisible(true);
1429                     hammer.toFront();
1430                 }
1431             });
1432         }
1433     }
1434 
1435     private static class ServerSocketThread extends Thread {
1436         private ServerSocket server = null;
1437         private XMLHammer hammer = null;
1438         
1439         public ServerSocketThread(ServerSocket server, XMLHammer hammer) {
1440             setPriority(Thread.MIN_PRIORITY);
1441          
1442             this.hammer = hammer;
1443             this.server = server;
1444         }
1445         
1446         @Override
1447         public void run() {
1448             while (true) {
1449                 try {
1450                     Socket socket = server.accept();
1451                     InputStream stream = socket.getInputStream();
1452                     int length = stream.read();
1453                     byte[] bytes = new byte[length];
1454                     stream.read(bytes);
1455 
1456                     try {
1457 	                    hammer.open(new String(bytes));
1458 	                } catch (JAXBException e) {
1459 	                	Logger.getLogger(XMLHammer.class).error("JAXB Error", e);
1460 	                } catch (TransformerException e) {
1461 	                	Logger.getLogger(XMLHammer.class).error("Transformer Error", e);
1462 	                }
1463                 } catch ( IOException e) {
1464                     Logger.getLogger("org.xmlhammer.gui.XMLHammer#ServerSocketThread").debug(e);
1465                 } 
1466             }
1467         }
1468     }
1469     
1470     private class ApplicationAdapter implements ApplicationListener {
1471         private XMLHammer parent = null;
1472 
1473         public ApplicationAdapter(XMLHammer parent) {
1474             this.parent = parent;
1475             Application app = new Application();
1476             app.setEnabledPreferencesMenu(true);
1477             app.addApplicationListener(this);
1478         }
1479 
1480         public void handleAbout(ApplicationEvent e) {
1481             e.setHandled(true);
1482 
1483             SwingUtilities.invokeLater(new Runnable() {
1484                 public void run() {
1485                     parent.getShowAboutDialogAction().run();
1486                 }
1487             });
1488         }
1489 
1490         public void handleQuit(ApplicationEvent e) {
1491             e.setHandled(true);
1492             parent.getExitAction().run();
1493         }
1494 
1495         public void handlePreferences(ApplicationEvent e) {
1496             e.setHandled(true);
1497 
1498             SwingUtilities.invokeLater(new Runnable() {
1499                 public void run() {
1500                     parent.getPreferencesAction().run();
1501                 }
1502             });
1503         }
1504 
1505         public void handleOpenApplication(ApplicationEvent e) {}
1506         public void handleReOpenApplication(ApplicationEvent e) {}
1507         public void handleOpenFile(final ApplicationEvent e) {}
1508         public void handlePrintFile(ApplicationEvent e) {}
1509     }
1510 }