/*
 *  soapUI, copyright (C) 2004-2011 smartbear.com 
 *
 *  soapUI is free software; you can redistribute it and/or modify it under the 
 *  terms of version 2.1 of the GNU Lesser General Public License as published by 
 *  the Free Software Foundation.
 *
 *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
 *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 *  See the GNU Lesser General Public License for more details at gnu.org.
 */

package com.eviware.soapui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragSource;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;

import com.google.common.base.Objects;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.eviware.soapui.actions.SaveAllProjectsAction;
import com.eviware.soapui.actions.ShowSystemPropertiesAction;
import com.eviware.soapui.actions.SoapUIPreferencesAction;
import com.eviware.soapui.actions.StartHermesJMSButtonAction;
import com.eviware.soapui.actions.SwitchDesktopPanelAction;
import com.eviware.soapui.actions.VersionUpdateAction;
import com.eviware.soapui.impl.WorkspaceImpl;
import com.eviware.soapui.impl.actions.ImportWsdlProjectAction;
import com.eviware.soapui.impl.actions.NewWsdlProjectAction;
import com.eviware.soapui.impl.rest.actions.project.NewRestServiceAction;
import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis1.Axis1XWSDL2JavaAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis2.Axis2WSDL2CodeAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.cxf.CXFAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.dotnet.DotNetWsdlAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.gsoap.GSoapAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.jaxb.JaxbXjcAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.JBossWSConsumeAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.WSToolsWsdl2JavaAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.oracle.OracleWsaGenProxyAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.tcpmon.TcpMonAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.wscompile.WSCompileAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.wsimport.WSImportAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.xfire.XFireAction;
import com.eviware.soapui.impl.wsdl.actions.iface.tools.xmlbeans.XmlBeans2Action;
import com.eviware.soapui.impl.wsdl.actions.project.StartLoadUI;
import com.eviware.soapui.impl.wsdl.actions.support.OpenUrlAction;
import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
import com.eviware.soapui.impl.wsdl.submit.transports.jms.util.HermesUtils;
import com.eviware.soapui.impl.wsdl.support.HelpUrls;
import com.eviware.soapui.impl.wsdl.support.http.ProxyUtils;
import com.eviware.soapui.integration.impl.CajoServer;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.PanelBuilder;
import com.eviware.soapui.model.TestPropertyHolder;
import com.eviware.soapui.model.environment.EnvironmentListener;
import com.eviware.soapui.model.environment.Property;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
import com.eviware.soapui.model.settings.Settings;
import com.eviware.soapui.model.settings.SettingsListener;
import com.eviware.soapui.model.tree.SoapUITreeNode;
import com.eviware.soapui.model.util.PanelBuilderRegistry;
import com.eviware.soapui.model.workspace.Workspace;
import com.eviware.soapui.model.workspace.WorkspaceFactory;
import com.eviware.soapui.monitor.MockEngine;
import com.eviware.soapui.monitor.TestMonitor;
import com.eviware.soapui.settings.ProxySettings;
import com.eviware.soapui.settings.UISettings;
import com.eviware.soapui.settings.VersionUpdateSettings;
import com.eviware.soapui.support.SoapUIException;
import com.eviware.soapui.support.SoapUIVersionUpdate;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.Tools;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.action.SoapUIAction;
import com.eviware.soapui.support.action.SoapUIActionRegistry;
import com.eviware.soapui.support.action.swing.ActionList;
import com.eviware.soapui.support.action.swing.ActionListBuilder;
import com.eviware.soapui.support.action.swing.ActionSupport;
import com.eviware.soapui.support.action.swing.SwingActionDelegate;
import com.eviware.soapui.support.components.JComponentInspector;
import com.eviware.soapui.support.components.JInspectorPanel;
import com.eviware.soapui.support.components.JInspectorPanelFactory;
import com.eviware.soapui.support.components.JPropertiesTable;
import com.eviware.soapui.support.components.JXToolBar;
import com.eviware.soapui.support.dnd.DropType;
import com.eviware.soapui.support.dnd.NavigatorDragAndDropable;
import com.eviware.soapui.support.dnd.SoapUIDragAndDropHandler;
import com.eviware.soapui.support.factory.SoapUIFactoryRegistry;
import com.eviware.soapui.support.jnlp.WebstartUtilCore;
import com.eviware.soapui.support.listener.SoapUIListenerRegistry;
import com.eviware.soapui.support.log.InspectorLog4JMonitor;
import com.eviware.soapui.support.log.JLogList;
import com.eviware.soapui.support.log.Log4JMonitor;
import com.eviware.soapui.support.log.LogDisablingTestMonitorListener;
import com.eviware.soapui.support.monitor.MonitorPanel;
import com.eviware.soapui.support.monitor.RuntimeMemoryMonitorSource;
import com.eviware.soapui.support.swing.MenuScroller;
import com.eviware.soapui.support.types.StringToStringMap;
import com.eviware.soapui.tools.CmdLineRunner;
import com.eviware.soapui.ui.JDesktopPanelsList;
import com.eviware.soapui.ui.Navigator;
import com.eviware.soapui.ui.NavigatorListener;
import com.eviware.soapui.ui.URLDesktopPanel;
import com.eviware.soapui.ui.desktop.DesktopPanel;
import com.eviware.soapui.ui.desktop.DesktopRegistry;
import com.eviware.soapui.ui.desktop.NullDesktop;
import com.eviware.soapui.ui.desktop.SoapUIDesktop;
import com.eviware.soapui.ui.desktop.standalone.StandaloneDesktop;
import com.eviware.soapui.ui.support.DesktopListenerAdapter;
import com.eviware.x.impl.swing.SwingDialogs;
import com.jgoodies.looks.HeaderStyle;
import com.jgoodies.looks.Options;
import com.jniwrapper.PlatformContext;
import com.teamdev.jxbrowser.BrowserType;

/**
 * Main SoapUI entry point.
 */

public class SoapUI
{
	public static final String DEFAULT_DESKTOP = "Default";
	public static final String CURRENT_SOAPUI_WORKSPACE = SoapUI.class.getName() + "@workspace";
	public final static Logger log = Logger.getLogger( SoapUI.class );
	public final static String SOAPUI_VERSION =
            Objects.firstNonNull(System.getProperty(SoapUISystemProperties.VERSION),
                Objects.firstNonNull(com.eviware.soapui.SoapUI.class.getPackage().getImplementationVersion(), "UNKNOWN VERSION"));
	public static final String DEFAULT_WORKSPACE_FILE = "default-soapui-workspace.xml";
	public static final String SOAPUI_SPLASH = "soapui-splash.png";
	public static final String SOAPUI_TITLE = "/branded/branded.properties";
	private static final int DEFAULT_DESKTOP_ACTIONS_COUNT = 3;
	public static final String PROXY_ENABLED_ICON = "/proxyEnabled.png";
	public static final String PROXY_DISABLED_ICON = "/proxyDisabled.png";

	@SuppressWarnings( "deprecation" )
	public static String PUSH_PAGE_URL = "http://soapui.org/Appindex/soapui-starterpage.html?version="
			+ URLEncoder.encode( SOAPUI_VERSION );
	public static String FRAME_ICON = "/16-perc.gif";
	public static String PUSH_PAGE_ERROR_URL = "file://" + System.getProperty( "soapui.home", "." )
			+ "/starter-page.html";

	// ------------------------------ FIELDS ------------------------------

	// private static SoapUI instance;
	private static List<Object> logCache = new ArrayList<Object>();

	private static SoapUICore soapUICore;
	private static Timer soapUITimer = new Timer();
	private static JFrame frame;

	private static Navigator navigator;
	private static SoapUIDesktop desktop;
	private static Workspace workspace;
	private static Log4JMonitor logMonitor;
	private static Logger errorLog = Logger.getLogger( "soapui.errorlog" );
	private static boolean isStandalone;
	private static boolean isCommandLine;
	private static TestMonitor testMonitor;

	private JMenu desktopMenu;
	private JMenu helpMenu;
	private JMenu fileMenu;
	private static JMenuBar menuBar;
	private JDesktopPanelsList desktopPanelsList;

	private static Boolean checkedGroovyLogMonitor = false;
	private static Boolean launchedTestRunner = false;

	private JPanel overviewPanel;
	private JMenu toolsMenu;
	private boolean saveOnExit = true;
	private InternalDesktopListener internalDesktopListener = new InternalDesktopListener();
	private JInspectorPanel mainInspector;

	private static AutoSaveTimerTask autoSaveTimerTask;
	private static String workspaceName;
	private static StringToStringMap projectOptions = new StringToStringMap();
	private static URLDesktopPanel urlDesktopPanel;
	private static JXToolBar mainToolbar;
	private static String[] mainArgs;
	private static GCTimerTask gcTimerTask;

	private final static ThreadPoolExecutor threadPool = ( ThreadPoolExecutor )Executors.newFixedThreadPool(
			getSystemPropertyAsInt( "soapui.threadpool.max", 200 ), new SoapUIThreadCreator() );
	private JTextField searchField;
	private static JToggleButton applyProxyButton;
	private static Logger groovyLogger;
	private static Logger loadUILogger;
	@SuppressWarnings( "unused" )
	private static JButton launchLoadUIButton;
	private static CmdLineRunner soapUIRunner;

	// --------------------------- CONSTRUCTORS ---------------------------

	private SoapUI()
	{
	}

	private static int getSystemPropertyAsInt( String string, int defaultValue )
	{

		String strValue = System.getProperty( "soapui.threadpool.max" );
		int parseInt = defaultValue;
		try
		{
			parseInt = Integer.parseInt( strValue );
		}
		catch( Exception e )
		{
			// Ignore, return default
		}

		return parseInt;
	}

	private void buildUI()
	{
		// display used java version
		log.info( "Used java version: " + System.getProperty( "java.version" ) );
		frame.addWindowListener( new MainFrameWindowListener() );
		UISupport.setMainFrame( frame );

		navigator = new Navigator( workspace );
		navigator.addNavigatorListener( new InternalNavigatorListener() );

		desktopPanelsList = new JDesktopPanelsList( desktop );

		mainInspector = JInspectorPanelFactory.build( buildContentPanel(), SwingConstants.LEFT );
		mainInspector.addInspector( new JComponentInspector<JComponent>( buildMainPanel(), "Navigator",
				"The soapUI Navigator", true ) );
		mainInspector.setCurrentInspector( "Navigator" );

		frame.setJMenuBar( buildMainMenu() );
		frame.getContentPane().add( buildToolbar(), BorderLayout.NORTH );
		frame.getContentPane().add( mainInspector.getComponent(), BorderLayout.CENTER );
		frame.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
		frame.setSize( 1000, 750 );

		mainInspector.setDividerLocation( 250 );
		mainInspector.setResizeWeight( 0.1 );
		navigator.selectModelItem( workspace );

		desktop.addDesktopListener( internalDesktopListener );

		ToolTipManager.sharedInstance().setInitialDelay( 200 );

		JTree mainTree = navigator.getMainTree();
		DragSource dragSource = DragSource.getDefaultDragSource();
		SoapUIDragAndDropHandler navigatorDragAndDropHandler = new SoapUIDragAndDropHandler(
				new NavigatorDragAndDropable( mainTree ), DropType.ON + DropType.AFTER );

		dragSource.createDefaultDragGestureRecognizer( mainTree, DnDConstants.ACTION_COPY_OR_MOVE,
				navigatorDragAndDropHandler );

		desktop.init();
	}

	public static JToggleButton getApplyProxyButton()
	{
		return applyProxyButton;
	}

	private JComponent buildToolbar()
	{
		mainToolbar = new JXToolBar();
		mainToolbar.setFloatable( false );
		mainToolbar.setRollover( true );
		mainToolbar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
		mainToolbar.add( new NewWsdlProjectActionDelegate() );
		mainToolbar.add( new ImportWsdlProjectActionDelegate() );
		mainToolbar.add( new SaveAllActionDelegate() );
		mainToolbar.addSpace( 2 );
		mainToolbar.add( new ShowOnlineHelpAction( "User Guide", HelpUrls.USERGUIDE_HELP_URL,
				"Opens the soapUI User-Guide in a browser" ) );
		mainToolbar.add( new ShowOnlineHelpAction( "Forum", HelpUrls.FORUMS_HELP_URL,
				"Opens the soapUI Forum in a browser", "/group_go.png" ) );
		mainToolbar.addSpace( 2 );
		mainToolbar.add( new ShowOnlineHelpAction( "Trial", HelpUrls.TRIAL_URL, "Apply for soapUI Pro Trial License",
				"/favicon.png" ) );
		mainToolbar.addSpace( 2 );
		mainToolbar.add( new PreferencesActionDelegate() );
		applyProxyButton = ( JToggleButton )mainToolbar.add( new JToggleButton( new ApplyProxyButtonAction() ) );
		ProxyUtils.setProxyEnabled( getSettings().getBoolean( ProxySettings.ENABLE_PROXY ) );
		if( ProxyUtils.isProxyEnabled() )
		{
			applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_ENABLED_ICON ) );
			applyProxyButton.setSelected( true );
			ProxyUtils.setProxyEnabled( true );
		}
		else
		{
			applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_DISABLED_ICON ) );
			ProxyUtils.setProxyEnabled( false );
		}
		launchLoadUIButton = mainToolbar.add( new LaunchLoadUIButtonAction() );
		//		mainToolbar.add( new ExitButtonAction() );

		mainToolbar.addGlue();

		searchField = new JTextField( 20 );
		searchField.addKeyListener( new KeyAdapter()
		{
			@Override
			public void keyTyped( KeyEvent e )
			{
				if( e.getKeyChar() == '\n' )
				{
					doForumSearch( searchField.getText() );
				}
			}
		} );

		mainToolbar.addLabeledFixed( "Search Forum", searchField );
		mainToolbar.add( new ToolbarForumSearchAction() );
		mainToolbar.add( new ShowOnlineHelpAction( HelpUrls.USERGUIDE_HELP_URL ) );

		for( int i = 0; i < mainToolbar.getComponentCount(); i++ )
		{
			if( mainToolbar.getComponent( i ) instanceof JComponent )
			{
				( ( JComponent )mainToolbar.getComponent( i ) ).setBorder( BorderFactory.createEmptyBorder( 4, 2, 4, 2 ) );
			}
		}

		mainToolbar.setBorder( BorderFactory.createEmptyBorder( 3, 1, 3, 1 ) );

		return mainToolbar;
	}

	@SuppressWarnings( "deprecation" )
	public void doForumSearch( String text )
	{
		if( !searchField.getText().equals( text ) )
			searchField.setText( text );

		if( StringUtils.hasContent( text ) )
		{
			Tools.openURL( "http://www.eviware.com/forums/search.php?keywords=" + URLEncoder.encode( text.trim() ) );
		}
		else
		{
			Tools.openURL( "http://www.eviware.com/forums" );
		}
	}

	private JMenuBar buildMainMenu()
	{
		menuBar = new JMenuBar();
		menuBar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );

		menuBar.add( buildFileMenu() );
		menuBar.add( buildToolsMenu() );
		menuBar.add( buildDesktopMenu() );
		menuBar.add( buildHelpMenu() );

		return menuBar;
	}

	public static ThreadPoolExecutor getThreadPool()
	{
		return threadPool;
	}

	public static Workspace getWorkspace()
	{
		return workspace;
	}

	private JMenu buildDesktopMenu()
	{
		desktopMenu = new JMenu( "Desktop" );
		desktopMenu.setMnemonic( KeyEvent.VK_D );
		desktopMenu.add( new SwitchDesktopPanelAction( desktopPanelsList ) );
		desktopMenu.add( new MaximizeDesktopAction( ( InspectorLog4JMonitor )logMonitor ) );
		desktopMenu.addSeparator();

		ActionSupport.addActions( desktop.getActions(), desktopMenu );

		return desktopMenu;
	}

	private JMenu buildHelpMenu()
	{
		helpMenu = new JMenu( "Help" );
		helpMenu.setMnemonic( KeyEvent.VK_H );

		helpMenu.add( new ShowPushPageAction() );
		helpMenu.addSeparator();
		helpMenu.add( new ShowOnlineHelpAction( "User Guide", HelpUrls.USERGUIDE_HELP_URL ) );
		helpMenu.add( new ShowOnlineHelpAction( "Getting Started", HelpUrls.GETTINGSTARTED_HELP_URL ) );
		helpMenu.add( new SearchForumAction() );
		helpMenu.addSeparator();
		helpMenu.add( new ShowSystemPropertiesAction() );
		helpMenu.addSeparator();
		helpMenu.add( new VersionUpdateAction() );
		helpMenu.addSeparator();
		helpMenu.add( new ShowOnlineHelpAction( "soapUI Pro Trial", HelpUrls.TRIAL_URL,
				"Apply for soapUI Pro Trial License", "/favicon.png" ) );
		helpMenu.addSeparator();
		helpMenu.add( new OpenUrlAction( "soapui.org", "http://www.soapui.org" ) );
		helpMenu.add( new OpenUrlAction( "smartbear.com", "http://smartbear.com" ) );
		helpMenu.addSeparator();
		helpMenu.add( new AboutAction() );
		return helpMenu;
	}

	private JMenu buildToolsMenu()
	{
		toolsMenu = new JMenu( "Tools" );
		toolsMenu.setMnemonic( KeyEvent.VK_T );

		toolsMenu.add( SwingActionDelegate.createDelegate( WSToolsWsdl2JavaAction.SOAPUI_ACTION_ID ) );
		toolsMenu.add( SwingActionDelegate.createDelegate( JBossWSConsumeAction.SOAPUI_ACTION_ID ) );
		toolsMenu.addSeparator();
		toolsMenu.add( SwingActionDelegate.createDelegate( WSCompileAction.SOAPUI_ACTION_ID ) );
		toolsMenu.add( SwingActionDelegate.createDelegate( WSImportAction.SOAPUI_ACTION_ID ) );
		toolsMenu.addSeparator();
		toolsMenu.add( SwingActionDelegate.createDelegate( Axis1XWSDL2JavaAction.SOAPUI_ACTION_ID ) );
		toolsMenu.add( SwingActionDelegate.createDelegate( Axis2WSDL2CodeAction.SOAPUI_ACTION_ID ) );
		toolsMenu.add( SwingActionDelegate.createDelegate( CXFAction.SOAPUI_ACTION_ID ) );
		toolsMenu.add( SwingActionDelegate.createDelegate( XFireAction.SOAPUI_ACTION_ID ) );
		toolsMenu.add( SwingActionDelegate.createDelegate( OracleWsaGenProxyAction.SOAPUI_ACTION_ID ) );
		toolsMenu.addSeparator();
		toolsMenu.add( SwingActionDelegate.createDelegate( XmlBeans2Action.SOAPUI_ACTION_ID ) );
		toolsMenu.add( SwingActionDelegate.createDelegate( JaxbXjcAction.SOAPUI_ACTION_ID ) );
		toolsMenu.addSeparator();
		toolsMenu.add( SwingActionDelegate.createDelegate( DotNetWsdlAction.SOAPUI_ACTION_ID ) );
		toolsMenu.add( SwingActionDelegate.createDelegate( GSoapAction.SOAPUI_ACTION_ID ) );
		toolsMenu.addSeparator();
		toolsMenu.add( SwingActionDelegate.createDelegate( TcpMonAction.SOAPUI_ACTION_ID ) );
		// toolsMenu.addSeparator();
		// toolsMenu.add( new XQueryXPathTesterAction());
		toolsMenu.addSeparator();
		StartHermesJMSButtonAction hermesJMSButtonAction = new StartHermesJMSButtonAction();
		hermesJMSButtonAction.setEnabled( HermesUtils.isHermesJMSSupported() );
		toolsMenu.add( hermesJMSButtonAction );

		return toolsMenu;
	}

	private JMenu buildFileMenu()
	{
		fileMenu = new JMenu( "File" );
		fileMenu.setMnemonic( KeyEvent.VK_F );

		ActionList actions = ActionListBuilder.buildActions( workspace );
		actions.removeAction( actions.getActionCount() - 1 );

		ActionSupport.addActions( actions, fileMenu );

		fileMenu.add( SoapUIPreferencesAction.getInstance() );
		fileMenu.add( new SavePreferencesAction() );
		fileMenu.add( new ImportPreferencesAction() );

		fileMenu.addSeparator();
		fileMenu.add( buildRecentMenu() );
		fileMenu.addSeparator();
		fileMenu.add( new ExitAction() );
		fileMenu.add( new ExitWithoutSavingAction() );
		fileMenu.addSeparator();
		fileMenu.add( new ShowOnlineHelpAction( HelpUrls.OVERVIEW_HELP_URL ) );

		return fileMenu;
	}

	private JMenuItem buildRecentMenu()
	{
		JMenu recentMenu = new JMenu( "Recent" );

		JMenu recentProjectsMenu = new JMenu( "Projects" );
		JMenu recentWorkspacesMenu = new JMenu( "Workspaces" );
		JMenu recentEditorsMenu = new JMenu( "Editors" );

		recentMenu.add( recentEditorsMenu );
		recentMenu.add( recentProjectsMenu );
		recentMenu.add( recentWorkspacesMenu );

		MenuScroller.setScrollerFor( recentEditorsMenu, 24, 125, 0, 1 );
		MenuScroller.setScrollerFor( recentProjectsMenu, 24, 125, 0, 1 );
		MenuScroller.setScrollerFor( recentWorkspacesMenu, 24, 125, 0, 1 );

		RecentItemsListener recentItemsListener = new RecentItemsListener( recentWorkspacesMenu, recentProjectsMenu,
				recentEditorsMenu );
		workspace.addWorkspaceListener( recentItemsListener );
		desktop.addDesktopListener( recentItemsListener );

		return recentMenu;
	}

	public static JFrame getFrame()
	{
		return frame;
	}

	private JComponent buildMainPanel()
	{
		JInspectorPanel inspectorPanel = JInspectorPanelFactory.build( navigator );
		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildOverviewPanel(), "Properties",
				"Properties for the currently selected item", true ) );
		inspectorPanel.setDividerLocation( 500 );
		inspectorPanel.setResizeWeight( 0.6 );
		inspectorPanel.setCurrentInspector( "Properties" );

		return inspectorPanel.getComponent();
	}

	private JComponent buildOverviewPanel()
	{
		overviewPanel = new JPanel( new BorderLayout() );
		overviewPanel.setBorder( BorderFactory.createEmptyBorder( 3, 0, 0, 2 ) );

		return overviewPanel;
	}

	private void setOverviewPanel( Component panel )
	{
		if( overviewPanel.getComponentCount() == 0 && panel == null )
			return;

		overviewPanel.removeAll();
		if( panel != null )
			overviewPanel.add( panel, BorderLayout.CENTER );
		overviewPanel.revalidate();
		overviewPanel.repaint();
	}

	private JComponent buildContentPanel()
	{
		return buildLogPanel( true, "soapUI log" );
	}

	private JComponent buildLogPanel( boolean hasDefault, String defaultName )
	{
		InspectorLog4JMonitor inspectorLog4JMonitor = new InspectorLog4JMonitor( desktop.getDesktopComponent() );

		JComponent monitor = initLogMonitor( hasDefault, defaultName, inspectorLog4JMonitor );

		if( !SoapUI.getSettings().getBoolean( UISettings.SHOW_LOGS_AT_STARTUP ) )
			inspectorLog4JMonitor.activate( null );

		MonitorPanel monitorPanel = new MonitorPanel( new RuntimeMemoryMonitorSource() );
		monitorPanel.start();
		inspectorLog4JMonitor.addInspector( new JComponentInspector<JComponent>( monitorPanel, "memory log",
				"Shows runtime memory consumption", true ) );

		return monitor;
	}

	public static JComponent initLogMonitor( boolean hasDefault, String defaultName, Log4JMonitor logMonitor )
	{
		SoapUI.logMonitor = logMonitor;
		logMonitor.addLogArea( defaultName, "com.eviware.soapui", hasDefault ).setLevel( Level.DEBUG );
		logMonitor.addLogArea( "http log", "org.apache.http.wire", false ).setLevel( Level.DEBUG );
		logMonitor.addLogArea( "jetty log", "jetty", false ).setLevel( Level.INFO );
		logMonitor.addLogArea( "error log", "soapui.errorlog", false ).setLevel( Level.DEBUG );
		logMonitor.addLogArea( "wsrm log", "wsrm", false ).setLevel( Level.INFO );

		for( Object message : logCache )
		{
			logMonitor.logEvent( message );
		}

		return logMonitor.getComponent();
	}

	// -------------------------- OTHER METHODS --------------------------

	public static synchronized void log( final Object msg )
	{
		if( logMonitor == null )
		{
			if( !isCommandLine && logCache.size() < 1000 )
				logCache.add( msg );

			return;
		}

		if( SwingUtilities.isEventDispatchThread() )
		{
			logMonitor.logEvent( msg );
		}
		else
		{
			SwingUtilities.invokeLater( new Runnable()
			{
				public void run()
				{
					logMonitor.logEvent( msg );
				}
			} );
		}
	}

	// -------------------------- INNER CLASSES --------------------------

	private static final class SoapUIRunner implements Runnable
	{
		public void run()
		{
			Properties props = new Properties();
			try
			{
				props.load( SoapUI.class.getResourceAsStream( SOAPUI_TITLE ) );
				String brandedTitleExt = props.getProperty( "soapui.app.title" );
				if( !StringUtils.isNullOrEmpty( brandedTitleExt ) )
				{
					brandedTitleExt = " - " + brandedTitleExt;
				}
				else
				{
					brandedTitleExt = "";
				}

				startSoapUI( mainArgs, "soapUI " + SOAPUI_VERSION + " " + brandedTitleExt, SOAPUI_SPLASH,
						new StandaloneSoapUICore( true ) );

				if( isAutoUpdateVersion() )
					new SoapUIVersionUpdate().checkForNewVersion( false );

				CajoServer.getInstance().start();
			}
			catch( Exception e )
			{
				e.printStackTrace();
				System.exit( 1 );
			}
		}
	}

	private static final class WsdlProjectCreator implements Runnable
	{
		private final String arg;

		public WsdlProjectCreator( String arg )
		{
			this.arg = arg;
		}

		public void run()
		{
			SoapUIAction<ModelItem> action = getActionRegistry().getAction( NewWsdlProjectAction.SOAPUI_ACTION_ID );
			if( action != null )
				action.perform( getWorkspace(), arg );
		}
	}

	private static final class RestProjectCreator implements Runnable
	{
		private final URL arg;

		public RestProjectCreator( URL arg )
		{
			this.arg = arg;
		}

		public void run()
		{
			try
			{
				WsdlProject project = ( WsdlProject )getWorkspace().createProject( arg.getHost(), null );
				SoapUIAction<ModelItem> action = getActionRegistry().getAction( NewRestServiceAction.SOAPUI_ACTION_ID );
				if( action != null )
					action.perform( project, arg );
			}
			catch( SoapUIException e )
			{
				e.printStackTrace();
			}
		}
	}

	private final class InternalDesktopListener extends DesktopListenerAdapter
	{
		@Override
		public void desktopPanelSelected( DesktopPanel desktopPanel )
		{
			ModelItem modelItem = desktopPanel.getModelItem();
			if( modelItem != null )
				navigator.selectModelItem( modelItem );
		}
	}

	private final class MainFrameWindowListener extends WindowAdapter
	{
		@Override
		public void windowClosing( WindowEvent e )
		{
			if( onExit() )
				frame.dispose();
		}

		@Override
		public void windowClosed( WindowEvent e )
		{
			System.out.println( "exiting.." );
			System.exit( 0 );
		}
	}

	public static void main( String[] args ) throws Exception
	{
		WebstartUtilCore.init();

		mainArgs = args;

		SoapUIRunner soapuiRunner = new SoapUIRunner();
		if( !SoapUI.isJXBrowserDisabled( true ) && PlatformContext.isMacOS() )
		{
			SwingUtilities.invokeLater( soapuiRunner );
		}
		else
		{
			soapuiRunner.run();
		}

	}

	public static String[] getMainArgs()
	{
		return mainArgs;
	}

	public static SoapUI startSoapUI( String[] args, String title, String splashImage, SwingSoapUICore core )
			throws Exception
	{
		System.setProperty( "apple.laf.useScreenMenuBar", "true" );
		System.setProperty( "com.apple.mrj.application.apple.menu.about.name", "SoapUI" );

		frame = new JFrame( title );

		SoapUISplash splash = new SoapUISplash( splashImage, frame );

		frame.setIconImage( UISupport.createImageIcon( FRAME_ICON ).getImage() );

		JPopupMenu.setDefaultLightWeightPopupEnabled( false );
		ToolTipManager.sharedInstance().setLightWeightPopupEnabled( false );

		isStandalone = true;
		soapUICore = core;

		SoapUI soapUI = new SoapUI();
		Workspace workspace = null;

		org.apache.commons.cli.Options options = initSoapUIOptions();
		CommandLineParser parser = new PosixParser();
		CommandLine cmd = parser.parse( options, args );

		if( !processCommandLineArgs( cmd, options ) )
		{
			System.exit( 1 );
		}

		if( workspaceName != null )
		{
			workspace = WorkspaceFactory.getInstance().openWorkspace( workspaceName, projectOptions );
			soapUICore.getSettings().setString( CURRENT_SOAPUI_WORKSPACE, workspaceName );
		}
		else
		{
			String wsfile = soapUICore.getSettings().getString( CURRENT_SOAPUI_WORKSPACE,
					System.getProperty( "user.home" ) + File.separatorChar + DEFAULT_WORKSPACE_FILE );
			try
			{
				workspace = WorkspaceFactory.getInstance().openWorkspace( wsfile, projectOptions );
			}
			catch( Exception e )
			{
				UISupport.setDialogs( new SwingDialogs( null ) );
				if( UISupport
						.confirm( "Failed to open workspace: [" + e.toString() + "], create new one instead?", "Error" ) )
				{
					new File( wsfile ).renameTo( new File( wsfile + ".bak" ) );
					workspace = WorkspaceFactory.getInstance().openWorkspace( wsfile, projectOptions );
				}
				else
				{
					System.exit( 1 );
				}
			}
		}

		core.prepareUI();
		soapUI.show( workspace );
		core.afterStartup( workspace );
		Thread.sleep( 500 );
		splash.setVisible( false );

		if( getSettings().getBoolean( UISettings.SHOW_STARTUP_PAGE ) && !SoapUI.isJXBrowserDisabled( true ) )
		{
			SwingUtilities.invokeLater( new Runnable()
			{
				public void run()
				{
					showPushPage();
				}
			} );
		}

		frame.setSize( 1000, 750 );

		String[] args2 = cmd.getArgs();
		if( args2 != null && args2.length > 0 )
		{
			String arg = args2[0];
			if( arg.toUpperCase().endsWith( ".WSDL" ) || arg.toUpperCase().endsWith( ".WADL" ) )
			{
				SwingUtilities.invokeLater( new WsdlProjectCreator( arg ) );
			}
			else
			{
				try
				{
					URL url = new URL( arg );
					SwingUtilities.invokeLater( new RestProjectCreator( url ) );
				}
				catch( Exception e )
				{
				}
			}
		}
		return soapUI;
	}

	private static boolean processCommandLineArgs( CommandLine cmd, org.apache.commons.cli.Options options )
	{
		if( cmd.hasOption( 'w' ) )
		{
			workspaceName = cmd.getOptionValue( 'w' );
		}

		if( cmd.hasOption( 'p' ) )
		{
			for( String projectNamePassword : cmd.getOptionValues( 'p' ) )
			{
				String[] nameAndPassword = projectNamePassword.split( ":" );
				projectOptions.put( nameAndPassword[0], nameAndPassword[1] );
			}
		}

		return true;
	}

	private static org.apache.commons.cli.Options initSoapUIOptions()
	{

		org.apache.commons.cli.Options options = new org.apache.commons.cli.Options();
		options.addOption( "w", true, "Specified the name of the workspace xml file" );
		options.addOption( "p", true, "Sets project name and its password in format <project name>:<password>" );

		return options;
	}

	public static SoapUICore getSoapUICore()
	{
		return soapUICore;
	}

	public static TestPropertyHolder getGlobalProperties()
	{
		return PropertyExpansionUtils.getGlobalProperties();
	}

	public static void setSoapUICore( SoapUICore soapUICore )
	{
		setSoapUICore( soapUICore, false );
	}

	public static void setSoapUICore( SoapUICore soapUICore, boolean isCommandLine )
	{
		SoapUI.soapUICore = soapUICore;
		SoapUI.isCommandLine = isCommandLine;
	}

	public static boolean isStandalone()
	{
		return isStandalone;
	}

	public static boolean isCommandLine()
	{
		return isCommandLine;
	}

	public static JMenuBar getMenuBar()
	{
		return menuBar;
	}

	private void show( Workspace workspace )
	{
		SoapUI.workspace = workspace;

		String desktopType = soapUICore.getSettings().getString( UISettings.DESKTOP_TYPE, SoapUI.DEFAULT_DESKTOP );
		desktop = DesktopRegistry.getInstance().createDesktop( desktopType, workspace );

		if( desktop == null )
			desktop = new StandaloneDesktop( workspace );

		if( testMonitor == null )
			testMonitor = new TestMonitor();

		soapUICore.getSettings().addSettingsListener( new SettingsListener()
		{
			public void settingChanged( String name, String newValue, String oldValue )
			{
				if( name.equals( UISettings.DESKTOP_TYPE ) )
				{
					changeDesktop( DesktopRegistry.getInstance().createDesktop( newValue, SoapUI.workspace ) );
				}
			}

			public void settingsReloaded()
			{
				// TODO Auto-generated method stub

			}
		} );

		buildUI();

		testMonitor.addTestMonitorListener( new LogDisablingTestMonitorListener() );
		testMonitor.init( workspace );
		frame.setVisible( true );

		initAutoSaveTimer();
		initGCTimer();
	}

	private void changeDesktop( SoapUIDesktop newDesktop )
	{
		desktopPanelsList.setDesktop( newDesktop );
		desktop.removeDesktopListener( internalDesktopListener );

		desktop.transferTo( newDesktop );
		desktop.release();

		desktop = newDesktop;

		if( logMonitor instanceof InspectorLog4JMonitor )
			( ( InspectorLog4JMonitor )logMonitor ).setContentComponent( desktop.getDesktopComponent() );

		desktop.addDesktopListener( internalDesktopListener );

		while( desktopMenu.getItemCount() > DEFAULT_DESKTOP_ACTIONS_COUNT )
			desktopMenu.remove( DEFAULT_DESKTOP_ACTIONS_COUNT );

		ActionSupport.addActions( desktop.getActions(), desktopMenu );

		desktop.init();
	}

	protected boolean onExit()
	{
		if( saveOnExit )
		{
			String question = "Exit SoapUI?";

			if( getTestMonitor().hasRunningTests() )
				question += "\n(Projects with running tests will not be saved)";

			if( !UISupport.confirm( question, "Question" ) )
				return false;

			try
			{
				soapUICore.saveSettings();
				workspace.onClose();
			}
			catch( Exception e1 )
			{
				SoapUI.logError( e1 );
			}
		}
		else
		{
			if( !UISupport.confirm( "Exit SoapUI without saving?", "Question" ) )
			{
				saveOnExit = true;
				return false;
			}
		}

		shutdown();

		return true;
	}

	public static boolean isJXBrowserDisabled()
	{
		return isJXBrowserDisabled( false );
	}

	public static boolean isJXBrowserDisabled( boolean allowNative )
	{
		if( UISupport.isHeadless() )
			return true;

		if( isCommandLine() )
			return true;

		String disable = System.getProperty( "soapui.jxbrowser.disable", "nope" );
		if( disable.equals( "true" ) )
			return true;

		if( getSoapUICore() != null && getSettings().getBoolean( UISettings.DISABLE_BROWSER ) )
			return true;

		if( !disable.equals( "false" ) && allowNative == true
				&& ( BrowserType.Mozilla.isSupported() || BrowserType.IE.isSupported() || BrowserType.Safari.isSupported() ) )
			return false;

		if( !disable.equals( "false" )
				&& ( !PlatformContext.isMacOS() && "64".equals( System.getProperty( "sun.arch.data.model" ) ) ) )
			return true;

		return false;
	}

	public static boolean isJXBrowserPluginsDisabled()
	{
		return getSettings().getBoolean( UISettings.DISABLE_BROWSER_PLUGINS );
	}

	public static void shutdown()
	{
		soapUITimer.cancel();
	}

	public static void logError( Throwable e )
	{
		logError( e, null );
	}

	public static void logError( Throwable e, String message )
	{
		String msg = e.getMessage();
		if( msg == null )
			msg = e.toString();

		log.error( "An error occured [" + msg + "], see error log for details" );

		try
		{
			if( message != null )
				errorLog.error( message );

			errorLog.error( e.toString(), e );
		}
		catch( OutOfMemoryError e1 )
		{
			e1.printStackTrace();
			System.gc();
		}
		if( !isStandalone() || "true".equals( System.getProperty( "soapui.stacktrace" ) ) )
			e.printStackTrace();
	}

	public static Logger getErrorLog()
	{
		return errorLog;
	}

	public static Logger ensureGroovyLog()
	{
		synchronized( threadPool )
		{
			if( !checkedGroovyLogMonitor || launchedTestRunner )
			{
				groovyLogger = Logger.getLogger( "groovy.log" );

				Log4JMonitor logMonitor = getLogMonitor();
				if( logMonitor != null && !logMonitor.hasLogArea( "groovy.log" ) )
				{
					logMonitor.addLogArea( "script log", "groovy.log", false );
					checkedGroovyLogMonitor = true;
				}
				else if( logMonitor == null && launchedTestRunner )
				{
					checkedGroovyLogMonitor = true;
					launchedTestRunner = false;
				}
			}
		}

		return groovyLogger;
	}

	public class InternalNavigatorListener implements NavigatorListener
	{
		private PropertyHolderTable selectedPropertyHolderTable = null;

		public void nodeSelected( SoapUITreeNode treeNode )
		{
			if( treeNode == null )
			{
				setOverviewPanel( null );
			}
			else
			{
				ModelItem modelItem = treeNode.getModelItem();

				if( selectedPropertyHolderTable != null )
				{
					selectedPropertyHolderTable.release();
					selectedPropertyHolderTable = null;
				}

				if( modelItem instanceof TestPropertyHolder )
				{
					// check for closed project -> this should be solved with a
					// separate ClosedWsdlProject modelItem
					if( !( modelItem instanceof WsdlProject ) || ( ( WsdlProject )modelItem ).isOpen() )
					{
						selectedPropertyHolderTable = new PropertyHolderTable( ( TestPropertyHolder )modelItem );

						if( modelItem instanceof WsdlProject )
						{
							WsdlProject project = ( WsdlProject )modelItem;
							EnvironmentListener environmentListener = new EnvironmentListener()
							{
								public void propertyValueChanged( Property property )
								{
									selectedPropertyHolderTable.getPropertiesModel().fireTableDataChanged();
								}
							};
							project.addEnvironmentListener( environmentListener );
							selectedPropertyHolderTable.setEnvironmentListener( environmentListener );
							project.addProjectListener( selectedPropertyHolderTable.getProjectListener() );
						}
					}
				}

				PanelBuilder<ModelItem> panelBuilder = PanelBuilderRegistry.getPanelBuilder( modelItem );
				if( panelBuilder != null && panelBuilder.hasOverviewPanel() )
				{
					Component overviewPanel = panelBuilder.buildOverviewPanel( modelItem );
					if( selectedPropertyHolderTable != null )
					{
						JTabbedPane tabs = new JTabbedPane();
						if( overviewPanel instanceof JPropertiesTable<?> )
						{
							JPropertiesTable<?> t = ( JPropertiesTable<?> )overviewPanel;
							tabs.addTab( t.getTitle(), overviewPanel );
							t.setTitle( null );
						}
						else
						{
							tabs.addTab( "Overview", overviewPanel );
						}

						tabs.addTab( ( ( TestPropertyHolder )modelItem ).getPropertiesLabel(), selectedPropertyHolderTable );
						overviewPanel = UISupport.createTabPanel( tabs, false );
					}

					setOverviewPanel( overviewPanel );
				}
				else
				{
					setOverviewPanel( null );
				}
			}
		}
	}

	private class ExitAction extends AbstractAction
	{
		public ExitAction()
		{
			super( "Exit" );
			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu Q" ) );
		}

		public void actionPerformed( ActionEvent e )
		{
			saveOnExit = true;
			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
			frame.dispatchEvent( windowEvent );
		}
	}

	private class ApplyProxyButtonAction extends AbstractAction
	{
		public ApplyProxyButtonAction()
		{
			// putValue(Action.SMALL_ICON,
			// UISupport.createImageIcon("/proxyEnabled.png"));
			putValue( Action.SHORT_DESCRIPTION, "Apply proxy defined in global preferences" );
		}

		public void actionPerformed( ActionEvent e )
		{
			if( ProxyUtils.isProxyEnabled() )
			{
				ProxyUtils.setProxyEnabled( false );
				SoapUI.getSettings().setBoolean( ProxySettings.ENABLE_PROXY, false );
				applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_DISABLED_ICON ) );
			}
			else
			{
				if( StringUtils.isNullOrEmpty( SoapUI.getSettings().getString( ProxySettings.HOST, "" ) )
						|| StringUtils.isNullOrEmpty( SoapUI.getSettings().getString( ProxySettings.PORT, "" ) ) )
				{
					SoapUIPreferencesAction.getInstance().show( SoapUIPreferencesAction.PROXY_SETTINGS );
					if( !StringUtils.isNullOrEmpty( SoapUI.getSettings().getString( ProxySettings.HOST, "" ) )
							&& !StringUtils.isNullOrEmpty( SoapUI.getSettings().getString( ProxySettings.PORT, "" ) ) )
					{
						ProxyUtils.setProxyEnabled( true );
						SoapUI.getSettings().setBoolean( ProxySettings.ENABLE_PROXY, true );
						applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_ENABLED_ICON ) );
					}
				}
				else
				{
					ProxyUtils.setProxyEnabled( true );
					SoapUI.getSettings().setBoolean( ProxySettings.ENABLE_PROXY, true );
					applyProxyButton.setIcon( UISupport.createImageIcon( PROXY_ENABLED_ICON ) );
				}
			}
		}
	}

	private class LaunchLoadUIButtonAction extends AbstractAction
	{
		private final class LoadUIRunner implements Runnable
		{
			public void run()
			{
				Process p = StartLoadUI.launchLoadUI();
				if( p != null )
				{
					InputStream is = p.getInputStream();
					loadUILogger = Logger.getLogger( "com.eviware.soapui" );
					try
					{
						BufferedInputStream inputStream = new BufferedInputStream( is );
						BufferedReader bris = new BufferedReader( new InputStreamReader( inputStream ) );
						String line = null;
						while( ( line = bris.readLine() ) != null )
						{
							loadUILogger.info( line );
						}
						inputStream.close();
						bris.close();
						is.close();
					}
					catch( IOException e1 )
					{// Catch exception if any
						SoapUI.logError( e1 );
					}
				}

			}
		}

		public LaunchLoadUIButtonAction()
		{
			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/launchLoadUI.png" ) );
			putValue( Action.SHORT_DESCRIPTION, "Launch loadUI" );
		}

		public void actionPerformed( ActionEvent e )
		{
			Thread launchLoadUI = new Thread( new LoadUIRunner() );
			launchLoadUI.start();
		}
	}

	private class ExitButtonAction extends AbstractAction
	{
		public ExitButtonAction()
		{
			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/system-log-out.png" ) );
			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
		}

		public void actionPerformed( ActionEvent e )
		{
			saveOnExit = true;
			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
			frame.dispatchEvent( windowEvent );
		}
	}

	private class ShowPushPageAction extends AbstractAction
	{
		public ShowPushPageAction()
		{
			super( "Starter Page" );
			putValue( Action.SHORT_DESCRIPTION, "Shows the starter page" );
		}

		public void actionPerformed( ActionEvent e )
		{
			showPushPage();
		}
	}

	private class ToolbarForumSearchAction extends AbstractAction
	{
		public ToolbarForumSearchAction()
		{
			putValue( Action.SHORT_DESCRIPTION, "Searches the soapUI Support Forum" );
			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/find.png" ) );
		}

		public void actionPerformed( ActionEvent e )
		{
			doForumSearch( searchField.getText() );
		}
	}

	private class SearchForumAction extends AbstractAction
	{
		public SearchForumAction()
		{
			super( "Search Forum" );
			putValue( Action.SHORT_DESCRIPTION, "Searches the soapUI Support Forum" );
		}

		public void actionPerformed( ActionEvent e )
		{
			String text = UISupport.prompt( "Search Forum", "Searches the online Forum, leave empty to open", "" );
			if( text == null )
				return;

			doForumSearch( text );
		}
	}

	public static void showPushPage()
	{
		if( urlDesktopPanel == null || urlDesktopPanel.isClosed() )
		{
			try
			{
				urlDesktopPanel = new URLDesktopPanel( "soapUI Starter Page", "Info on soapUI", null );
			}
			catch( Throwable t )
			{
				t.printStackTrace();
				return;
			}
		}

		DesktopPanel dp = UISupport.showDesktopPanel( urlDesktopPanel );
		desktop.maximize( dp );

		urlDesktopPanel.navigate( PUSH_PAGE_URL, PUSH_PAGE_ERROR_URL, true );

	}

	private static class AboutAction extends AbstractAction
	{
        private static final String COPYRIGHT = "2004-2013 smartbear.com";
        private static final String SOAPUI_WEBSITE = "http://www.soapui.org";
        private static final String SMARTBEAR_WEBSITE = "http://www.smartbear.com";
        public static final String BUILDINFO_PROPERTIES = "/buildinfo.properties";

        public AboutAction()
		{
			super( "About soapUI" );
			putValue( Action.SHORT_DESCRIPTION, "Shows information on soapUI" );
		}

		public void actionPerformed( ActionEvent e )
		{
			URI splashURI = null;
			try
			{
				splashURI = UISupport.findSplash( SoapUI.SOAPUI_SPLASH ).toURI();
			}
			catch( URISyntaxException e1 )
			{
				SoapUI.logError( e1 );
			}

			Properties buildInfoProperties = new Properties();
            try
            {
                buildInfoProperties.load(SoapUI.class.getResourceAsStream(BUILDINFO_PROPERTIES));
            }
            catch( Exception exception )
            {
                SoapUI.logError (exception, "Could not read build info properties");
            }



			UISupport.showExtendedInfo(
					"About soapUI",
					null,
					"<html><body><p align=center> <font face=\"Verdana,Arial,Helvetica\"><strong><img src=\"" + splashURI
							+ "\"><br>soapUI " + SOAPUI_VERSION + "<br>"
                            + "Copyright (C) " + COPYRIGHT + "<br>"
							+ "<a href=\"" + SOAPUI_WEBSITE + "\">" + SOAPUI_WEBSITE + "</a> | "
							    + "<a href=\"" + SMARTBEAR_WEBSITE + "\">" + SMARTBEAR_WEBSITE + "</a><br>"
                            + "Build Date: " + Objects.firstNonNull(buildInfoProperties.getProperty( "build.date" ), "UNKNOWN BUILD DATE")
							+ "</strong></font></p></body></html>",

					new Dimension( 646, 480 ) );	//Splash screen width + 70px, height + 175px
		}
	}

	private class ExitWithoutSavingAction extends AbstractAction
	{
		public ExitWithoutSavingAction()
		{
			super( "Exit without saving" );
			putValue( Action.SHORT_DESCRIPTION, "Exits SoapUI without saving" );
			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "ctrl shift Q" ) );
		}

		public void actionPerformed( ActionEvent e )
		{
			saveOnExit = false;
			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
			frame.dispatchEvent( windowEvent );
		}
	}

	private class SavePreferencesAction extends AbstractAction
	{
		public SavePreferencesAction()
		{
			super( "Save Preferences" );
			putValue( Action.SHORT_DESCRIPTION, "Saves all global preferences" );
		}

		public void actionPerformed( ActionEvent e )
		{
			try
			{
				soapUICore.saveSettings();
			}
			catch( Exception e1 )
			{
				SoapUI.logError( e1, "There was an error when attempting to save your preferences" );
				UISupport.showErrorMessage( e1 );
			}
		}
	}

	public static TestMonitor getTestMonitor()
	{
		if( testMonitor == null )
			testMonitor = new TestMonitor();

		return testMonitor;
	}

	public static void setTestMonitor( TestMonitor monitor )
	{
		testMonitor = monitor;
	}

	public static Log4JMonitor getLogMonitor()
	{
		return logMonitor;
	}

	public static void setLogMonitor( Log4JMonitor monitor )
	{
		logMonitor = monitor;
	}

	// instance is null in Eclipse. /Lars
	// eclipse-version(s) should provide SoapUIDesktop implementation
	public static SoapUIDesktop getDesktop()
	{
		if( desktop == null )
			desktop = new NullDesktop();

		return desktop;
	}

	public static void setDesktop( SoapUIDesktop desktop )
	{
		SoapUI.desktop = desktop;
	}

	public static Navigator getNavigator()
	{
		return navigator;
	}

	public static SoapUIActionRegistry getActionRegistry()
	{
		if( soapUICore == null )
			soapUICore = new DefaultSoapUICore();

		return soapUICore.getActionRegistry();
	}

	public static void setNavigator( Navigator navigator )
	{
		SoapUI.navigator = navigator;
	}

	public static void setWorkspace( Workspace workspace )
	{
		SoapUI.workspace = workspace;
	}

	public static void setStandalone( boolean standalone )
	{
		SoapUI.isStandalone = standalone;
	}

	private static class NewWsdlProjectActionDelegate extends AbstractAction
	{
		public NewWsdlProjectActionDelegate()
		{
			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/project.gif" ) );
			putValue( Action.SHORT_DESCRIPTION, "Creates a new soapUI Project" );
		}

		public void actionPerformed( ActionEvent e )
		{
			SoapUI.getActionRegistry().getAction( NewWsdlProjectAction.SOAPUI_ACTION_ID ).perform( workspace, null );
		}
	}

	private static class ImportWsdlProjectActionDelegate extends AbstractAction
	{
		public ImportWsdlProjectActionDelegate()
		{
			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/import_project.gif" ) );
			putValue( Action.SHORT_DESCRIPTION, "Imports an existing soapUI Project into the current workspace" );
		}

		public void actionPerformed( ActionEvent e )
		{
			SoapUI.getActionRegistry().getAction( ImportWsdlProjectAction.SOAPUI_ACTION_ID ).perform( workspace, null );
		}
	}

	private static class SaveAllActionDelegate extends AbstractAction
	{
		public SaveAllActionDelegate()
		{
			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/disk_multiple.png" ) );
			putValue( Action.SHORT_DESCRIPTION, "Saves all projects in the current workspace" );
		}

		public void actionPerformed( ActionEvent e )
		{
			SoapUI.getActionRegistry().getAction( SaveAllProjectsAction.SOAPUI_ACTION_ID ).perform( workspace, null );
		}
	}

	private class PreferencesActionDelegate extends AbstractAction
	{
		public PreferencesActionDelegate()
		{
			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ) );
			putValue( Action.SHORT_DESCRIPTION, "Sets Global soapUI Preferences" );
		}

		public void actionPerformed( ActionEvent e )
		{
			SoapUIPreferencesAction.getInstance().actionPerformed( null );
		}
	}

	public static class ImportPreferencesAction extends AbstractAction
	{
		public static final String IMPORT_PREFERENCES_ACTION_NAME = "Import Preferences";

		public ImportPreferencesAction()
		{
			super( ImportPreferencesAction.IMPORT_PREFERENCES_ACTION_NAME );
			putValue( Action.SHORT_DESCRIPTION, "Imports soapUI Settings from another settings-file" );
		}

		public void actionPerformed( ActionEvent e )
		{
			try
			{
				// prompt for import
				File file = UISupport.getFileDialogs().open( null, ImportPreferencesAction.IMPORT_PREFERENCES_ACTION_NAME,
						".xml", "soapUI Settings XML (*.xml)", null );
				if( file != null )
					soapUICore.importSettings( file );
			}
			catch( Exception e1 )
			{
				UISupport.showErrorMessage( e1 );
			}
		}
	}

	public static SoapUIListenerRegistry getListenerRegistry()
	{
		if( soapUICore == null )
			soapUICore = DefaultSoapUICore.createDefault();

		return soapUICore.getListenerRegistry();
	}

	public static SoapUIFactoryRegistry getFactoryRegistry()
	{
		if( soapUICore == null )
			soapUICore = DefaultSoapUICore.createDefault();

		return soapUICore.getFactoryRegistry();
	}

	public static Settings getSettings()
	{
		if( soapUICore == null )
			soapUICore = DefaultSoapUICore.createDefault();

		return soapUICore.getSettings();
	}

	public static void importPreferences( File file ) throws Exception
	{
		if( soapUICore != null )
			soapUICore.importSettings( file );
	}

	public static MockEngine getMockEngine()
	{
		if( soapUICore == null )
			soapUICore = DefaultSoapUICore.createDefault();

		return soapUICore.getMockEngine();
	}

	public static String saveSettings() throws Exception
	{
		return soapUICore == null ? null : soapUICore.saveSettings();
	}

	public static void initDefaultCore()
	{
		if( soapUICore == null )
			soapUICore = DefaultSoapUICore.createDefault();
	}

	public class MaximizeDesktopAction extends AbstractAction
	{
		private JLogList lastLog;
		private int lastMainDividerLocation;
		private final InspectorLog4JMonitor log4JMonitor;
		private int lastLogDividerLocation;

		public MaximizeDesktopAction( InspectorLog4JMonitor log4JMonitor )
		{
			super( "Maximize Desktop" );
			this.log4JMonitor = log4JMonitor;

			putValue( SHORT_DESCRIPTION, "Hides/Shows the Navigator and Log tabs" );
			putValue( ACCELERATOR_KEY, UISupport.getKeyStroke( "menu M" ) );
		}

		public void actionPerformed( ActionEvent e )
		{
			if( mainInspector.getCurrentInspector() != null || logMonitor.getCurrentLog() != null )
			{
				lastMainDividerLocation = mainInspector.getDividerLocation();
				mainInspector.deactivate();

				lastLog = logMonitor.getCurrentLog();
				lastLogDividerLocation = log4JMonitor.getDividerLocation();

				log4JMonitor.deactivate();
			}
			else
			{
				mainInspector.setCurrentInspector( "Navigator" );
				mainInspector.setDividerLocation( lastMainDividerLocation == 0 ? 250 : lastMainDividerLocation );

				log4JMonitor.setCurrentLog( lastLog );
				log4JMonitor.setDividerLocation( lastLogDividerLocation == 0 ? 500 : lastLogDividerLocation );
			}
		}
	}

	public static void initAutoSaveTimer()
	{
		Settings settings = SoapUI.getSettings();
		long interval = settings.getLong( UISettings.AUTO_SAVE_INTERVAL, 0 );

		if( autoSaveTimerTask != null )
		{
			if( interval == 0 )
				SoapUI.log( "Cancelling AutoSave Timer" );

			autoSaveTimerTask.cancel();
			autoSaveTimerTask = null;
		}

		if( interval > 0 )
		{
			autoSaveTimerTask = new AutoSaveTimerTask();

			SoapUI.log( "Scheduling autosave every " + interval + " minutes" );

			soapUITimer.schedule( autoSaveTimerTask, interval * 1000 * 60, interval * 1000 * 60 );
		}
	}

	private static class AutoSaveTimerTask extends TimerTask
	{
		@Override
		public void run()
		{
			SwingUtilities.invokeLater( new Runnable()
			{
				public void run()
				{
					SoapUI.log( "Autosaving Workspace" );
					WorkspaceImpl wrkspc = ( WorkspaceImpl )SoapUI.getWorkspace();
					if( wrkspc != null )
					{
						wrkspc.save( false, true );
					}
				}
			} );
		}
	}

	public static void initGCTimer()
	{
		Settings settings = SoapUI.getSettings();
		long interval = settings.getLong( UISettings.GC_INTERVAL, 60 );

		if( gcTimerTask != null )
		{
			if( interval == 0 )
				SoapUI.log( "Cancelling GC Timer" );

			gcTimerTask.cancel();
			gcTimerTask = null;
		}

		if( interval > 0 )
		{
			gcTimerTask = new GCTimerTask();
			SoapUI.log( "Scheduling garbage collection every " + interval + " seconds" );
			soapUITimer.schedule( gcTimerTask, interval * 1000, interval * 1000 );
		}
	}

	private static class GCTimerTask extends TimerTask
	{
		@Override
		public void run()
		{
			System.gc();
		}
	}

	public static JXToolBar getToolBar()
	{
		return mainToolbar;
	}

	public static void setLaunchedTestRunner( Boolean launchedTestRunner )
	{
		SoapUI.launchedTestRunner = launchedTestRunner;
	}

	public static void setProxyEnabled( boolean proxyEnabled )
	{
		if( applyProxyButton != null )
		{
			applyProxyButton.setSelected( proxyEnabled );
		}

		ProxyUtils.setProxyEnabled( proxyEnabled );
	}

	public static Timer getSoapUITimer()
	{
		return soapUITimer;
	}

	public static void setCmdLineRunner( CmdLineRunner abstractSoapUIRunner )
	{
		SoapUI.soapUIRunner = abstractSoapUIRunner;
	}

	public static CmdLineRunner getCmdLineRunner()
	{
		return soapUIRunner;
	}

	public static boolean isAutoUpdateVersion()
	{
		return getSettings().getBoolean( VersionUpdateSettings.AUTO_CHECK_VERSION_UPDATE );
	}

}