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