View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Dimension;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.KeyEvent;
20  import java.awt.event.WindowAdapter;
21  import java.awt.event.WindowEvent;
22  import java.io.File;
23  import java.net.URI;
24  import java.net.URISyntaxException;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.List;
28  import java.util.Properties;
29  
30  import javax.swing.AbstractAction;
31  import javax.swing.Action;
32  import javax.swing.BorderFactory;
33  import javax.swing.JComponent;
34  import javax.swing.JFrame;
35  import javax.swing.JMenu;
36  import javax.swing.JMenuBar;
37  import javax.swing.JMenuItem;
38  import javax.swing.JPanel;
39  import javax.swing.JSplitPane;
40  import javax.swing.SwingUtilities;
41  import javax.swing.ToolTipManager;
42  
43  import org.apache.log4j.Level;
44  import org.apache.log4j.Logger;
45  
46  import com.eviware.soapui.actions.SaveAllProjectsAction;
47  import com.eviware.soapui.actions.SoapUIPreferencesAction;
48  import com.eviware.soapui.actions.SwitchDesktopPanelAction;
49  import com.eviware.soapui.impl.actions.ImportWsdlProjectAction;
50  import com.eviware.soapui.impl.actions.NewWsdlProjectAction;
51  import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis1.Axis1XWSDL2JavaAction;
52  import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis2.Axis2WSDL2CodeAction;
53  import com.eviware.soapui.impl.wsdl.actions.iface.tools.cxf.CXFAction;
54  import com.eviware.soapui.impl.wsdl.actions.iface.tools.dotnet.DotNetWsdlAction;
55  import com.eviware.soapui.impl.wsdl.actions.iface.tools.gsoap.GSoapAction;
56  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jaxb.JaxbXjcAction;
57  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.JBossWSConsumeAction;
58  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.WSToolsWsdl2JavaAction;
59  import com.eviware.soapui.impl.wsdl.actions.iface.tools.oracle.OracleWsaGenProxyAction;
60  import com.eviware.soapui.impl.wsdl.actions.iface.tools.tcpmon.TcpMonAction;
61  import com.eviware.soapui.impl.wsdl.actions.iface.tools.wscompile.WSCompileAction;
62  import com.eviware.soapui.impl.wsdl.actions.iface.tools.wsimport.WSImportAction;
63  import com.eviware.soapui.impl.wsdl.actions.iface.tools.xfire.XFireAction;
64  import com.eviware.soapui.impl.wsdl.actions.iface.tools.xmlbeans.XmlBeans2Action;
65  import com.eviware.soapui.impl.wsdl.actions.support.OpenUrlAction;
66  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
67  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
68  import com.eviware.soapui.model.ModelItem;
69  import com.eviware.soapui.model.PanelBuilder;
70  import com.eviware.soapui.model.settings.Settings;
71  import com.eviware.soapui.model.settings.SettingsListener;
72  import com.eviware.soapui.model.tree.SoapUITreeNode;
73  import com.eviware.soapui.model.util.PanelBuilderRegistry;
74  import com.eviware.soapui.model.workspace.Workspace;
75  import com.eviware.soapui.model.workspace.WorkspaceFactory;
76  import com.eviware.soapui.monitor.MockEngine;
77  import com.eviware.soapui.monitor.TestMonitor;
78  import com.eviware.soapui.settings.UISettings;
79  import com.eviware.soapui.support.UISupport;
80  import com.eviware.soapui.support.action.SoapUIActionRegistry;
81  import com.eviware.soapui.support.action.swing.ActionList;
82  import com.eviware.soapui.support.action.swing.ActionListBuilder;
83  import com.eviware.soapui.support.action.swing.ActionSupport;
84  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
85  import com.eviware.soapui.support.components.JComponentInspector;
86  import com.eviware.soapui.support.components.JInspectorPanel;
87  import com.eviware.soapui.support.components.JXToolBar;
88  import com.eviware.soapui.support.listener.SoapUIListenerRegistry;
89  import com.eviware.soapui.support.log.InspectorLog4JMonitor;
90  import com.eviware.soapui.support.log.JLogList;
91  import com.eviware.soapui.support.log.Log4JMonitor;
92  import com.eviware.soapui.support.log.LogDisablingTestMonitorListener;
93  import com.eviware.soapui.ui.JDesktopPanelsList;
94  import com.eviware.soapui.ui.Navigator;
95  import com.eviware.soapui.ui.NavigatorListener;
96  import com.eviware.soapui.ui.desktop.DesktopPanel;
97  import com.eviware.soapui.ui.desktop.DesktopRegistry;
98  import com.eviware.soapui.ui.desktop.SoapUIDesktop;
99  import com.eviware.soapui.ui.desktop.standalone.StandaloneDesktop;
100 import com.eviware.soapui.ui.support.DesktopListenerAdapter;
101 import com.jgoodies.looks.HeaderStyle;
102 import com.jgoodies.looks.Options;
103 
104 /***
105  * Main SoapUI entry point.
106  * 
107  */
108 
109 public class SoapUI
110 {
111 	public static final String DEFAULT_DESKTOP = "Default";
112 	public static final String CURRENT_SOAPUI_WORKSPACE = SoapUI.class.getName() + "@workspace";
113 	public final static Logger log = Logger.getLogger( SoapUI.class );
114 	public final static String SOAPUI_VERSION = "1.7.6";
115 	public static final String DEFAULT_WORKSPACE_FILE = "default-soapui-workspace.xml";
116 	public static final String SOAPUI_SPLASH_GIF = "soapui-splash.gif";
117 	private static final int DEFAULT_DESKTOP_ACTIONS_COUNT = 3;
118 
119 	// ------------------------------ FIELDS ------------------------------
120 
121 //	private static SoapUI instance;
122 	private static List<Object> logCache = new ArrayList<Object>();
123 	
124 	private static SoapUICore soapUICore;
125 	private static JFrame frame;
126 
127 	private static Navigator navigator;
128 	private static SoapUIDesktop desktop;
129 	private static Workspace workspace;
130 	private static Log4JMonitor logMonitor;
131 	private static Logger errorLog = Logger.getLogger( "soapui.errorlog" );
132 	private static boolean isStandalone;
133 	private static TestMonitor testMonitor;
134 
135 	private JMenu desktopMenu;
136 	private JMenu helpMenu;
137 	private JMenu fileMenu;
138 	private static JMenuBar menuBar;
139 	private JDesktopPanelsList desktopPanelsList;
140 
141 	public static boolean checkedGroovyLogMonitor;
142 	
143 	private JPanel overviewPanel;
144 	private JMenu toolsMenu;
145 	private boolean saveOnExit = true;
146 	private InternalDesktopListener internalDesktopListener = new InternalDesktopListener();
147 	private JInspectorPanel mainInspector;
148 
149 	// --------------------------- CONSTRUCTORS ---------------------------
150 
151 	private SoapUI()
152 	{
153 	}
154 
155 	private void buildUI()
156 	{
157 		frame.addWindowListener( new MainFrameWindowListener() );
158 		UISupport.setMainFrame( frame );
159 
160 		navigator = new Navigator( workspace );
161 		navigator.addNavigatorListener( new InternalNavigatorListener() );
162 
163 		desktopPanelsList = new JDesktopPanelsList( desktop );
164 
165 		mainInspector = new JInspectorPanel( buildContentPanel(), JSplitPane.HORIZONTAL_SPLIT );
166 		mainInspector.addInspector( new JComponentInspector( buildMainPanel(), "Navigator", "The soapUI Navigator", true ) );
167 		mainInspector.setCurrentInspector( "Navigator" );
168 		
169 
170 		frame.setJMenuBar( buildMainMenu() );
171 		frame.getContentPane().add( buildToolbar(), BorderLayout.NORTH );
172 		frame.getContentPane().add( mainInspector, BorderLayout.CENTER );
173 		frame.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
174 		frame.setSize( 1000, 750 );
175 
176 		mainInspector.setDividerLocation( 250 );
177 		mainInspector.setResizeWeight( 0.1 );
178 		navigator.selectModelItem( workspace );
179 
180 		desktop.addDesktopListener( internalDesktopListener );
181 
182 		ToolTipManager.sharedInstance().setInitialDelay( 200 );
183 		
184 		desktop.init();
185 	}
186 
187 	private JComponent buildToolbar()
188 	{
189 		JXToolBar toolbar = new JXToolBar();
190 		toolbar.setRollover( true );
191 		toolbar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
192 		toolbar.add( new NewWsdlProjectActionDelegate() );
193 		toolbar.add( new ImportWsdlProjectActionDelegate() );
194 		toolbar.add( new SaveAllActionDelegate() );
195 		toolbar.addSeparator();
196 		toolbar.add( new PreferencesActionDelegate() );
197 		toolbar.add( new ExitButtonAction() );
198 		toolbar.addGlue();
199 		
200 		toolbar.add( new ShowOnlineHelpAction( HelpUrls.USERGUIDE_HELP_URL ));
201 		
202 		toolbar.setBorder( BorderFactory.createEtchedBorder() );
203 		
204 		return toolbar;
205 	}
206 
207 	private JMenuBar buildMainMenu()
208 	{
209 		menuBar = new JMenuBar();
210 		menuBar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
211 
212 		menuBar.add( buildFileMenu() );
213 		menuBar.add( buildToolsMenu() );
214 		menuBar.add( buildDesktopMenu() );
215 		menuBar.add( buildHelpMenu() );
216 
217 		return menuBar;
218 	}
219 
220 	public static Workspace getWorkspace()
221 	{
222 		return workspace;
223 	}
224 
225 	private JMenu buildDesktopMenu()
226 	{
227 		desktopMenu = new JMenu( "Desktop" );
228 		desktopMenu.setMnemonic( KeyEvent.VK_D );
229 		desktopMenu.add( new SwitchDesktopPanelAction( desktopPanelsList ) );
230 		desktopMenu.add( new MaximizeDesktopAction( ( InspectorLog4JMonitor ) logMonitor ) );
231 		desktopMenu.addSeparator();
232 
233 		ActionSupport.addActions( desktop.getActions(), desktopMenu );
234 
235 		return desktopMenu;
236 	}
237 	
238 	private JMenu buildHelpMenu()
239 	{
240 		helpMenu = new JMenu( "Help" );
241 		helpMenu.setMnemonic( KeyEvent.VK_H );
242 
243 		helpMenu.add( new ShowOnlineHelpAction( "User Guide", HelpUrls.USERGUIDE_HELP_URL ) );
244 		helpMenu.add( new ShowOnlineHelpAction( "Getting Started",
245 					HelpUrls.GETTINGSTARTED_HELP_URL ) );
246 		helpMenu.addSeparator();
247 		
248 		helpMenu.add( new ShowSystemPropertiesAction());
249 		
250 		helpMenu.addSeparator();
251 		helpMenu.add( new OpenUrlAction( "soapui.org", "http://www.soapui.org" ) );
252 		helpMenu.add( new AboutAction() );
253 		return helpMenu;
254 	}
255 
256 	@SuppressWarnings("unchecked")
257 	private JMenu buildToolsMenu()
258 	{
259 		toolsMenu = new JMenu( "Tools" );
260 		toolsMenu.setMnemonic( KeyEvent.VK_T );
261 
262 		toolsMenu.add( SwingActionDelegate.createDelegate( WSToolsWsdl2JavaAction.SOAPUI_ACTION_ID ));
263 		toolsMenu.add( SwingActionDelegate.createDelegate( JBossWSConsumeAction.SOAPUI_ACTION_ID ));
264 		toolsMenu.addSeparator();
265 		toolsMenu.add( SwingActionDelegate.createDelegate( WSCompileAction.SOAPUI_ACTION_ID ));
266 		toolsMenu.add( SwingActionDelegate.createDelegate( WSImportAction.SOAPUI_ACTION_ID ));
267 		toolsMenu.addSeparator();
268 		toolsMenu.add( SwingActionDelegate.createDelegate( Axis1XWSDL2JavaAction.SOAPUI_ACTION_ID ));
269 		toolsMenu.add( SwingActionDelegate.createDelegate( Axis2WSDL2CodeAction.SOAPUI_ACTION_ID ));
270 		toolsMenu.add( SwingActionDelegate.createDelegate( CXFAction.SOAPUI_ACTION_ID ));
271 		toolsMenu.add( SwingActionDelegate.createDelegate( XFireAction.SOAPUI_ACTION_ID ));
272 		toolsMenu.add( SwingActionDelegate.createDelegate( OracleWsaGenProxyAction.SOAPUI_ACTION_ID ));
273 		toolsMenu.addSeparator();
274 		toolsMenu.add( SwingActionDelegate.createDelegate( XmlBeans2Action.SOAPUI_ACTION_ID ));
275 		toolsMenu.add( SwingActionDelegate.createDelegate( JaxbXjcAction.SOAPUI_ACTION_ID ));
276 		toolsMenu.addSeparator();
277 		toolsMenu.add( SwingActionDelegate.createDelegate( DotNetWsdlAction.SOAPUI_ACTION_ID ));
278 		toolsMenu.add( SwingActionDelegate.createDelegate( GSoapAction.SOAPUI_ACTION_ID ));
279 		toolsMenu.addSeparator();
280 		toolsMenu.add( SwingActionDelegate.createDelegate( TcpMonAction.SOAPUI_ACTION_ID ));
281 		// toolsMenu.addSeparator();
282 		// toolsMenu.add( new XQueryXPathTesterAction());
283 
284 		return toolsMenu;
285 	}
286 
287 	private JMenu buildFileMenu()
288 	{
289 		fileMenu = new JMenu( "File" );
290 		fileMenu.setMnemonic( KeyEvent.VK_F );
291 
292 		ActionList actions = ActionListBuilder.buildActions( workspace );
293 		actions.removeAction( actions.getActionCount()-1 );
294 
295 		ActionSupport.addActions( actions, fileMenu );
296 
297 		fileMenu.add( SoapUIPreferencesAction.getInstance() );
298 		fileMenu.add( new SavePreferencesAction() );
299 		fileMenu.add( new ImportPreferencesAction() );
300 
301 		fileMenu.addSeparator();
302 		fileMenu.add( buildRecentMenu() );
303 		fileMenu.addSeparator();
304 		fileMenu.add( new ExitAction() );
305 		fileMenu.add( new ExitWithoutSavingAction() );
306 		fileMenu.addSeparator();
307 		fileMenu.add( new ShowOnlineHelpAction( HelpUrls.OVERVIEW_HELP_URL ));
308 		
309 		return fileMenu;
310 	}
311 
312 	private JMenuItem buildRecentMenu()
313 	{
314 		JMenu recentMenu = new JMenu( "Recent" );
315 		
316 		JMenu recentProjectsMenu = new JMenu( "Projects" );
317 		JMenu recentWorkspacesMenu = new JMenu( "Workspaces" );
318 		JMenu recentEditorsMenu = new JMenu( "Editors" );
319 		
320 		recentMenu.add( recentEditorsMenu );
321 		recentMenu.add( recentProjectsMenu );
322 		recentMenu.add( recentWorkspacesMenu );
323 		
324 		RecentItemsListener recentItemsListener = new RecentItemsListener( recentWorkspacesMenu, recentProjectsMenu, recentEditorsMenu );
325 		workspace.addWorkspaceListener( recentItemsListener );
326 		desktop.addDesktopListener( recentItemsListener );
327 		
328 		return recentMenu;
329 	}
330 
331 	public JFrame getFrame()
332 	{
333 		return frame;
334 	}
335 
336 	private JComponent buildMainPanel()
337 	{
338 		JInspectorPanel inspectorPanel = new JInspectorPanel( navigator );
339 		inspectorPanel.addInspector( new JComponentInspector( buildOverviewPanel(), 
340 					"Properties", "Properties for the currently selected item", true ) );
341 		inspectorPanel.setDividerLocation( 500 );
342 		inspectorPanel.setResizeWeight( 0.6 );
343 		inspectorPanel.setCurrentInspector( "Properties" );
344 		
345 		return inspectorPanel;
346 	}
347 
348 	private JComponent buildOverviewPanel()
349 	{
350 		overviewPanel = new JPanel( new BorderLayout() );
351 		overviewPanel.setBorder( BorderFactory.createEmptyBorder( 3, 0, 0, 2 ) );
352 
353 		return overviewPanel;
354 	}
355 
356 	private void setOverviewPanel( Component panel )
357 	{
358 		if( overviewPanel.getComponentCount() == 0 && panel == null )
359 			return;
360 
361 		overviewPanel.removeAll();
362 		if( panel != null )
363 			overviewPanel.add( panel, BorderLayout.CENTER );
364 		overviewPanel.revalidate();
365 		overviewPanel.repaint();
366 	}
367 
368 	private JComponent buildContentPanel()
369 	{
370 		return buildLogPanel( true, "soapUI log" );
371 	}
372 
373 	private JComponent buildLogPanel( boolean hasDefault, String defaultName )
374 	{
375 		return initLogMonitor( hasDefault, defaultName, new InspectorLog4JMonitor(desktop.getDesktopComponent()) );
376 	}
377 
378 	public static JComponent initLogMonitor( boolean hasDefault, String defaultName, Log4JMonitor logMonitor )
379 	{
380 		SoapUI.logMonitor = logMonitor; 
381 		logMonitor.addLogArea( defaultName, "com.eviware.soapui", hasDefault ).setLevel( Level.DEBUG );
382 		logMonitor.addLogArea( "http log", "httpclient.wire", false ).setLevel( Level.DEBUG );
383 		logMonitor.addLogArea( "jetty log", "jetty", false ).setLevel( Level.INFO );
384 		logMonitor.addLogArea( "error log", "soapui.errorlog", false ).setLevel( Level.DEBUG );
385 
386 		for( Object message : logCache )
387 		{
388 			logMonitor.logEvent( message );
389 		}
390 		
391 		return logMonitor.getComponent();
392 	}
393 	
394 	// -------------------------- OTHER METHODS --------------------------
395 
396 	public static synchronized void log( final Object msg )
397 	{
398 		if( logMonitor == null )
399 		{
400 			logCache.add( msg );
401 			return;
402 		}
403 
404 		if( SwingUtilities.isEventDispatchThread() )
405 		{
406 			logMonitor.logEvent( msg );
407 		}
408 		else
409 		{
410 			SwingUtilities.invokeLater( new Runnable()
411 			{
412 				public void run()
413 				{
414 					logMonitor.logEvent( msg );
415 				}
416 			} );
417 		}
418 	}
419 
420 	// -------------------------- INNER CLASSES --------------------------
421 
422 	private final class InternalDesktopListener extends DesktopListenerAdapter
423 	{
424 		public void desktopPanelSelected( DesktopPanel desktopPanel )
425 		{
426 			ModelItem modelItem = desktopPanel.getModelItem();
427 			if( modelItem != null )
428 				navigator.selectModelItem( modelItem );
429 		}
430 	}
431 
432 	private final class MainFrameWindowListener extends WindowAdapter
433 	{
434 		public void windowClosing( WindowEvent e )
435 		{
436 			if( saveOnExit )
437 			{
438 				String question = "Exit SoapUI?";
439 				
440 				if( getTestMonitor().hasRunningTests() )
441 					question += "\n(Projects with running tests will not be saved)";
442 				
443 				if( !UISupport.confirm( question, "Question" ) )
444 					return;
445 
446 				try
447 				{
448 					soapUICore.saveSettings();
449 					workspace.onClose();
450 				}
451 				catch( Exception e1 )
452 				{
453 					SoapUI.logError( e1 );
454 				}
455 			}
456 			else
457 			{
458 				if( !UISupport.confirm( "Exit SoapUI without saving?", "Question" ) )
459 				{
460 					saveOnExit = true;
461 					return;
462 				}
463 			}
464 
465 			frame.dispose();
466 		}
467 
468 		public void windowClosed( WindowEvent e )
469 		{
470 			System.out.println( "exiting.." );
471 			System.exit( 0 );
472 		}
473 	}
474 
475 	public static void main( String[] args ) throws Exception
476 	{
477 		startSoapUI( args, "soapUI " + SOAPUI_VERSION, "soapui-splash.gif", new StandaloneSoapUICore( true ) );
478 	}
479 	
480 	public static SoapUI startSoapUI( String[] args, String title, String splashImage, SwingSoapUICore core ) throws Exception
481 	{
482 		frame = new JFrame( title );
483 		
484 		SoapUISplash splash = new SoapUISplash( splashImage, frame );
485 		
486 		isStandalone = true;
487 		soapUICore = core;
488 		
489 		SoapUI soapUI = new SoapUI();
490 		Workspace workspace = null;
491 
492 		if( args.length > 0 )
493 		{
494 			workspace = WorkspaceFactory.getInstance().openWorkspace( args );
495 			soapUICore.getSettings().setString( CURRENT_SOAPUI_WORKSPACE, args[0] );
496 		}
497 		else
498 		{
499 			String wsfile = soapUICore.getSettings().getString( CURRENT_SOAPUI_WORKSPACE, System.getProperty( "user.home" ) + File.separatorChar
500 						+ DEFAULT_WORKSPACE_FILE );
501 			workspace = WorkspaceFactory.getInstance().openWorkspace( new String[] { wsfile } );
502 		}
503 		
504 		core.prepareUI();
505 		soapUI.show( workspace );
506 		core.afterStartup( workspace );
507 		Thread.sleep( 500 );
508 		splash.setVisible( false );
509 		
510 		return soapUI;
511 	}
512 	
513 	public static SoapUICore getSoapUICore()
514 	{
515 		return soapUICore;
516 	}
517 
518 	public static void setSoapUICore( SoapUICore soapUICore )
519 	{
520 		SoapUI.soapUICore = soapUICore;
521 	}
522 
523 	public static boolean isStandalone()
524 	{
525 		return isStandalone;
526 	}
527 
528 	public static JMenuBar getMenuBar()
529 	{
530 		return menuBar;
531 	}
532 	
533 	private void show( Workspace workspace )
534 	{
535 		SoapUI.workspace = workspace;
536 
537 		String desktopType = soapUICore.getSettings().getString( UISettings.DESKTOP_TYPE, SoapUI.DEFAULT_DESKTOP);
538 		desktop = DesktopRegistry.getInstance().createDesktop( desktopType, workspace );
539 		
540 		if( desktop == null ) 
541 			desktop = new StandaloneDesktop( workspace );
542 		
543 		if( testMonitor == null )
544 			testMonitor = new TestMonitor();
545 
546 		soapUICore.getSettings().addSettingsListener( new SettingsListener() {
547 
548 			public void settingChanged( String name, String newValue, String oldValue )
549 			{
550 				if( name.equals( UISettings.DESKTOP_TYPE ))
551 				{
552 					changeDesktop( DesktopRegistry.getInstance().createDesktop( newValue, SoapUI.workspace ));
553 				}
554 			}
555 		} );
556 		
557 		buildUI();
558 		
559 		testMonitor.addTestMonitorListener( new LogDisablingTestMonitorListener() );
560 		testMonitor.init( workspace );
561 		frame.setVisible( true );
562 	}
563 	
564 	private void changeDesktop(SoapUIDesktop newDesktop )
565 	{
566 		desktopPanelsList.setDesktop( newDesktop );
567 		desktop.removeDesktopListener( internalDesktopListener );
568 		
569 		desktop.transferTo( newDesktop );
570 		desktop.release();
571 		
572 		desktop = newDesktop;
573 		
574 		if( logMonitor instanceof InspectorLog4JMonitor )
575 			((InspectorLog4JMonitor)logMonitor).setContentComponent( desktop.getDesktopComponent() );
576 		
577 		desktop.addDesktopListener( internalDesktopListener );
578 		
579 		while( desktopMenu.getItemCount() > DEFAULT_DESKTOP_ACTIONS_COUNT )
580 			desktopMenu.remove( DEFAULT_DESKTOP_ACTIONS_COUNT );
581 		
582 		ActionSupport.addActions( desktop.getActions(), desktopMenu );
583 		
584 		desktop.init();
585 	}
586 	
587 	public static void logError( Throwable e )
588 	{
589 		String msg = e.getMessage();
590 		if( msg == null )
591 			msg = e.toString();
592 		
593 		log.error( "An error occured [" + msg + "], see error log for details" );
594 		errorLog.error(e.toString(), e );
595 		if( !isStandalone() )
596 			e.printStackTrace();
597 	}
598 
599 	public static synchronized Logger ensureGroovyLog()
600 	{
601 		if( !checkedGroovyLogMonitor )
602 		{
603 			Log4JMonitor logMonitor = getLogMonitor();
604 			if( logMonitor != null && !logMonitor.hasLogArea( "groovy.log" ))
605 				logMonitor.addLogArea( "groovy log", "groovy.log", false );
606 			
607 			checkedGroovyLogMonitor = true;
608 		}
609 		
610 		return Logger.getLogger( "groovy.log" );
611 	}
612 
613 	public class InternalNavigatorListener implements NavigatorListener
614 	{
615 		public void nodeSelected( SoapUITreeNode treeNode )
616 		{
617 			if( treeNode == null )
618 			{
619 				setOverviewPanel( null );
620 			}
621 			else
622 			{
623 				PanelBuilder<ModelItem> panelBuilder = PanelBuilderRegistry.getPanelBuilder( treeNode.getModelItem() );
624 				if( panelBuilder != null && panelBuilder.hasOverviewPanel() )
625 				{
626 					setOverviewPanel( panelBuilder.buildOverviewPanel( treeNode.getModelItem() ) );
627 				}
628 				else
629 				{
630 					setOverviewPanel( null );
631 				}
632 			}
633 		}
634 	}
635 
636 	private class ExitAction extends AbstractAction
637 	{
638 		public ExitAction()
639 		{
640 			super( "Exit" );
641 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
642 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu Q" ) );
643 		}
644 
645 		public void actionPerformed( ActionEvent e )
646 		{
647 			saveOnExit = true;
648 			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
649 			frame.dispatchEvent( windowEvent );
650 		}
651 	}
652 	
653 	private class ExitButtonAction extends AbstractAction
654 	{
655 		public ExitButtonAction()
656 		{
657 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/system-log-out.png" ));
658 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
659 		}
660 
661 		public void actionPerformed( ActionEvent e )
662 		{
663 			saveOnExit = true;
664 			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
665 			frame.dispatchEvent( windowEvent );
666 		}
667 	}
668 
669 	private static class ShowSystemPropertiesAction extends AbstractAction
670 	{
671 		public ShowSystemPropertiesAction()
672 		{
673 			super( "System Properties" );
674 			putValue( Action.SHORT_DESCRIPTION, "Shows the current systems properties" );
675 		}
676 
677 		public void actionPerformed( ActionEvent e )
678 		{
679 			StringBuffer buffer = new StringBuffer();
680 			Properties properties = System.getProperties();
681 			
682 			List<String> keys = new ArrayList<String>();
683 			for( Object key : properties.keySet() )
684 				keys.add( key.toString() );
685 			
686 			Collections.sort( keys );
687 			
688 			String lastKey = null;
689 			
690 			for( String key : keys )
691 			{
692 				if( lastKey != null )
693 				{
694 					if( !key.startsWith( lastKey ))
695 						buffer.append(  "\r\n" );
696 				}
697 
698 				int ix = key.indexOf( '.' );
699 				lastKey = ix == -1 ? key : key.substring( 0, ix );
700 				
701 				buffer.append( key ).append( '=' ).append( properties.get( key )).append( "\r\n" );
702 			}
703 			
704 			UISupport.showExtendedInfo( "System Properties", "Current system properties", 
705 						"<html><body><pre><font size=-1>" + buffer.toString() + "</font></pre></body></html>", 
706 						new Dimension( 600, 400 ));
707 		}
708 	}
709 	
710 	private static class AboutAction extends AbstractAction
711 	{
712 		public AboutAction()
713 		{
714 			super( "About soapUI" );
715 			putValue( Action.SHORT_DESCRIPTION, "Shows information on soapUI" );
716 		}
717 
718 		public void actionPerformed( ActionEvent e )
719 		{
720 			URI splashURI = null;
721 			try
722 			{
723 				splashURI = UISupport.findSplash( SoapUI.SOAPUI_SPLASH_GIF ).toURI();
724 			}
725 			catch( URISyntaxException e1 )
726 			{
727 				SoapUI.logError( e1 );
728 			}
729 			
730 			Properties props = new Properties();
731 			try
732 			{
733 				props.load( SoapUI.class.getResourceAsStream( "/buildinfo.txt" ) );
734 			}
735 			catch( Exception e1 )
736 			{
737 				SoapUI.logError( e1 );
738 			}
739 			
740 			
741 			UISupport.showExtendedInfo( "About soapUI", null, 
742 						"<html><body><p align=center><img src=\"" + splashURI + "\"><br>soapUI " +
743 						SOAPUI_VERSION + ", copyright (C) 2004-2007 eviware.com<br>" +
744 						"<a href=\"http://www.soapui.org\">http://www.soapui.org</a> | " +
745 						"<a href=\"http://www.eviware.com\">http://www.eviware.com</a><br>" +
746 									"Build " + props.getProperty( "build.number" ) + ", Build Date " +
747 									props.getProperty( "build.date" ) + "</p></body></html>",
748 									
749 						new Dimension( 470, 350 ));
750 		}
751 	}
752 	
753 	private class ExitWithoutSavingAction extends AbstractAction
754 	{
755 		public ExitWithoutSavingAction()
756 		{
757 			super( "Exit without saving" );
758 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
759 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "ctrl alt Q" ) );
760 		}
761 
762 		public void actionPerformed( ActionEvent e )
763 		{
764 			saveOnExit = false;
765 			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
766 			frame.dispatchEvent( windowEvent );
767 		}
768 	}
769 
770 	private class SavePreferencesAction extends AbstractAction
771 	{
772 		public SavePreferencesAction()
773 		{
774 			super( "Save Preferences" );
775 			putValue( Action.SHORT_DESCRIPTION, "Saves all global preferences" );
776 		}
777 
778 		public void actionPerformed( ActionEvent e )
779 		{
780 			try
781 			{
782 				soapUICore.saveSettings();
783 			}
784 			catch( Exception e1 )
785 			{
786 				UISupport.showErrorMessage( e1 );
787 			}
788 		}
789 	}
790 	
791 	public static TestMonitor getTestMonitor()
792 	{
793 		if( testMonitor == null )
794 			testMonitor = new TestMonitor();
795 		
796 		return testMonitor;
797 	}
798 
799 	public static void setTestMonitor( TestMonitor monitor )
800 	{
801 		testMonitor = monitor;
802 	}
803 
804 	public static Log4JMonitor getLogMonitor()
805 	{
806 		return logMonitor;
807 	}
808 
809 	public static void setLogMonitor( Log4JMonitor monitor )
810 	{
811 		logMonitor = monitor;
812 	}
813 
814 	// instance is null in Eclipse. /Lars
815 	// eclipse-version(s) should provide SoapUIDesktop implementation
816 	public static SoapUIDesktop getDesktop()
817 	{
818 		return desktop;
819 	}
820 
821 	public static void setDesktop( SoapUIDesktop desktop )
822 	{
823 		SoapUI.desktop = desktop;
824 	}
825 
826 	public static Navigator getNavigator()
827 	{
828 		return navigator;
829 	}
830 	
831 	public static SoapUIActionRegistry getActionRegistry()
832 	{
833 		if( soapUICore == null )
834 			soapUICore = new DefaultSoapUICore();
835 		
836 		return soapUICore.getActionRegistry();
837 	}
838 
839 	public static void setNavigator( Navigator navigator )
840 	{
841 		SoapUI.navigator = navigator;
842 	}
843 
844 	public static void setStandalone( boolean standalone )
845 	{
846 		SoapUI.isStandalone = standalone;
847 	}
848 	
849 	private static class NewWsdlProjectActionDelegate extends AbstractAction
850 	{
851 		public NewWsdlProjectActionDelegate()
852 		{
853 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/project.gif" ));
854 			putValue( Action.SHORT_DESCRIPTION, "Creates a new WSDL Project" );
855 		}
856 		
857 		public void actionPerformed( ActionEvent e )
858 		{
859 			SoapUI.getActionRegistry().getAction( NewWsdlProjectAction.SOAPUI_ACTION_ID ).perform( workspace, null );
860 		}
861 	}
862 	
863 	private static class ImportWsdlProjectActionDelegate extends AbstractAction
864 	{
865 		public ImportWsdlProjectActionDelegate()
866 		{
867 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/import_project.gif" ));
868 			putValue( Action.SHORT_DESCRIPTION, "Imports an existing WSDL Project into the current workspace" );
869 		}
870 		
871 		public void actionPerformed( ActionEvent e )
872 		{
873 			SoapUI.getActionRegistry().getAction( ImportWsdlProjectAction.SOAPUI_ACTION_ID ).perform( workspace, null );
874 		}
875 	}
876 	
877 	private static class SaveAllActionDelegate extends AbstractAction
878 	{
879 		public SaveAllActionDelegate()
880 		{
881 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/disk_multiple.png" ));
882 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects in the current workspace" );
883 		}
884 		
885 		public void actionPerformed( ActionEvent e )
886 		{
887 			SoapUI.getActionRegistry().getAction( SaveAllProjectsAction.SOAPUI_ACTION_ID ).perform( workspace, null );
888 		}
889 	}
890 	
891 	private class PreferencesActionDelegate extends AbstractAction
892 	{
893 		public PreferencesActionDelegate()
894 		{
895 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ));
896 			putValue( Action.SHORT_DESCRIPTION, "Sets Global soapUI Options" );
897 		}
898 		
899 		public void actionPerformed( ActionEvent e )
900 		{
901 			SoapUIPreferencesAction.getInstance().actionPerformed( null );
902 		}
903 	}
904 	
905 	public static class ImportPreferencesAction extends AbstractAction
906 	{
907 		public static final String IMPORT_PREFERENCES_ACTION_NAME = "Import Preferences";
908 
909 		public ImportPreferencesAction()
910 		{
911 			super( ImportPreferencesAction.IMPORT_PREFERENCES_ACTION_NAME );
912 			putValue( Action.SHORT_DESCRIPTION, "Imports soapUI Settings from another settings-file" );
913 		}
914 
915 		public void actionPerformed( ActionEvent e )
916 		{
917 			try
918 			{
919 				// prompt for import
920 				File file = UISupport.getFileDialogs().open( null, ImportPreferencesAction.IMPORT_PREFERENCES_ACTION_NAME, ".xml", "soapUI Settings XML (*.xml)", null );
921 				if( file != null )
922 					soapUICore.importSettings( file );
923 			}
924 			catch( Exception e1 )
925 			{
926 				UISupport.showErrorMessage( e1 );
927 			}
928 		}
929 	}
930 	
931 	public static SoapUIListenerRegistry getListenerRegistry()
932 	{
933 		if( soapUICore == null )
934 			soapUICore = DefaultSoapUICore.createDefault();
935 		
936 		return soapUICore.getListenerRegistry();
937 	}
938 
939 	public static Settings getSettings()
940 	{
941 		if( soapUICore == null )
942 			soapUICore = DefaultSoapUICore.createDefault();
943 		
944 		return soapUICore.getSettings();
945 	}
946 
947 	public static void importPreferences( File file ) throws Exception
948 	{
949 		if( soapUICore != null )
950 			soapUICore.importSettings( file );
951 	}
952 
953 	public static MockEngine getMockEngine()
954 	{
955 		if( soapUICore == null )
956 			soapUICore = DefaultSoapUICore.createDefault();
957 		
958 		return soapUICore.getMockEngine();
959 	}
960 
961 	public static String saveSettings() throws Exception
962 	{
963 		return soapUICore == null ? null : soapUICore.saveSettings();
964 	}
965 
966 	public static void initDefaultCore()
967 	{
968 		if( soapUICore == null )
969 			soapUICore = DefaultSoapUICore.createDefault();
970 	}
971 	
972 	public class MaximizeDesktopAction extends AbstractAction
973 	{
974 		private JLogList lastLog;
975 		private int lastMainDividerLocation;
976 		private final InspectorLog4JMonitor log4JMonitor;
977 		private int lastLogDividerLocation;
978 		
979 		public MaximizeDesktopAction( InspectorLog4JMonitor log4JMonitor )
980 		{
981 			super( "Maximize Desktop" );
982 			this.log4JMonitor = log4JMonitor;
983 
984 			putValue( SHORT_DESCRIPTION, "Hides/Shows the Navigator and Log tabs" );
985 			putValue( ACCELERATOR_KEY, UISupport.getKeyStroke( "menu M" ) );
986 		}
987 
988 		public void actionPerformed( ActionEvent e )
989 		{
990 			if( mainInspector.getCurrentInspector() != null || logMonitor.getCurrentLog() != null )
991 			{
992 				lastMainDividerLocation = mainInspector.getDividerLocation();
993 				mainInspector.deactivate();
994 				
995 				lastLog = logMonitor.getCurrentLog();
996 				lastLogDividerLocation = log4JMonitor.getDividerLocation();
997 				
998 				log4JMonitor.deactivate();
999 			}
1000 			else
1001 			{
1002 				mainInspector.setCurrentInspector( "Navigator" );
1003 				mainInspector.setDividerLocation( lastMainDividerLocation == 0 ? 250 : lastMainDividerLocation );
1004 				
1005 				log4JMonitor.setCurrentLog( lastLog );
1006 				log4JMonitor.setDividerLocation( lastLogDividerLocation == 0 ? 500 : lastLogDividerLocation );
1007 			}
1008 		}
1009 	}
1010 }