View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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.dnd.DnDConstants;
19  import java.awt.dnd.DragSource;
20  import java.awt.event.ActionEvent;
21  import java.awt.event.KeyAdapter;
22  import java.awt.event.KeyEvent;
23  import java.awt.event.WindowAdapter;
24  import java.awt.event.WindowEvent;
25  import java.io.BufferedInputStream;
26  import java.io.BufferedReader;
27  import java.io.File;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.io.InputStreamReader;
31  import java.net.URI;
32  import java.net.URISyntaxException;
33  import java.net.URL;
34  import java.net.URLEncoder;
35  import java.util.ArrayList;
36  import java.util.List;
37  import java.util.Properties;
38  import java.util.Timer;
39  import java.util.TimerTask;
40  import java.util.concurrent.Executors;
41  import java.util.concurrent.ThreadPoolExecutor;
42  
43  import javax.swing.AbstractAction;
44  import javax.swing.Action;
45  import javax.swing.BorderFactory;
46  import javax.swing.JButton;
47  import javax.swing.JComponent;
48  import javax.swing.JFrame;
49  import javax.swing.JMenu;
50  import javax.swing.JMenuBar;
51  import javax.swing.JMenuItem;
52  import javax.swing.JPanel;
53  import javax.swing.JPopupMenu;
54  import javax.swing.JTabbedPane;
55  import javax.swing.JTextField;
56  import javax.swing.JToggleButton;
57  import javax.swing.JTree;
58  import javax.swing.SwingConstants;
59  import javax.swing.SwingUtilities;
60  import javax.swing.ToolTipManager;
61  
62  import org.apache.commons.cli.CommandLine;
63  import org.apache.commons.cli.CommandLineParser;
64  import org.apache.commons.cli.PosixParser;
65  import org.apache.log4j.Level;
66  import org.apache.log4j.Logger;
67  
68  import com.eviware.soapui.actions.SaveAllProjectsAction;
69  import com.eviware.soapui.actions.ShowSystemPropertiesAction;
70  import com.eviware.soapui.actions.SoapUIPreferencesAction;
71  import com.eviware.soapui.actions.StartHermesJMSButtonAction;
72  import com.eviware.soapui.actions.SwitchDesktopPanelAction;
73  import com.eviware.soapui.impl.WorkspaceImpl;
74  import com.eviware.soapui.impl.actions.ImportWsdlProjectAction;
75  import com.eviware.soapui.impl.actions.NewWsdlProjectAction;
76  import com.eviware.soapui.impl.rest.actions.project.NewRestServiceAction;
77  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
78  import com.eviware.soapui.impl.wsdl.WsdlProject;
79  import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis1.Axis1XWSDL2JavaAction;
80  import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis2.Axis2WSDL2CodeAction;
81  import com.eviware.soapui.impl.wsdl.actions.iface.tools.cxf.CXFAction;
82  import com.eviware.soapui.impl.wsdl.actions.iface.tools.dotnet.DotNetWsdlAction;
83  import com.eviware.soapui.impl.wsdl.actions.iface.tools.gsoap.GSoapAction;
84  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jaxb.JaxbXjcAction;
85  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.JBossWSConsumeAction;
86  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.WSToolsWsdl2JavaAction;
87  import com.eviware.soapui.impl.wsdl.actions.iface.tools.oracle.OracleWsaGenProxyAction;
88  import com.eviware.soapui.impl.wsdl.actions.iface.tools.tcpmon.TcpMonAction;
89  import com.eviware.soapui.impl.wsdl.actions.iface.tools.wscompile.WSCompileAction;
90  import com.eviware.soapui.impl.wsdl.actions.iface.tools.wsimport.WSImportAction;
91  import com.eviware.soapui.impl.wsdl.actions.iface.tools.xfire.XFireAction;
92  import com.eviware.soapui.impl.wsdl.actions.iface.tools.xmlbeans.XmlBeans2Action;
93  import com.eviware.soapui.impl.wsdl.actions.project.StartLoadUI;
94  import com.eviware.soapui.impl.wsdl.actions.support.OpenUrlAction;
95  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
96  import com.eviware.soapui.impl.wsdl.submit.transports.jms.util.HermesUtils;
97  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
98  import com.eviware.soapui.impl.wsdl.support.http.ProxyUtils;
99  import com.eviware.soapui.integration.impl.CajoServer;
100 import com.eviware.soapui.model.ModelItem;
101 import com.eviware.soapui.model.PanelBuilder;
102 import com.eviware.soapui.model.TestPropertyHolder;
103 import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
104 import com.eviware.soapui.model.settings.Settings;
105 import com.eviware.soapui.model.settings.SettingsListener;
106 import com.eviware.soapui.model.tree.SoapUITreeNode;
107 import com.eviware.soapui.model.util.PanelBuilderRegistry;
108 import com.eviware.soapui.model.workspace.Workspace;
109 import com.eviware.soapui.model.workspace.WorkspaceFactory;
110 import com.eviware.soapui.monitor.MockEngine;
111 import com.eviware.soapui.monitor.TestMonitor;
112 import com.eviware.soapui.settings.ProxySettings;
113 import com.eviware.soapui.settings.UISettings;
114 import com.eviware.soapui.support.SoapUIException;
115 import com.eviware.soapui.support.StringUtils;
116 import com.eviware.soapui.support.Tools;
117 import com.eviware.soapui.support.UISupport;
118 import com.eviware.soapui.support.action.SoapUIAction;
119 import com.eviware.soapui.support.action.SoapUIActionRegistry;
120 import com.eviware.soapui.support.action.swing.ActionList;
121 import com.eviware.soapui.support.action.swing.ActionListBuilder;
122 import com.eviware.soapui.support.action.swing.ActionSupport;
123 import com.eviware.soapui.support.action.swing.SwingActionDelegate;
124 import com.eviware.soapui.support.components.JComponentInspector;
125 import com.eviware.soapui.support.components.JInspectorPanel;
126 import com.eviware.soapui.support.components.JInspectorPanelFactory;
127 import com.eviware.soapui.support.components.JPropertiesTable;
128 import com.eviware.soapui.support.components.JXToolBar;
129 import com.eviware.soapui.support.dnd.DropType;
130 import com.eviware.soapui.support.dnd.NavigatorDragAndDropable;
131 import com.eviware.soapui.support.dnd.SoapUIDragAndDropHandler;
132 import com.eviware.soapui.support.jnlp.WebstartUtilCore;
133 import com.eviware.soapui.support.listener.SoapUIListenerRegistry;
134 import com.eviware.soapui.support.log.InspectorLog4JMonitor;
135 import com.eviware.soapui.support.log.JLogList;
136 import com.eviware.soapui.support.log.Log4JMonitor;
137 import com.eviware.soapui.support.log.LogDisablingTestMonitorListener;
138 import com.eviware.soapui.support.monitor.MonitorPanel;
139 import com.eviware.soapui.support.monitor.RuntimeMemoryMonitorSource;
140 import com.eviware.soapui.support.swing.MenuScroller;
141 import com.eviware.soapui.support.types.StringToStringMap;
142 import com.eviware.soapui.tools.CmdLineRunner;
143 import com.eviware.soapui.ui.JDesktopPanelsList;
144 import com.eviware.soapui.ui.Navigator;
145 import com.eviware.soapui.ui.NavigatorListener;
146 import com.eviware.soapui.ui.URLDesktopPanel;
147 import com.eviware.soapui.ui.desktop.DesktopPanel;
148 import com.eviware.soapui.ui.desktop.DesktopRegistry;
149 import com.eviware.soapui.ui.desktop.NullDesktop;
150 import com.eviware.soapui.ui.desktop.SoapUIDesktop;
151 import com.eviware.soapui.ui.desktop.standalone.StandaloneDesktop;
152 import com.eviware.soapui.ui.support.DesktopListenerAdapter;
153 import com.eviware.x.impl.swing.SwingDialogs;
154 import com.jgoodies.looks.HeaderStyle;
155 import com.jgoodies.looks.Options;
156 import com.jniwrapper.PlatformContext;
157 
158 /***
159  * Main SoapUI entry point.
160  */
161 
162 public class SoapUI
163 {
164 	public static final String DEFAULT_DESKTOP = "Default";
165 	public static final String CURRENT_SOAPUI_WORKSPACE = SoapUI.class.getName() + "@workspace";
166 	public final static Logger log = Logger.getLogger( SoapUI.class );
167 	public final static String SOAPUI_VERSION = "3.6.2-SNAPSHOT";
168 	public static final String DEFAULT_WORKSPACE_FILE = "default-soapui-workspace.xml";
169 	public static final String SOAPUI_SPLASH = "soapui-splash.jpg";
170 	public static final String SOAPUI_TITLE = "/com/eviware/soapui/resources/branded/branded.properties";
171 	private static final int DEFAULT_DESKTOP_ACTIONS_COUNT = 3;
172 	public static final String BUILDINFO_RESOURCE = "/com/eviware/soapui/resources/conf/buildinfo.txt";
173 	public static final String PROXY_ENABLED_ICON = "/proxyEnabled.png";
174 	public static final String PROXY_DISABLED_ICON = "/proxyDisabled.png";
175 
176 	@SuppressWarnings( "deprecation" )
177 	public static String PUSH_PAGE_URL = "http://www.soapui.org/appindex/soapui_starterpage.php?version="
178 			+ URLEncoder.encode( SOAPUI_VERSION );
179 	public static String FRAME_ICON = "/16-perc.gif";
180 	public static String PUSH_PAGE_ERROR_URL = "file://" + System.getProperty( "soapui.home", "." )
181 			+ "/starter-page.html";
182 
183 	// ------------------------------ FIELDS ------------------------------
184 
185 	// private static SoapUI instance;
186 	private static List<Object> logCache = new ArrayList<Object>();
187 
188 	private static SoapUICore soapUICore;
189 	private static Timer soapUITimer = new Timer();
190 	private static JFrame frame;
191 
192 	private static Navigator navigator;
193 	private static SoapUIDesktop desktop;
194 	private static Workspace workspace;
195 	private static Log4JMonitor logMonitor;
196 	private static Logger errorLog = Logger.getLogger( "soapui.errorlog" );
197 	private static boolean isStandalone;
198 	private static boolean isCommandLine;
199 	private static TestMonitor testMonitor;
200 
201 	private JMenu desktopMenu;
202 	private JMenu helpMenu;
203 	private JMenu fileMenu;
204 	private static JMenuBar menuBar;
205 	private JDesktopPanelsList desktopPanelsList;
206 
207 	private static Boolean checkedGroovyLogMonitor = false;
208 	private static Boolean launchedTestRunner = false;
209 
210 	private JPanel overviewPanel;
211 	private JMenu toolsMenu;
212 	private boolean saveOnExit = true;
213 	private InternalDesktopListener internalDesktopListener = new InternalDesktopListener();
214 	private JInspectorPanel mainInspector;
215 
216 	private static AutoSaveTimerTask autoSaveTimerTask;
217 	private static String workspaceName;
218 	private static StringToStringMap projectOptions = new StringToStringMap();
219 	private static URLDesktopPanel urlDesktopPanel;
220 	private static JXToolBar mainToolbar;
221 	private static String[] mainArgs;
222 	private static GCTimerTask gcTimerTask;
223 
224 	private final static ThreadPoolExecutor threadPool = ( ThreadPoolExecutor )Executors
225 			.newCachedThreadPool( new SoapUIThreadCreator() );
226 	private JTextField searchField;
227 	private static JToggleButton applyProxyButton;
228 	private static Logger groovyLogger;
229 	private static Logger loadUILogger;
230 	@SuppressWarnings( "unused" )
231 	private static JButton launchLoadUIButton;
232 	private static CmdLineRunner soapUIRunner;
233 
234 	// --------------------------- CONSTRUCTORS ---------------------------
235 
236 	private SoapUI()
237 	{
238 	}
239 
240 	private void buildUI()
241 	{
242 		// display used java version
243 		log.info( "Used java version: " + System.getProperty( "java.version" ) );
244 		frame.addWindowListener( new MainFrameWindowListener() );
245 		UISupport.setMainFrame( frame );
246 
247 		navigator = new Navigator( workspace );
248 		navigator.addNavigatorListener( new InternalNavigatorListener() );
249 
250 		desktopPanelsList = new JDesktopPanelsList( desktop );
251 
252 		mainInspector = JInspectorPanelFactory.build( buildContentPanel(), SwingConstants.LEFT );
253 		mainInspector.addInspector( new JComponentInspector<JComponent>( buildMainPanel(), "Navigator",
254 				"The soapUI Navigator", true ) );
255 		mainInspector.setCurrentInspector( "Navigator" );
256 
257 		frame.setJMenuBar( buildMainMenu() );
258 		frame.getContentPane().add( buildToolbar(), BorderLayout.NORTH );
259 		frame.getContentPane().add( mainInspector.getComponent(), BorderLayout.CENTER );
260 		frame.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
261 		frame.setSize( 1000, 750 );
262 
263 		mainInspector.setDividerLocation( 250 );
264 		mainInspector.setResizeWeight( 0.1 );
265 		navigator.selectModelItem( workspace );
266 
267 		desktop.addDesktopListener( internalDesktopListener );
268 
269 		ToolTipManager.sharedInstance().setInitialDelay( 200 );
270 
271 		JTree mainTree = navigator.getMainTree();
272 		DragSource dragSource = DragSource.getDefaultDragSource();
273 		SoapUIDragAndDropHandler navigatorDragAndDropHandler = new SoapUIDragAndDropHandler(
274 				new NavigatorDragAndDropable( mainTree ), DropType.ON + DropType.AFTER );
275 
276 		dragSource.createDefaultDragGestureRecognizer( mainTree, DnDConstants.ACTION_COPY_OR_MOVE,
277 				navigatorDragAndDropHandler );
278 
279 		desktop.init();
280 	}
281 
282 	public static JToggleButton getApplyProxyButton()
283 	{
284 		return applyProxyButton;
285 	}
286 
287 	private JComponent buildToolbar()
288 	{
289 		mainToolbar = new JXToolBar();
290 		mainToolbar.setRollover( true );
291 		mainToolbar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
292 		mainToolbar.add( new NewWsdlProjectActionDelegate() );
293 		mainToolbar.add( new ImportWsdlProjectActionDelegate() );
294 		mainToolbar.add( new SaveAllActionDelegate() );
295 		mainToolbar.addSeparator();
296 		mainToolbar.add( new ShowOnlineHelpAction( "User Guide", HelpUrls.USERGUIDE_HELP_URL,
297 				"Opens the soapUI User-Guide in a browser" ) );
298 		mainToolbar.add( new ShowOnlineHelpAction( "Forum", HelpUrls.FORUMS_HELP_URL,
299 				"Opens the soapUI Forum in a browser", "/group_go.png" ) );
300 		mainToolbar.addSeparator();
301 		mainToolbar.add( new ShowOnlineHelpAction( "Trial", HelpUrls.TRIAL_URL, "Apply for soapUI Pro Trial License",
302 				"/favicon.png" ) );
303 		mainToolbar.addSeparator();
304 		mainToolbar.add( new PreferencesActionDelegate() );
305 		applyProxyButton = ( JToggleButton )mainToolbar.add( new JToggleButton( new ApplyProxyButtonAction() ) );
306 		ProxyUtils.setProxyEnabled( getSettings().getBoolean( ProxySettings.ENABLE_PROXY ) );
307 		if( ProxyUtils.isProxyEnabled() )
308 		{
309 			applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_ENABLED_ICON ) );
310 			applyProxyButton.setSelected( true );
311 			ProxyUtils.setProxyEnabled( true );
312 		}
313 		else
314 		{
315 			applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_DISABLED_ICON ) );
316 			ProxyUtils.setProxyEnabled( false );
317 		}
318 		launchLoadUIButton = mainToolbar.add( new LaunchLoadUIButtonAction() );
319 		mainToolbar.add( new ExitButtonAction() );
320 
321 		mainToolbar.addGlue();
322 
323 		searchField = new JTextField( 20 );
324 		searchField.addKeyListener( new KeyAdapter()
325 		{
326 			@Override
327 			public void keyTyped( KeyEvent e )
328 			{
329 				if( e.getKeyChar() == '\n' )
330 				{
331 					doForumSearch( searchField.getText() );
332 				}
333 			}
334 		} );
335 
336 		mainToolbar.addLabeledFixed( "Search Forum", searchField );
337 		mainToolbar.add( new ToolbarForumSearchAction() );
338 		mainToolbar.add( new ShowOnlineHelpAction( HelpUrls.USERGUIDE_HELP_URL ) );
339 
340 		mainToolbar.setBorder( BorderFactory.createEtchedBorder() );
341 
342 		return mainToolbar;
343 	}
344 
345 	@SuppressWarnings( "deprecation" )
346 	public void doForumSearch( String text )
347 	{
348 		if( !searchField.getText().equals( text ) )
349 			searchField.setText( text );
350 
351 		if( StringUtils.hasContent( text ) )
352 		{
353 			Tools.openURL( "http://www.eviware.com/forums/search.php?keywords=" + URLEncoder.encode( text.trim() ) );
354 		}
355 		else
356 		{
357 			Tools.openURL( "http://www.eviware.com/forums" );
358 		}
359 	}
360 
361 	private JMenuBar buildMainMenu()
362 	{
363 		menuBar = new JMenuBar();
364 		menuBar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
365 
366 		menuBar.add( buildFileMenu() );
367 		menuBar.add( buildToolsMenu() );
368 		menuBar.add( buildDesktopMenu() );
369 		menuBar.add( buildHelpMenu() );
370 
371 		return menuBar;
372 	}
373 
374 	public static ThreadPoolExecutor getThreadPool()
375 	{
376 		return threadPool;
377 	}
378 
379 	public static Workspace getWorkspace()
380 	{
381 		return workspace;
382 	}
383 
384 	private JMenu buildDesktopMenu()
385 	{
386 		desktopMenu = new JMenu( "Desktop" );
387 		desktopMenu.setMnemonic( KeyEvent.VK_D );
388 		desktopMenu.add( new SwitchDesktopPanelAction( desktopPanelsList ) );
389 		desktopMenu.add( new MaximizeDesktopAction( ( InspectorLog4JMonitor )logMonitor ) );
390 		desktopMenu.addSeparator();
391 
392 		ActionSupport.addActions( desktop.getActions(), desktopMenu );
393 
394 		return desktopMenu;
395 	}
396 
397 	private JMenu buildHelpMenu()
398 	{
399 		helpMenu = new JMenu( "Help" );
400 		helpMenu.setMnemonic( KeyEvent.VK_H );
401 
402 		helpMenu.add( new ShowPushPageAction() );
403 		helpMenu.addSeparator();
404 		helpMenu.add( new ShowOnlineHelpAction( "User Guide", HelpUrls.USERGUIDE_HELP_URL ) );
405 		helpMenu.add( new ShowOnlineHelpAction( "Getting Started", HelpUrls.GETTINGSTARTED_HELP_URL ) );
406 		helpMenu.add( new SearchForumAction() );
407 		helpMenu.addSeparator();
408 		helpMenu.add( new ShowSystemPropertiesAction() );
409 		helpMenu.addSeparator();
410 		helpMenu.add( new OpenUrlAction( "soapui.org", "http://www.soapui.org" ) );
411 		helpMenu.add( new ShowOnlineHelpAction( "soapUI Pro Trial", HelpUrls.TRIAL_URL,
412 				"Apply for soapUI Pro Trial License", "/favicon.png" ) );
413 		helpMenu.addSeparator();
414 		helpMenu.add( new AboutAction() );
415 		return helpMenu;
416 	}
417 
418 	private JMenu buildToolsMenu()
419 	{
420 		toolsMenu = new JMenu( "Tools" );
421 		toolsMenu.setMnemonic( KeyEvent.VK_T );
422 
423 		toolsMenu.add( SwingActionDelegate.createDelegate( WSToolsWsdl2JavaAction.SOAPUI_ACTION_ID ) );
424 		toolsMenu.add( SwingActionDelegate.createDelegate( JBossWSConsumeAction.SOAPUI_ACTION_ID ) );
425 		toolsMenu.addSeparator();
426 		toolsMenu.add( SwingActionDelegate.createDelegate( WSCompileAction.SOAPUI_ACTION_ID ) );
427 		toolsMenu.add( SwingActionDelegate.createDelegate( WSImportAction.SOAPUI_ACTION_ID ) );
428 		toolsMenu.addSeparator();
429 		toolsMenu.add( SwingActionDelegate.createDelegate( Axis1XWSDL2JavaAction.SOAPUI_ACTION_ID ) );
430 		toolsMenu.add( SwingActionDelegate.createDelegate( Axis2WSDL2CodeAction.SOAPUI_ACTION_ID ) );
431 		toolsMenu.add( SwingActionDelegate.createDelegate( CXFAction.SOAPUI_ACTION_ID ) );
432 		toolsMenu.add( SwingActionDelegate.createDelegate( XFireAction.SOAPUI_ACTION_ID ) );
433 		toolsMenu.add( SwingActionDelegate.createDelegate( OracleWsaGenProxyAction.SOAPUI_ACTION_ID ) );
434 		toolsMenu.addSeparator();
435 		toolsMenu.add( SwingActionDelegate.createDelegate( XmlBeans2Action.SOAPUI_ACTION_ID ) );
436 		toolsMenu.add( SwingActionDelegate.createDelegate( JaxbXjcAction.SOAPUI_ACTION_ID ) );
437 		toolsMenu.addSeparator();
438 		toolsMenu.add( SwingActionDelegate.createDelegate( DotNetWsdlAction.SOAPUI_ACTION_ID ) );
439 		toolsMenu.add( SwingActionDelegate.createDelegate( GSoapAction.SOAPUI_ACTION_ID ) );
440 		toolsMenu.addSeparator();
441 		toolsMenu.add( SwingActionDelegate.createDelegate( TcpMonAction.SOAPUI_ACTION_ID ) );
442 		// toolsMenu.addSeparator();
443 		// toolsMenu.add( new XQueryXPathTesterAction());
444 		toolsMenu.addSeparator();
445 		StartHermesJMSButtonAction hermesJMSButtonAction = new StartHermesJMSButtonAction();
446 		hermesJMSButtonAction.setEnabled( HermesUtils.isHermesJMSSupported() );
447 		toolsMenu.add( hermesJMSButtonAction );
448 
449 		return toolsMenu;
450 	}
451 
452 	private JMenu buildFileMenu()
453 	{
454 		fileMenu = new JMenu( "File" );
455 		fileMenu.setMnemonic( KeyEvent.VK_F );
456 
457 		ActionList actions = ActionListBuilder.buildActions( workspace );
458 		actions.removeAction( actions.getActionCount() - 1 );
459 
460 		ActionSupport.addActions( actions, fileMenu );
461 
462 		fileMenu.add( SoapUIPreferencesAction.getInstance() );
463 		fileMenu.add( new SavePreferencesAction() );
464 		fileMenu.add( new ImportPreferencesAction() );
465 
466 		fileMenu.addSeparator();
467 		fileMenu.add( buildRecentMenu() );
468 		fileMenu.addSeparator();
469 		fileMenu.add( new ExitAction() );
470 		fileMenu.add( new ExitWithoutSavingAction() );
471 		fileMenu.addSeparator();
472 		fileMenu.add( new ShowOnlineHelpAction( HelpUrls.OVERVIEW_HELP_URL ) );
473 
474 		return fileMenu;
475 	}
476 
477 	private JMenuItem buildRecentMenu()
478 	{
479 		JMenu recentMenu = new JMenu( "Recent" );
480 
481 		JMenu recentProjectsMenu = new JMenu( "Projects" );
482 		JMenu recentWorkspacesMenu = new JMenu( "Workspaces" );
483 		JMenu recentEditorsMenu = new JMenu( "Editors" );
484 
485 		recentMenu.add( recentEditorsMenu );
486 		recentMenu.add( recentProjectsMenu );
487 		recentMenu.add( recentWorkspacesMenu );
488 
489 		MenuScroller.setScrollerFor( recentEditorsMenu, 24, 125, 0, 1 );
490 		MenuScroller.setScrollerFor( recentProjectsMenu, 24, 125, 0, 1 );
491 		MenuScroller.setScrollerFor( recentWorkspacesMenu, 24, 125, 0, 1 );
492 
493 		RecentItemsListener recentItemsListener = new RecentItemsListener( recentWorkspacesMenu, recentProjectsMenu,
494 				recentEditorsMenu );
495 		workspace.addWorkspaceListener( recentItemsListener );
496 		desktop.addDesktopListener( recentItemsListener );
497 
498 		return recentMenu;
499 	}
500 
501 	public JFrame getFrame()
502 	{
503 		return frame;
504 	}
505 
506 	private JComponent buildMainPanel()
507 	{
508 		JInspectorPanel inspectorPanel = JInspectorPanelFactory.build( navigator );
509 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildOverviewPanel(), "Properties",
510 				"Properties for the currently selected item", true ) );
511 		inspectorPanel.setDividerLocation( 500 );
512 		inspectorPanel.setResizeWeight( 0.6 );
513 		inspectorPanel.setCurrentInspector( "Properties" );
514 
515 		return inspectorPanel.getComponent();
516 	}
517 
518 	private JComponent buildOverviewPanel()
519 	{
520 		overviewPanel = new JPanel( new BorderLayout() );
521 		overviewPanel.setBorder( BorderFactory.createEmptyBorder( 3, 0, 0, 2 ) );
522 
523 		return overviewPanel;
524 	}
525 
526 	private void setOverviewPanel( Component panel )
527 	{
528 		if( overviewPanel.getComponentCount() == 0 && panel == null )
529 			return;
530 
531 		overviewPanel.removeAll();
532 		if( panel != null )
533 			overviewPanel.add( panel, BorderLayout.CENTER );
534 		overviewPanel.revalidate();
535 		overviewPanel.repaint();
536 	}
537 
538 	private JComponent buildContentPanel()
539 	{
540 		return buildLogPanel( true, "soapUI log" );
541 	}
542 
543 	private JComponent buildLogPanel( boolean hasDefault, String defaultName )
544 	{
545 		InspectorLog4JMonitor inspectorLog4JMonitor = new InspectorLog4JMonitor( desktop.getDesktopComponent() );
546 
547 		JComponent monitor = initLogMonitor( hasDefault, defaultName, inspectorLog4JMonitor );
548 
549 		if( !SoapUI.getSettings().getBoolean( UISettings.SHOW_LOGS_AT_STARTUP ) )
550 			inspectorLog4JMonitor.activate( null );
551 
552 		MonitorPanel monitorPanel = new MonitorPanel( new RuntimeMemoryMonitorSource() );
553 		monitorPanel.start();
554 		inspectorLog4JMonitor.addInspector( new JComponentInspector<JComponent>( monitorPanel, "memory log",
555 				"Shows runtime memory consumption", true ) );
556 
557 		return monitor;
558 	}
559 
560 	public static JComponent initLogMonitor( boolean hasDefault, String defaultName, Log4JMonitor logMonitor )
561 	{
562 		SoapUI.logMonitor = logMonitor;
563 		logMonitor.addLogArea( defaultName, "com.eviware.soapui", hasDefault ).setLevel( Level.DEBUG );
564 		logMonitor.addLogArea( "http log", "httpclient.wire", false ).setLevel( Level.DEBUG );
565 		logMonitor.addLogArea( "jetty log", "jetty", false ).setLevel( Level.INFO );
566 		logMonitor.addLogArea( "error log", "soapui.errorlog", false ).setLevel( Level.DEBUG );
567 		logMonitor.addLogArea( "wsrm log", "wsrm", false ).setLevel( Level.INFO );
568 
569 		for( Object message : logCache )
570 		{
571 			logMonitor.logEvent( message );
572 		}
573 
574 		return logMonitor.getComponent();
575 	}
576 
577 	// -------------------------- OTHER METHODS --------------------------
578 
579 	public static synchronized void log( final Object msg )
580 	{
581 		if( logMonitor == null )
582 		{
583 			if( !isCommandLine && logCache.size() < 1000 )
584 				logCache.add( msg );
585 
586 			return;
587 		}
588 
589 		if( SwingUtilities.isEventDispatchThread() )
590 		{
591 			logMonitor.logEvent( msg );
592 		}
593 		else
594 		{
595 			SwingUtilities.invokeLater( new Runnable()
596 			{
597 				public void run()
598 				{
599 					logMonitor.logEvent( msg );
600 				}
601 			} );
602 		}
603 	}
604 
605 	// -------------------------- INNER CLASSES --------------------------
606 
607 	private static final class SoapUIRunner implements Runnable
608 	{
609 		public void run()
610 		{
611 			Properties props = new Properties();
612 			try
613 			{
614 				props.load( SoapUI.class.getResourceAsStream( SOAPUI_TITLE ) );
615 				String brandedTitleExt = props.getProperty( "soapui.app.title" );
616 				if( !StringUtils.isNullOrEmpty( brandedTitleExt ) )
617 				{
618 					brandedTitleExt = " - " + brandedTitleExt;
619 				}
620 				else
621 				{
622 					brandedTitleExt = "";
623 				}
624 
625 				startSoapUI( mainArgs, "soapUI " + SOAPUI_VERSION + " " + brandedTitleExt, SOAPUI_SPLASH,
626 						new StandaloneSoapUICore( true ) );
627 
628 				CajoServer.getInstance().start();
629 			}
630 			catch( Exception e )
631 			{
632 				e.printStackTrace();
633 				System.exit( 1 );
634 			}
635 		}
636 	}
637 
638 	private static final class WsdlProjectCreator implements Runnable
639 	{
640 		private final String arg;
641 
642 		public WsdlProjectCreator( String arg )
643 		{
644 			this.arg = arg;
645 		}
646 
647 		public void run()
648 		{
649 			SoapUIAction<ModelItem> action = getActionRegistry().getAction( NewWsdlProjectAction.SOAPUI_ACTION_ID );
650 			if( action != null )
651 				action.perform( getWorkspace(), arg );
652 		}
653 	}
654 
655 	private static final class RestProjectCreator implements Runnable
656 	{
657 		private final URL arg;
658 
659 		public RestProjectCreator( URL arg )
660 		{
661 			this.arg = arg;
662 		}
663 
664 		public void run()
665 		{
666 			try
667 			{
668 				WsdlProject project = ( WsdlProject )getWorkspace().createProject( arg.getHost(), null );
669 				SoapUIAction<ModelItem> action = getActionRegistry().getAction( NewRestServiceAction.SOAPUI_ACTION_ID );
670 				if( action != null )
671 					action.perform( project, arg );
672 			}
673 			catch( SoapUIException e )
674 			{
675 				e.printStackTrace();
676 			}
677 		}
678 	}
679 
680 	private final class InternalDesktopListener extends DesktopListenerAdapter
681 	{
682 		@Override
683 		public void desktopPanelSelected( DesktopPanel desktopPanel )
684 		{
685 			ModelItem modelItem = desktopPanel.getModelItem();
686 			if( modelItem != null )
687 				navigator.selectModelItem( modelItem );
688 		}
689 	}
690 
691 	private final class MainFrameWindowListener extends WindowAdapter
692 	{
693 		@Override
694 		public void windowClosing( WindowEvent e )
695 		{
696 			if( onExit() )
697 				frame.dispose();
698 		}
699 
700 		@Override
701 		public void windowClosed( WindowEvent e )
702 		{
703 			System.out.println( "exiting.." );
704 			System.exit( 0 );
705 		}
706 	}
707 
708 	public static void main( String[] args ) throws Exception
709 	{
710 		WebstartUtilCore.init();
711 
712 		mainArgs = args;
713 
714 		SoapUIRunner soapuiRunner = new SoapUIRunner();
715 		if( !SoapUI.isJXBrowserDisabled() && PlatformContext.isMacOS() )
716 		{
717 			SwingUtilities.invokeLater( soapuiRunner );
718 		}
719 		else
720 		{
721 			soapuiRunner.run();
722 		}
723 	}
724 
725 	public static String[] getMainArgs()
726 	{
727 		return mainArgs;
728 	}
729 
730 	public static SoapUI startSoapUI( String[] args, String title, String splashImage, SwingSoapUICore core )
731 			throws Exception
732 	{
733 		System.setProperty( "apple.laf.useScreenMenuBar", "true" );
734 		System.setProperty( "com.apple.mrj.application.apple.menu.about.name", "SoapUI" );
735 
736 		frame = new JFrame( title );
737 
738 		SoapUISplash splash = new SoapUISplash( splashImage, frame );
739 
740 		frame.setIconImage( UISupport.createImageIcon( FRAME_ICON ).getImage() );
741 
742 		JPopupMenu.setDefaultLightWeightPopupEnabled( false );
743 		ToolTipManager.sharedInstance().setLightWeightPopupEnabled( false );
744 
745 		isStandalone = true;
746 		soapUICore = core;
747 
748 		SoapUI soapUI = new SoapUI();
749 		Workspace workspace = null;
750 
751 		org.apache.commons.cli.Options options = initSoapUIOptions();
752 		CommandLineParser parser = new PosixParser();
753 		CommandLine cmd = parser.parse( options, args );
754 
755 		if( !processCommandLineArgs( cmd, options ) )
756 		{
757 			System.exit( 1 );
758 		}
759 
760 		if( workspaceName != null )
761 		{
762 			workspace = WorkspaceFactory.getInstance().openWorkspace( workspaceName, projectOptions );
763 			soapUICore.getSettings().setString( CURRENT_SOAPUI_WORKSPACE, workspaceName );
764 		}
765 		else
766 		{
767 			String wsfile = soapUICore.getSettings().getString( CURRENT_SOAPUI_WORKSPACE,
768 					System.getProperty( "user.home" ) + File.separatorChar + DEFAULT_WORKSPACE_FILE );
769 			try
770 			{
771 				workspace = WorkspaceFactory.getInstance().openWorkspace( wsfile, projectOptions );
772 			}
773 			catch( Exception e )
774 			{
775 				UISupport.setDialogs( new SwingDialogs( null ) );
776 				if( UISupport
777 						.confirm( "Failed to open workspace: [" + e.toString() + "], create new one instead?", "Error" ) )
778 				{
779 					new File( wsfile ).renameTo( new File( wsfile + ".bak" ) );
780 					workspace = WorkspaceFactory.getInstance().openWorkspace( wsfile, projectOptions );
781 				}
782 				else
783 				{
784 					System.exit( 1 );
785 				}
786 			}
787 		}
788 
789 		core.prepareUI();
790 		soapUI.show( workspace );
791 		core.afterStartup( workspace );
792 		Thread.sleep( 500 );
793 		splash.setVisible( false );
794 
795 		if( getSettings().getBoolean( UISettings.SHOW_STARTUP_PAGE ) && !SoapUI.isJXBrowserDisabled() )
796 		{
797 			SwingUtilities.invokeLater( new Runnable()
798 			{
799 				public void run()
800 				{
801 					showPushPage();
802 				}
803 			} );
804 		}
805 
806 		frame.setSize( 1000, 750 );
807 
808 		String[] args2 = cmd.getArgs();
809 		if( args2 != null && args2.length > 0 )
810 		{
811 			String arg = args2[0];
812 			if( arg.toUpperCase().endsWith( ".WSDL" ) || arg.toUpperCase().endsWith( ".WADL" ) )
813 			{
814 				SwingUtilities.invokeLater( new WsdlProjectCreator( arg ) );
815 			}
816 			else
817 			{
818 				try
819 				{
820 					URL url = new URL( arg );
821 					SwingUtilities.invokeLater( new RestProjectCreator( url ) );
822 				}
823 				catch( Exception e )
824 				{
825 				}
826 			}
827 		}
828 
829 		return soapUI;
830 	}
831 
832 	private static boolean processCommandLineArgs( CommandLine cmd, org.apache.commons.cli.Options options )
833 	{
834 		if( cmd.hasOption( 'w' ) )
835 		{
836 			workspaceName = cmd.getOptionValue( 'w' );
837 		}
838 
839 		if( cmd.hasOption( 'p' ) )
840 		{
841 			for( String projectNamePassword : cmd.getOptionValues( 'p' ) )
842 			{
843 				String[] nameAndPassword = projectNamePassword.split( ":" );
844 				projectOptions.put( nameAndPassword[0], nameAndPassword[1] );
845 			}
846 		}
847 
848 		return true;
849 	}
850 
851 	private static org.apache.commons.cli.Options initSoapUIOptions()
852 	{
853 
854 		org.apache.commons.cli.Options options = new org.apache.commons.cli.Options();
855 		options.addOption( "w", true, "Specified the name of the workspace xml file" );
856 		options.addOption( "p", true, "Sets project name and its password in format <project name>:<password>" );
857 
858 		return options;
859 	}
860 
861 	public static SoapUICore getSoapUICore()
862 	{
863 		return soapUICore;
864 	}
865 
866 	public static TestPropertyHolder getGlobalProperties()
867 	{
868 		return PropertyExpansionUtils.getGlobalProperties();
869 	}
870 
871 	public static void setSoapUICore( SoapUICore soapUICore )
872 	{
873 		setSoapUICore( soapUICore, false );
874 	}
875 
876 	public static void setSoapUICore( SoapUICore soapUICore, boolean isCommandLine )
877 	{
878 		SoapUI.soapUICore = soapUICore;
879 		SoapUI.isCommandLine = isCommandLine;
880 	}
881 
882 	public static boolean isStandalone()
883 	{
884 		return isStandalone;
885 	}
886 
887 	public static boolean isCommandLine()
888 	{
889 		return isCommandLine;
890 	}
891 
892 	public static JMenuBar getMenuBar()
893 	{
894 		return menuBar;
895 	}
896 
897 	private void show( Workspace workspace )
898 	{
899 		SoapUI.workspace = workspace;
900 
901 		String desktopType = soapUICore.getSettings().getString( UISettings.DESKTOP_TYPE, SoapUI.DEFAULT_DESKTOP );
902 		desktop = DesktopRegistry.getInstance().createDesktop( desktopType, workspace );
903 
904 		if( desktop == null )
905 			desktop = new StandaloneDesktop( workspace );
906 
907 		if( testMonitor == null )
908 			testMonitor = new TestMonitor();
909 
910 		soapUICore.getSettings().addSettingsListener( new SettingsListener()
911 		{
912 			public void settingChanged( String name, String newValue, String oldValue )
913 			{
914 				if( name.equals( UISettings.DESKTOP_TYPE ) )
915 				{
916 					changeDesktop( DesktopRegistry.getInstance().createDesktop( newValue, SoapUI.workspace ) );
917 				}
918 			}
919 
920 			public void settingsReloaded()
921 			{
922 				// TODO Auto-generated method stub
923 
924 			}
925 		} );
926 
927 		buildUI();
928 
929 		testMonitor.addTestMonitorListener( new LogDisablingTestMonitorListener() );
930 		testMonitor.init( workspace );
931 		frame.setVisible( true );
932 
933 		initAutoSaveTimer();
934 		initGCTimer();
935 	}
936 
937 	private void changeDesktop( SoapUIDesktop newDesktop )
938 	{
939 		desktopPanelsList.setDesktop( newDesktop );
940 		desktop.removeDesktopListener( internalDesktopListener );
941 
942 		desktop.transferTo( newDesktop );
943 		desktop.release();
944 
945 		desktop = newDesktop;
946 
947 		if( logMonitor instanceof InspectorLog4JMonitor )
948 			( ( InspectorLog4JMonitor )logMonitor ).setContentComponent( desktop.getDesktopComponent() );
949 
950 		desktop.addDesktopListener( internalDesktopListener );
951 
952 		while( desktopMenu.getItemCount() > DEFAULT_DESKTOP_ACTIONS_COUNT )
953 			desktopMenu.remove( DEFAULT_DESKTOP_ACTIONS_COUNT );
954 
955 		ActionSupport.addActions( desktop.getActions(), desktopMenu );
956 
957 		desktop.init();
958 	}
959 
960 	protected boolean onExit()
961 	{
962 		if( saveOnExit )
963 		{
964 			String question = "Exit SoapUI?";
965 
966 			if( getTestMonitor().hasRunningTests() )
967 				question += "\n(Projects with running tests will not be saved)";
968 
969 			if( !UISupport.confirm( question, "Question" ) )
970 				return false;
971 
972 			try
973 			{
974 				PropertyExpansionUtils.saveGlobalProperties();
975 				soapUICore.saveSettings();
976 				workspace.onClose();
977 			}
978 			catch( Exception e1 )
979 			{
980 				SoapUI.logError( e1 );
981 			}
982 		}
983 		else
984 		{
985 			if( !UISupport.confirm( "Exit SoapUI without saving?", "Question" ) )
986 			{
987 				saveOnExit = true;
988 				return false;
989 			}
990 		}
991 
992 		shutdown();
993 
994 		return true;
995 	}
996 
997 	public static boolean isJXBrowserDisabled()
998 	{
999 		if( UISupport.isHeadless() )
1000 			return true;
1001 
1002 		if( isCommandLine() )
1003 			return true;
1004 
1005 		String disable = System.getProperty( "soapui.jxbrowser.disable", "nope" );
1006 		if( disable.equals( "true" ) )
1007 			return true;
1008 
1009 		if( getSoapUICore() != null && getSettings().getBoolean( UISettings.DISABLE_BROWSER ) )
1010 			return true;
1011 
1012 		if( !disable.equals( "false" )
1013 				&& ( !PlatformContext.isMacOS() && "64".equals( System.getProperty( "sun.arch.data.model" ) ) ) )
1014 			return true;
1015 
1016 		return false;
1017 	}
1018 
1019 	public static void shutdown()
1020 	{
1021 		soapUITimer.cancel();
1022 	}
1023 
1024 	public static void logError( Throwable e )
1025 	{
1026 		logError( e, null );
1027 	}
1028 
1029 	public static void logError( Throwable e, String message )
1030 	{
1031 		String msg = e.getMessage();
1032 		if( msg == null )
1033 			msg = e.toString();
1034 
1035 		log.error( "An error occured [" + msg + "], see error log for details" );
1036 
1037 		try
1038 		{
1039 			if( message != null )
1040 				errorLog.error( message );
1041 
1042 			errorLog.error( e.toString(), e );
1043 		}
1044 		catch( OutOfMemoryError e1 )
1045 		{
1046 			e1.printStackTrace();
1047 			System.gc();
1048 		}
1049 		if( !isStandalone() || "true".equals( System.getProperty( "soapui.stacktrace" ) ) )
1050 			e.printStackTrace();
1051 	}
1052 
1053 	public static Logger getErrorLog()
1054 	{
1055 		return errorLog;
1056 	}
1057 
1058 	public static Logger ensureGroovyLog()
1059 	{
1060 		synchronized( checkedGroovyLogMonitor )
1061 		{
1062 			if( !checkedGroovyLogMonitor || launchedTestRunner )
1063 			{
1064 				groovyLogger = Logger.getLogger( "groovy.log" );
1065 
1066 				Log4JMonitor logMonitor = getLogMonitor();
1067 				if( logMonitor != null && !logMonitor.hasLogArea( "groovy.log" ) )
1068 				{
1069 					logMonitor.addLogArea( "script log", "groovy.log", false );
1070 					checkedGroovyLogMonitor = true;
1071 				}
1072 				else if( logMonitor == null && launchedTestRunner )
1073 				{
1074 					checkedGroovyLogMonitor = true;
1075 					launchedTestRunner = false;
1076 				}
1077 			}
1078 		}
1079 
1080 		return groovyLogger;
1081 	}
1082 
1083 	public class InternalNavigatorListener implements NavigatorListener
1084 	{
1085 		private PropertyHolderTable selectedPropertyHolderTable = null;
1086 
1087 		public void nodeSelected( SoapUITreeNode treeNode )
1088 		{
1089 			if( treeNode == null )
1090 			{
1091 				setOverviewPanel( null );
1092 			}
1093 			else
1094 			{
1095 				ModelItem modelItem = treeNode.getModelItem();
1096 
1097 				if( selectedPropertyHolderTable != null )
1098 				{
1099 					selectedPropertyHolderTable.release();
1100 					selectedPropertyHolderTable = null;
1101 				}
1102 
1103 				if( modelItem instanceof TestPropertyHolder )
1104 				{
1105 					// check for closed project -> this should be solved with a
1106 					// separate ClosedWsdlProject modelItem
1107 					if( !( modelItem instanceof WsdlProject ) || ( ( WsdlProject )modelItem ).isOpen() )
1108 					{
1109 						selectedPropertyHolderTable = new PropertyHolderTable( ( TestPropertyHolder )modelItem );
1110 					}
1111 				}
1112 
1113 				PanelBuilder<ModelItem> panelBuilder = PanelBuilderRegistry.getPanelBuilder( modelItem );
1114 				if( panelBuilder != null && panelBuilder.hasOverviewPanel() )
1115 				{
1116 					Component overviewPanel = panelBuilder.buildOverviewPanel( modelItem );
1117 					if( selectedPropertyHolderTable != null )
1118 					{
1119 						JTabbedPane tabs = new JTabbedPane();
1120 						if( overviewPanel instanceof JPropertiesTable<?> )
1121 						{
1122 							JPropertiesTable<?> t = ( JPropertiesTable<?> )overviewPanel;
1123 							tabs.addTab( t.getTitle(), overviewPanel );
1124 							t.setTitle( null );
1125 						}
1126 						else
1127 						{
1128 							tabs.addTab( "Overview", overviewPanel );
1129 						}
1130 
1131 						tabs.addTab( ( ( TestPropertyHolder )modelItem ).getPropertiesLabel(), selectedPropertyHolderTable );
1132 						overviewPanel = UISupport.createTabPanel( tabs, false );
1133 					}
1134 
1135 					setOverviewPanel( overviewPanel );
1136 				}
1137 				else
1138 				{
1139 					setOverviewPanel( null );
1140 				}
1141 			}
1142 		}
1143 	}
1144 
1145 	private class ExitAction extends AbstractAction
1146 	{
1147 		public ExitAction()
1148 		{
1149 			super( "Exit" );
1150 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
1151 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu Q" ) );
1152 		}
1153 
1154 		public void actionPerformed( ActionEvent e )
1155 		{
1156 			saveOnExit = true;
1157 			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
1158 			frame.dispatchEvent( windowEvent );
1159 		}
1160 	}
1161 
1162 	private class ApplyProxyButtonAction extends AbstractAction
1163 	{
1164 		public ApplyProxyButtonAction()
1165 		{
1166 			// putValue(Action.SMALL_ICON,
1167 			// UISupport.createImageIcon("/proxyEnabled.png"));
1168 			putValue( Action.SHORT_DESCRIPTION, "Apply proxy defined in global preferences" );
1169 		}
1170 
1171 		public void actionPerformed( ActionEvent e )
1172 		{
1173 			if( ProxyUtils.isProxyEnabled() )
1174 			{
1175 				ProxyUtils.setProxyEnabled( false );
1176 				SoapUI.getSettings().setBoolean( ProxySettings.ENABLE_PROXY, false );
1177 				applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_DISABLED_ICON ) );
1178 			}
1179 			else
1180 			{
1181 				if( StringUtils.isNullOrEmpty( SoapUI.getSettings().getString( ProxySettings.HOST, "" ) )
1182 						|| StringUtils.isNullOrEmpty( SoapUI.getSettings().getString( ProxySettings.PORT, "" ) ) )
1183 				{
1184 					SoapUIPreferencesAction.getInstance().show( SoapUIPreferencesAction.PROXY_SETTINGS );
1185 					if( !StringUtils.isNullOrEmpty( SoapUI.getSettings().getString( ProxySettings.HOST, "" ) )
1186 							&& !StringUtils.isNullOrEmpty( SoapUI.getSettings().getString( ProxySettings.PORT, "" ) ) )
1187 					{
1188 						ProxyUtils.setProxyEnabled( true );
1189 						SoapUI.getSettings().setBoolean( ProxySettings.ENABLE_PROXY, true );
1190 						applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_ENABLED_ICON ) );
1191 					}
1192 				}
1193 				else
1194 				{
1195 					ProxyUtils.setProxyEnabled( true );
1196 					SoapUI.getSettings().setBoolean( ProxySettings.ENABLE_PROXY, true );
1197 					applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_ENABLED_ICON ) );
1198 				}
1199 			}
1200 		}
1201 	}
1202 
1203 	private class LaunchLoadUIButtonAction extends AbstractAction
1204 	{
1205 		private final class LoadUIRunner implements Runnable
1206 		{
1207 			public void run()
1208 			{
1209 				Process p = StartLoadUI.launchLoadUI();
1210 				if( p != null )
1211 				{
1212 					InputStream is = p.getInputStream();
1213 					loadUILogger = Logger.getLogger( "com.eviware.soapui" );
1214 					try
1215 					{
1216 						BufferedInputStream inputStream = new BufferedInputStream( is );
1217 						BufferedReader bris = new BufferedReader( new InputStreamReader( inputStream ) );
1218 						String line = null;
1219 						while( ( line = bris.readLine() ) != null )
1220 						{
1221 							loadUILogger.info( line );
1222 						}
1223 						inputStream.close();
1224 						bris.close();
1225 						is.close();
1226 					}
1227 					catch( IOException e1 )
1228 					{// Catch exception if any
1229 						SoapUI.logError( e1 );
1230 					}
1231 				}
1232 
1233 			}
1234 		}
1235 
1236 		public LaunchLoadUIButtonAction()
1237 		{
1238 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/launchLoadUI.png" ) );
1239 			putValue( Action.SHORT_DESCRIPTION, "Launch loadUI" );
1240 		}
1241 
1242 		public void actionPerformed( ActionEvent e )
1243 		{
1244 			Thread launchLoadUI = new Thread( new LoadUIRunner() );
1245 			launchLoadUI.start();
1246 		}
1247 	}
1248 
1249 	private class ExitButtonAction extends AbstractAction
1250 	{
1251 		public ExitButtonAction()
1252 		{
1253 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/system-log-out.png" ) );
1254 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
1255 		}
1256 
1257 		public void actionPerformed( ActionEvent e )
1258 		{
1259 			saveOnExit = true;
1260 			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
1261 			frame.dispatchEvent( windowEvent );
1262 		}
1263 	}
1264 
1265 	private class ShowPushPageAction extends AbstractAction
1266 	{
1267 		public ShowPushPageAction()
1268 		{
1269 			super( "Starter Page" );
1270 			putValue( Action.SHORT_DESCRIPTION, "Shows the starter page" );
1271 		}
1272 
1273 		public void actionPerformed( ActionEvent e )
1274 		{
1275 			showPushPage();
1276 		}
1277 	}
1278 
1279 	private class ToolbarForumSearchAction extends AbstractAction
1280 	{
1281 		public ToolbarForumSearchAction()
1282 		{
1283 			putValue( Action.SHORT_DESCRIPTION, "Searches the soapUI Support Forum" );
1284 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/find.png" ) );
1285 		}
1286 
1287 		public void actionPerformed( ActionEvent e )
1288 		{
1289 			doForumSearch( searchField.getText() );
1290 		}
1291 	}
1292 
1293 	private class SearchForumAction extends AbstractAction
1294 	{
1295 		public SearchForumAction()
1296 		{
1297 			super( "Search Forum" );
1298 			putValue( Action.SHORT_DESCRIPTION, "Searches the soapUI Support Forum" );
1299 		}
1300 
1301 		public void actionPerformed( ActionEvent e )
1302 		{
1303 			String text = UISupport.prompt( "Search Forum", "Searches the online Forum, leave empty to open", "" );
1304 			if( text == null )
1305 				return;
1306 
1307 			doForumSearch( text );
1308 		}
1309 	}
1310 
1311 	public static void showPushPage()
1312 	{
1313 		if( urlDesktopPanel == null || urlDesktopPanel.isClosed() )
1314 		{
1315 			try
1316 			{
1317 				urlDesktopPanel = new URLDesktopPanel( "soapUI Starter Page", "Info on soapUI", null );
1318 			}
1319 			catch( Throwable t )
1320 			{
1321 				t.printStackTrace();
1322 				return;
1323 			}
1324 		}
1325 
1326 		DesktopPanel dp = UISupport.showDesktopPanel( urlDesktopPanel );
1327 		desktop.maximize( dp );
1328 
1329 		urlDesktopPanel.navigate( PUSH_PAGE_URL, PUSH_PAGE_ERROR_URL, true );
1330 
1331 	}
1332 
1333 	private static class AboutAction extends AbstractAction
1334 	{
1335 		public AboutAction()
1336 		{
1337 			super( "About soapUI" );
1338 			putValue( Action.SHORT_DESCRIPTION, "Shows information on soapUI" );
1339 		}
1340 
1341 		public void actionPerformed( ActionEvent e )
1342 		{
1343 			URI splashURI = null;
1344 			try
1345 			{
1346 				splashURI = UISupport.findSplash( SoapUI.SOAPUI_SPLASH ).toURI();
1347 			}
1348 			catch( URISyntaxException e1 )
1349 			{
1350 				SoapUI.logError( e1 );
1351 			}
1352 
1353 			Properties props = new Properties();
1354 			try
1355 			{
1356 				props.load( SoapUI.class.getResourceAsStream( BUILDINFO_RESOURCE ) );
1357 			}
1358 			catch( Exception e1 )
1359 			{
1360 				SoapUI.logError( e1 );
1361 			}
1362 
1363 			UISupport.showExtendedInfo(
1364 					"About soapUI",
1365 					null,
1366 					"<html><body><p align=center> <font face=\"Verdana,Arial,Helvetica\"><strong><img src=\"" + splashURI
1367 							+ "\"><br>soapUI " + SOAPUI_VERSION + ", copyright (C) 2004-2010 eviware software ab<br>"
1368 							+ "<a href=\"http://www.soapui.org\">http://www.soapui.org</a> | "
1369 							+ "<a href=\"http://www.eviware.com\">http://www.eviware.com</a><br>" + "Build "
1370 							+ props.getProperty( "build.number" ) + ", Build Date " + props.getProperty( "build.date" )
1371 							+ "</strong></font></p></body></html>",
1372 
1373 					new Dimension( 470, 350 ) );
1374 		}
1375 	}
1376 
1377 	private class ExitWithoutSavingAction extends AbstractAction
1378 	{
1379 		public ExitWithoutSavingAction()
1380 		{
1381 			super( "Exit without saving" );
1382 			putValue( Action.SHORT_DESCRIPTION, "Exits SoapUI without saving" );
1383 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "ctrl shift Q" ) );
1384 		}
1385 
1386 		public void actionPerformed( ActionEvent e )
1387 		{
1388 			saveOnExit = false;
1389 			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
1390 			frame.dispatchEvent( windowEvent );
1391 		}
1392 	}
1393 
1394 	private class SavePreferencesAction extends AbstractAction
1395 	{
1396 		public SavePreferencesAction()
1397 		{
1398 			super( "Save Preferences" );
1399 			putValue( Action.SHORT_DESCRIPTION, "Saves all global preferences" );
1400 		}
1401 
1402 		public void actionPerformed( ActionEvent e )
1403 		{
1404 			try
1405 			{
1406 				soapUICore.saveSettings();
1407 			}
1408 			catch( Exception e1 )
1409 			{
1410 				UISupport.showErrorMessage( e1 );
1411 			}
1412 		}
1413 	}
1414 
1415 	public static TestMonitor getTestMonitor()
1416 	{
1417 		if( testMonitor == null )
1418 			testMonitor = new TestMonitor();
1419 
1420 		return testMonitor;
1421 	}
1422 
1423 	public static void setTestMonitor( TestMonitor monitor )
1424 	{
1425 		testMonitor = monitor;
1426 	}
1427 
1428 	public static Log4JMonitor getLogMonitor()
1429 	{
1430 		return logMonitor;
1431 	}
1432 
1433 	public static void setLogMonitor( Log4JMonitor monitor )
1434 	{
1435 		logMonitor = monitor;
1436 	}
1437 
1438 	// instance is null in Eclipse. /Lars
1439 	// eclipse-version(s) should provide SoapUIDesktop implementation
1440 	public static SoapUIDesktop getDesktop()
1441 	{
1442 		if( desktop == null )
1443 			desktop = new NullDesktop();
1444 
1445 		return desktop;
1446 	}
1447 
1448 	public static void setDesktop( SoapUIDesktop desktop )
1449 	{
1450 		SoapUI.desktop = desktop;
1451 	}
1452 
1453 	public static Navigator getNavigator()
1454 	{
1455 		return navigator;
1456 	}
1457 
1458 	public static SoapUIActionRegistry getActionRegistry()
1459 	{
1460 		if( soapUICore == null )
1461 			soapUICore = new DefaultSoapUICore();
1462 
1463 		return soapUICore.getActionRegistry();
1464 	}
1465 
1466 	public static void setNavigator( Navigator navigator )
1467 	{
1468 		SoapUI.navigator = navigator;
1469 	}
1470 
1471 	public static void setWorkspace( Workspace workspace )
1472 	{
1473 		SoapUI.workspace = workspace;
1474 	}
1475 
1476 	public static void setStandalone( boolean standalone )
1477 	{
1478 		SoapUI.isStandalone = standalone;
1479 	}
1480 
1481 	private static class NewWsdlProjectActionDelegate extends AbstractAction
1482 	{
1483 		public NewWsdlProjectActionDelegate()
1484 		{
1485 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/project.gif" ) );
1486 			putValue( Action.SHORT_DESCRIPTION, "Creates a new soapUI Project" );
1487 		}
1488 
1489 		public void actionPerformed( ActionEvent e )
1490 		{
1491 			SoapUI.getActionRegistry().getAction( NewWsdlProjectAction.SOAPUI_ACTION_ID ).perform( workspace, null );
1492 		}
1493 	}
1494 
1495 	private static class ImportWsdlProjectActionDelegate extends AbstractAction
1496 	{
1497 		public ImportWsdlProjectActionDelegate()
1498 		{
1499 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/import_project.gif" ) );
1500 			putValue( Action.SHORT_DESCRIPTION, "Imports an existing soapUI Project into the current workspace" );
1501 		}
1502 
1503 		public void actionPerformed( ActionEvent e )
1504 		{
1505 			SoapUI.getActionRegistry().getAction( ImportWsdlProjectAction.SOAPUI_ACTION_ID ).perform( workspace, null );
1506 		}
1507 	}
1508 
1509 	private static class SaveAllActionDelegate extends AbstractAction
1510 	{
1511 		public SaveAllActionDelegate()
1512 		{
1513 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/disk_multiple.png" ) );
1514 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects in the current workspace" );
1515 		}
1516 
1517 		public void actionPerformed( ActionEvent e )
1518 		{
1519 			SoapUI.getActionRegistry().getAction( SaveAllProjectsAction.SOAPUI_ACTION_ID ).perform( workspace, null );
1520 		}
1521 	}
1522 
1523 	private class PreferencesActionDelegate extends AbstractAction
1524 	{
1525 		public PreferencesActionDelegate()
1526 		{
1527 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ) );
1528 			putValue( Action.SHORT_DESCRIPTION, "Sets Global soapUI Preferences" );
1529 		}
1530 
1531 		public void actionPerformed( ActionEvent e )
1532 		{
1533 			SoapUIPreferencesAction.getInstance().actionPerformed( null );
1534 		}
1535 	}
1536 
1537 	public static class ImportPreferencesAction extends AbstractAction
1538 	{
1539 		public static final String IMPORT_PREFERENCES_ACTION_NAME = "Import Preferences";
1540 
1541 		public ImportPreferencesAction()
1542 		{
1543 			super( ImportPreferencesAction.IMPORT_PREFERENCES_ACTION_NAME );
1544 			putValue( Action.SHORT_DESCRIPTION, "Imports soapUI Settings from another settings-file" );
1545 		}
1546 
1547 		public void actionPerformed( ActionEvent e )
1548 		{
1549 			try
1550 			{
1551 				// prompt for import
1552 				File file = UISupport.getFileDialogs().open( null, ImportPreferencesAction.IMPORT_PREFERENCES_ACTION_NAME,
1553 						".xml", "soapUI Settings XML (*.xml)", null );
1554 				if( file != null )
1555 					soapUICore.importSettings( file );
1556 			}
1557 			catch( Exception e1 )
1558 			{
1559 				UISupport.showErrorMessage( e1 );
1560 			}
1561 		}
1562 	}
1563 
1564 	public static SoapUIListenerRegistry getListenerRegistry()
1565 	{
1566 		if( soapUICore == null )
1567 			soapUICore = DefaultSoapUICore.createDefault();
1568 
1569 		return soapUICore.getListenerRegistry();
1570 	}
1571 
1572 	public static Settings getSettings()
1573 	{
1574 		if( soapUICore == null )
1575 			soapUICore = DefaultSoapUICore.createDefault();
1576 
1577 		return soapUICore.getSettings();
1578 	}
1579 
1580 	public static void importPreferences( File file ) throws Exception
1581 	{
1582 		if( soapUICore != null )
1583 			soapUICore.importSettings( file );
1584 	}
1585 
1586 	public static MockEngine getMockEngine()
1587 	{
1588 		if( soapUICore == null )
1589 			soapUICore = DefaultSoapUICore.createDefault();
1590 
1591 		return soapUICore.getMockEngine();
1592 	}
1593 
1594 	public static String saveSettings() throws Exception
1595 	{
1596 		return soapUICore == null ? null : soapUICore.saveSettings();
1597 	}
1598 
1599 	public static void initDefaultCore()
1600 	{
1601 		if( soapUICore == null )
1602 			soapUICore = DefaultSoapUICore.createDefault();
1603 	}
1604 
1605 	public class MaximizeDesktopAction extends AbstractAction
1606 	{
1607 		private JLogList lastLog;
1608 		private int lastMainDividerLocation;
1609 		private final InspectorLog4JMonitor log4JMonitor;
1610 		private int lastLogDividerLocation;
1611 
1612 		public MaximizeDesktopAction( InspectorLog4JMonitor log4JMonitor )
1613 		{
1614 			super( "Maximize Desktop" );
1615 			this.log4JMonitor = log4JMonitor;
1616 
1617 			putValue( SHORT_DESCRIPTION, "Hides/Shows the Navigator and Log tabs" );
1618 			putValue( ACCELERATOR_KEY, UISupport.getKeyStroke( "menu M" ) );
1619 		}
1620 
1621 		public void actionPerformed( ActionEvent e )
1622 		{
1623 			if( mainInspector.getCurrentInspector() != null || logMonitor.getCurrentLog() != null )
1624 			{
1625 				lastMainDividerLocation = mainInspector.getDividerLocation();
1626 				mainInspector.deactivate();
1627 
1628 				lastLog = logMonitor.getCurrentLog();
1629 				lastLogDividerLocation = log4JMonitor.getDividerLocation();
1630 
1631 				log4JMonitor.deactivate();
1632 			}
1633 			else
1634 			{
1635 				mainInspector.setCurrentInspector( "Navigator" );
1636 				mainInspector.setDividerLocation( lastMainDividerLocation == 0 ? 250 : lastMainDividerLocation );
1637 
1638 				log4JMonitor.setCurrentLog( lastLog );
1639 				log4JMonitor.setDividerLocation( lastLogDividerLocation == 0 ? 500 : lastLogDividerLocation );
1640 			}
1641 		}
1642 	}
1643 
1644 	public static void initAutoSaveTimer()
1645 	{
1646 		Settings settings = SoapUI.getSettings();
1647 		long interval = settings.getLong( UISettings.AUTO_SAVE_INTERVAL, 0 );
1648 
1649 		if( autoSaveTimerTask != null )
1650 		{
1651 			if( interval == 0 )
1652 				SoapUI.log( "Cancelling AutoSave Timer" );
1653 
1654 			autoSaveTimerTask.cancel();
1655 			autoSaveTimerTask = null;
1656 		}
1657 
1658 		if( interval > 0 )
1659 		{
1660 			autoSaveTimerTask = new AutoSaveTimerTask();
1661 
1662 			SoapUI.log( "Scheduling autosave every " + interval + " minutes" );
1663 
1664 			soapUITimer.schedule( autoSaveTimerTask, interval * 1000 * 60, interval * 1000 * 60 );
1665 		}
1666 	}
1667 
1668 	private static class AutoSaveTimerTask extends TimerTask
1669 	{
1670 		@Override
1671 		public void run()
1672 		{
1673 			SwingUtilities.invokeLater( new Runnable()
1674 			{
1675 				public void run()
1676 				{
1677 					SoapUI.log( "Autosaving Workspace" );
1678 					WorkspaceImpl wrkspc = ( WorkspaceImpl )SoapUI.getWorkspace();
1679 					if( wrkspc != null )
1680 					{
1681 						wrkspc.save( false, true );
1682 					}
1683 				}
1684 			} );
1685 		}
1686 	}
1687 
1688 	public static void initGCTimer()
1689 	{
1690 		Settings settings = SoapUI.getSettings();
1691 		long interval = settings.getLong( UISettings.GC_INTERVAL, 60 );
1692 
1693 		if( gcTimerTask != null )
1694 		{
1695 			if( interval == 0 )
1696 				SoapUI.log( "Cancelling GC Timer" );
1697 
1698 			gcTimerTask.cancel();
1699 			gcTimerTask = null;
1700 		}
1701 
1702 		if( interval > 0 )
1703 		{
1704 			gcTimerTask = new GCTimerTask();
1705 			SoapUI.log( "Scheduling garbage collection every " + interval + " seconds" );
1706 			soapUITimer.schedule( gcTimerTask, interval * 1000, interval * 1000 );
1707 		}
1708 	}
1709 
1710 	private static class GCTimerTask extends TimerTask
1711 	{
1712 		@Override
1713 		public void run()
1714 		{
1715 			System.gc();
1716 		}
1717 	}
1718 
1719 	public static JXToolBar getToolBar()
1720 	{
1721 		return mainToolbar;
1722 	}
1723 
1724 	public static void setLaunchedTestRunner( Boolean launchedTestRunner )
1725 	{
1726 		SoapUI.launchedTestRunner = launchedTestRunner;
1727 	}
1728 
1729 	public static void setProxyEnabled( boolean proxyEnabled )
1730 	{
1731 		if( applyProxyButton != null )
1732 		{
1733 			applyProxyButton.setSelected( proxyEnabled );
1734 		}
1735 
1736 		ProxyUtils.setProxyEnabled( proxyEnabled );
1737 	}
1738 
1739 	public static Timer getSoapUITimer()
1740 	{
1741 		return soapUITimer;
1742 	}
1743 
1744 	public static void setCmdLineRunner( CmdLineRunner abstractSoapUIRunner )
1745 	{
1746 		SoapUI.soapUIRunner = abstractSoapUIRunner;
1747 	}
1748 
1749 	public static CmdLineRunner getCmdLineRunner()
1750 	{
1751 		return soapUIRunner;
1752 	}
1753 }