View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 eviware.com
    3    *
    4    *  soapUI is free software; you can redistribute it and/or modify it under the
    5    *  terms of version 2.1 of the GNU Lesser General Public License as published by
    6    *  the Free Software Foundation.
    7    *
    8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
    9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    10   *  See the GNU Lesser General Public License for more details at gnu.org.
    11   */
    12
    13  package com.eviware.soapui;
    14
    15  import java.awt.BorderLayout;
    16  import java.awt.Color;
    17  import java.awt.Component;
    18  import java.awt.Dimension;
    19  import java.awt.Insets;
    20  import java.awt.Toolkit;
    21  import java.awt.event.ActionEvent;
    22  import java.awt.event.KeyEvent;
    23  import java.awt.event.MouseAdapter;
    24  import java.awt.event.MouseEvent;
    25  import java.awt.event.WindowAdapter;
    26  import java.awt.event.WindowEvent;
    27  import java.io.File;
    28  import java.io.IOException;
    29  import java.net.URI;
    30  import java.net.URISyntaxException;
    31  import java.net.URL;
    32  import java.util.ArrayList;
    33  import java.util.Collection;
    34  import java.util.Collections;
    35  import java.util.List;
    36  import java.util.Properties;
    37
    38  import javax.swing.AbstractAction;
    39  import javax.swing.Action;
    40  import javax.swing.BorderFactory;
    41  import javax.swing.ImageIcon;
    42  import javax.swing.JComponent;
    43  import javax.swing.JFrame;
    44  import javax.swing.JLabel;
    45  import javax.swing.JMenu;
    46  import javax.swing.JMenuBar;
    47  import javax.swing.JOptionPane;
    48  import javax.swing.JPanel;
    49  import javax.swing.JScrollPane;
    50  import javax.swing.JSplitPane;
    51  import javax.swing.JTabbedPane;
    52  import javax.swing.JWindow;
    53  import javax.swing.SwingUtilities;
    54  import javax.swing.ToolTipManager;
    55  import javax.swing.UIManager;
    56  import javax.swing.plaf.ColorUIResource;
    57  import javax.xml.namespace.QName;
    58  import javax.xml.parsers.FactoryConfigurationError;
    59
    60  import org.apache.log4j.Level;
    61  import org.apache.log4j.Logger;
    62  import org.apache.log4j.xml.DOMConfigurator;
    63
    64  import com.eviware.soapui.actions.SoapUIPreferencesAction;
    65  import com.eviware.soapui.config.SoapuiSettingsDocumentConfig;
    66  import com.eviware.soapui.impl.settings.XmlBeansSettingsImpl;
    67  import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis1.Axis1XWSDL2JavaAction;
    68  import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis2.Axis2WSDL2CodeAction;
    69  import com.eviware.soapui.impl.wsdl.actions.iface.tools.dotnet.DotNetWsdlAction;
    70  import com.eviware.soapui.impl.wsdl.actions.iface.tools.gsoap.GSoapAction;
    71  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jaxb.JaxbXjcAction;
    72  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.JBossWSConsumeAction;
    73  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.WSToolsWsdl2JavaAction;
    74  import com.eviware.soapui.impl.wsdl.actions.iface.tools.oracle.OracleWsaGenProxyAction;
    75  import com.eviware.soapui.impl.wsdl.actions.iface.tools.support.SwingToolHost;
    76  import com.eviware.soapui.impl.wsdl.actions.iface.tools.tcpmon.TcpMonAction;
    77  import com.eviware.soapui.impl.wsdl.actions.iface.tools.wscompile.WSCompileAction;
    78  import com.eviware.soapui.impl.wsdl.actions.iface.tools.wsimport.WSImportAction;
    79  import com.eviware.soapui.impl.wsdl.actions.iface.tools.xfire.XFireAction;
    80  import com.eviware.soapui.impl.wsdl.actions.iface.tools.xmlbeans.XmlBeans2Action;
    81  import com.eviware.soapui.impl.wsdl.actions.support.OpenUrlAction;
    82  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
    83  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
    84  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
    85  import com.eviware.soapui.model.ModelItem;
    86  import com.eviware.soapui.model.PanelBuilder;
    87  import com.eviware.soapui.model.settings.Settings;
    88  import com.eviware.soapui.model.settings.SettingsListener;
    89  import com.eviware.soapui.model.tree.SoapUITreeNode;
    90  import com.eviware.soapui.model.util.PanelBuilderRegistry;
    91  import com.eviware.soapui.model.workspace.Workspace;
    92  import com.eviware.soapui.model.workspace.WorkspaceFactory;
    93  import com.eviware.soapui.monitor.MockEngine;
    94  import com.eviware.soapui.monitor.TestMonitor;
    95  import com.eviware.soapui.settings.HttpSettings;
    96  import com.eviware.soapui.settings.UISettings;
    97  import com.eviware.soapui.settings.WsdlSettings;
    98  import com.eviware.soapui.support.ClasspathHacker;
    99  import com.eviware.soapui.support.SoapUIException;
    100 import com.eviware.soapui.support.UISupport;
    101 import com.eviware.soapui.support.action.SoapUIActionRegistry;
    102 import com.eviware.soapui.support.action.swing.ActionList;
    103 import com.eviware.soapui.support.action.swing.ActionListBuilder;
    104 import com.eviware.soapui.support.action.swing.ActionSupport;
    105 import com.eviware.soapui.support.action.swing.SwingActionDelegate;
    106 import com.eviware.soapui.support.log.Log4JMonitor;
    107 import com.eviware.soapui.support.log.LogDisablingTestMonitorListener;
    108 import com.eviware.soapui.support.types.StringList;
    109 import com.eviware.soapui.ui.JDesktopPanelsList;
    110 import com.eviware.soapui.ui.Navigator;
    111 import com.eviware.soapui.ui.NavigatorListener;
    112 import com.eviware.soapui.ui.desktop.DesktopPanel;
    113 import com.eviware.soapui.ui.desktop.DesktopRegistry;
    114 import com.eviware.soapui.ui.desktop.SoapUIDesktop;
    115 import com.eviware.soapui.ui.desktop.standalone.StandaloneDesktop;
    116 import com.eviware.soapui.ui.desktop.standalone.StandaloneDesktopFactory;
    117 import com.eviware.soapui.ui.support.DesktopListenerAdapter;
    118 import com.eviware.x.form.XFormFactory;
    119 import com.eviware.x.impl.swing.SwingFileDialogs;
    120 import com.eviware.x.impl.swing.SwingFormFactory;
    121 import com.jgoodies.looks.HeaderStyle;
    122 import com.jgoodies.looks.Options;
    123 import com.jgoodies.looks.plastic.PlasticXPLookAndFeel;
    124 import com.jgoodies.looks.plastic.theme.SkyBluer;
    125
    126 /***
    127  * Main SoapUI entry point.
    128  *
    129  * @author Ole.Matzura
    130  *
    131  * For version 0.6
    132  * @todo improve error assertion reporting +
    133  * @todo find/search/replace +
    134  * @todo undo +
    135  * @todo recreate request and keep values +
    136  * @todo dont create optional elements +
    137  * @todo option to create requests when importing +
    138  * @todo show soapaction +
    139  * @todo save response +
    140  * @todo color-coding +
    141  * @todo rapportera fel vid null-svar +
    142  * @todo fixa bugg vid update interface +
    143  * @todo xmlbeans2 +
    144  * @todo httpclient rc3 +
    145  * @todo refactor request panels +
    146  * @todo refactor project/interface/testsuite listeners +
    147  * @todo create properties table +
    148  *
    149  * For version 0.7
    150  * @todo workspace in home folder +
    151  * @todo allow renaming of operation names in tree +
    152  * @todo add functionality for copying values from test response to following
    153  *       test request +
    154  * @todo fix relative xsd imports when loading from file system +
    155  * @todo fix cancelling of request when closing request window -> introduce
    156  *       DesktopPanel interface +
    157  * @todo refactor panel creation / listener handling/release +
    158  * @todo fix update of testcase window when adding test steps +
    159  * @todo add delete-line action in xml-editor (Ctrl-D) +
    160  * @todo add submit action to xml request editor (Ctrl Enter) +
    161  * @todo add mousewheel support to xml editor +
    162  * @todo add mousewheel + C support to xml editor (move cursor) +
    163  * @todo fix revalidation problems +
    164  * @todo add validation to xmleditors +
    165  * @todo check localisation of schema errors +
    166  * @todo add possibility to reload schema (neccessary?) +
    167  * @todo fix cloning of assertions when cloning test steps +
    168  * @todo ask for creation of optional elements when (re)creating new request +
    169  * @todo add action to add existing namespaces to xpath in xpathassertion +
    170  *
    171  * For version 0.8
    172  * @todo fix default values when creating requests +
    173  * @todo bug-fixes - creation of namespace declarations creates multiple with
    174  *       same name + - check defintion update + - deletion of endpoint always
    175  *       deletes first + - deleted assertions result in error during save/exit? + -
    176  *       disable submit when missing endpoint + - clone request null-pointer + -
    177  *       fix value transfer element <> attribute + - fix cancelling of test
    178  *       requests +
    179  * @todo create assertion events / listeners +
    180  * @todo ask to add testcase if missing +
    181  * @todo add alt-enter to response area +
    182  * @todo allow url config of SchemaCompliance assertion +
    183  * @todo add accelerators for common actions +
    184  * @todo fix positions of dialogs +
    185  * @todo add possibility to specify testsuite/testcase in maven-plugin +
    186  * @todo refactoring: replaced SoapUIAction with standard swing Action +
    187  * @todo refactoring: checked all JOptionPanes for correct title, etc. +
    188  * @todo add filename-filters to filechoosers +
    189  * @todo add shortcut for cancel request to editor +
    190  *
    191  * For version 0.9
    192  * @todo initial class/code comments +
    193  * @todo bug-fixes - fix cancelling of test runs + - fix removal of request
    194  *       test-steps when associated operations / interfaces are removed + -
    195  *       update of request-step status in testcase panel + - focus on find-field
    196  *       in find/replace dialog + - fix filters to not remove directories.. + -
    197  *       change wsdl file filter to *.wsdl + - disable declare in transfer panel
    198  *       when no transfer is selected + - declare in transfer panel declares
    199  *       target from target response (should be request) + - ask to cancel when
    200  *       closing running testcase + - fix pretty-printing of large xml-documents + -
    201  *       fix find and replace + - fix node insert error on multiple clone
    202  *       teststep + - fix log-messages from canceled requests + - disable
    203  *       replace-related options in find/replace if editor is not editable +
    204  * @todo add possibility to move teststeps within testcase +
    205  * @todo improve/disable disabling of request-editor +
    206  * @todo add addAssertion button to testrequest panel +
    207  * @todo add copy/pase actions to editor popup +
    208  * @todo model-items tests
    209  * @todo improve wsdl/xsd viewer +
    210  * @todo improve line-number reporting in validations +
    211  * @todo added shift-tab to move focus between request/response editors +
    212  * @todo refactorings - SoapUIException + - UIFacade for JOptionPane +
    213  *       (partially)
    214  *
    215  * For version 1.0b
    216  * @todo initial user documentation / samples +
    217  * @todo bug-fixes +
    218  * @todo more tests / testing!
    219  * @todo beta release +
    220  *
    221  * For version 1.0
    222  * @todo official release
    223  *
    224  * For version 1.5
    225  * @todo finish LoadTest panels - fix UI + - color legend + - reset action + -
    226  *       interactive thread-count change + - error-log + - see responses + -
    227  *       assertions + - command-line/maven-plugin + - export results +
    228  * @todo loadtest fixes - resizing/scaling of graphs + - autoreset on restart +
    229  * @todo fix disabling of relevant actions during test-runs + - Add to testcase,
    230  *       delete testcase, etc +
    231  * @todo allow TransferValues between any requests/responses +
    232  * @todo fix "global values" in testcases + - properties +
    233  * @todo improve endpoint editing + - add "edit.." to combobox +
    234  * @todo remove xpath/xquery tester.. +
    235  * @todo improve testcase properties dialog +
    236  * @todo fix icons for all tree nodes +
    237  * @todo fix updating of desktop panel titles +
    238  * @todo global settings; + - proxy + - close connections + - user-agent header + -
    239  *       preemptive authentication + - editor font + - socket timeout + - ?
    240  * @todo add loop-functionality for testcases +
    241  * @todo support one-way operations +
    242  * @todo fix wsdlcontext initialization in loadtests +
    243  * @todo create testrun summary in commandline
    244  * @todo create loadtest summary in commandline
    245  * @todo add maven.soapui.test.host commandline property +
    246  * @todo add test-suite runner panel +
    247  * @todo option to abort testcase on error +
    248  * @todo ensure unique test-step names +
    249  * @todo grooy-teststep +
    250  * @todo onewayop tree icon +
    251  * @todo fix desktoppanels list +
    252  *
    253  * For version 1.6
    254  * @todo finish SOAP 1.2 request generation +
    255  * @todo finish gsoap integration +
    256  * @todo bugfixes!
    257  * @todo swa-attachments support +
    258  *
    259  * Improvements
    260  * @todo make modifications of response content "alive"
    261  * @todo animated tree icons for testcase/loadtest runs
    262  * @todo add run-testcase action in teststep/testcase editors
    263  * @todo implement testsuite/testcase generation
    264  * @todo refactor XmlObject configurables
    265  * @todo workspace management
    266  * @todo add reload-project!?
    267  * @todo option to reload schemas on run testcase
    268  * @todo option to select visible steps in loadtest statistics
    269  * @todo generate testcase/testsuite actions
    270  * @todo form-based input
    271  */
    272
    273 public class SoapUI
    274 {
    275 	public static final String CURRENT_SOAPUI_WORKSPACE = SoapUI.class.getName() + "@workspace";
    276 	public final static Logger log = Logger.getLogger( SoapUI.class );
    277 	public final static String SOAPUI_VERSION = "1.7.5";
    278 	public static final String DEFAULT_WORKSPACE_FILE = "default-soapui-workspace.xml";
    279 	private final static String DEFAULT_SETTINGS_FILE = "soapui-settings.xml";
    280 	public static final String SOAPUI_SPLASH_GIF = "soapui-splash.gif";
    281
    282 	// ------------------------------ FIELDS ------------------------------
    283
    284 	private static SoapUI instance;
    285 	private static SoapuiSettingsDocumentConfig settingsDocument;
    286 	private static List<Object> logCache = new ArrayList<Object>();
    287 	private static Settings settings;
    288
    289 	private static JFrame frame;
    290
    291 	private Navigator navigator;
    292 	private SoapUIDesktop desktop;
    293 	private static TestMonitor testMonitor;
    294 	static Workspace workspace;
    295 	private JDesktopPanelsList desktopPanelsList;
    296 	private Log4JMonitor logMonitor;
    297
    298 	private JMenu desktopMenu;
    299 	private JMenu helpMenu;
    300 	private JMenu fileMenu;
    301 	private JMenuBar menuBar;
    302
    303 	public static boolean checkedGroovyLogMonitor;
    304
    305 	private JPanel overviewPanel;
    306 	private JMenu toolsMenu;
    307 	private boolean saveOnExit = true;
    308 	private static MockEngine mockEngine;
    309 	private static boolean loadedExtLibs;
    310 	private static boolean isStandalone;
    311 	private JSplitPane contentSplit;
    312 	private InternalDesktopListener internalDesktopListener = new InternalDesktopListener();
    313 	private static SoapUIActionRegistry actionRegistry;
    314 	private static Logger errorLog = Logger.getLogger( "soapui.errorlog" );
    315 	private static boolean logIsInitialized;
    316
    317 	// --------------------------- CONSTRUCTORS ---------------------------
    318
    319 	public SoapUI()
    320 	{
    321 		instance = this;
    322 		testMonitor = new TestMonitor();
    323 		actionRegistry = new SoapUIActionRegistry( SoapUI.class.getResourceAsStream( "/soapui-actions.xml" ));
    324 	}
    325
    326 	private void buildUI()
    327 	{
    328 		frame.addWindowListener( new MainFrameWindowListener() );
    329 		UISupport.setMainFrame( frame );
    330
    331 		navigator = new Navigator( workspace );
    332 		navigator.addNavigatorListener( new InternalNavigatorListener() );
    333
    334 		desktopPanelsList = new JDesktopPanelsList( desktop );
    335
    336 		JSplitPane splitPane = UISupport
    337 					.createHorizontalSplit( buildMainPanel(), buildContentPanel() );
    338
    339 		frame.setJMenuBar( buildMainMenu() );
    340 		frame.getContentPane().add( splitPane, BorderLayout.CENTER );
    341 		frame.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
    342 		frame.setSize( 1000, 750 );
    343
    344 		splitPane.setDividerLocation( 250 );
    345
    346 		navigator.selectModelItem( workspace );
    347
    348 		desktop.addDesktopListener( internalDesktopListener );
    349
    350 		ToolTipManager.sharedInstance().setInitialDelay( 200 );
    351 	}
    352
    353 	private JMenuBar buildMainMenu()
    354 	{
    355 		menuBar = new JMenuBar();
    356 		menuBar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
    357
    358 		menuBar.add( buildFileMenu() );
    359 		menuBar.add( buildToolsMenu() );
    360 		menuBar.add( buildDesktopMenu() );
    361 		menuBar.add( buildHelpMenu() );
    362
    363 		return menuBar;
    364 	}
    365
    366 	public static Workspace getWorkspace()
    367 	{
    368 		return workspace;
    369 	}
    370
    371 	private JMenu buildDesktopMenu()
    372 	{
    373 		desktopMenu = new JMenu( "Desktop" );
    374 		desktopMenu.setMnemonic( KeyEvent.VK_D );
    375
    376 		ActionSupport.addActions( desktop.getActions(), desktopMenu );
    377
    378 		return desktopMenu;
    379 	}
    380
    381 	private JMenu buildHelpMenu()
    382 	{
    383 		helpMenu = new JMenu( "Help" );
    384 		helpMenu.setMnemonic( KeyEvent.VK_H );
    385
    386 		helpMenu.add( new ShowOnlineHelpAction( "User Guide", HelpUrls.USERGUIDE_HELP_URL ) );
    387 		helpMenu.add( new ShowOnlineHelpAction( "Getting Started",
    388 					HelpUrls.GETTINGSTARTED_HELP_URL ) );
    389 		helpMenu.addSeparator();
    390
    391 		helpMenu.add( new ShowSystemPropertiesAction());
    392
    393 		helpMenu.addSeparator();
    394 		helpMenu.add( new OpenUrlAction( "soapui.org", "http://www.soapui.org" ) );
    395 		helpMenu.add( new AboutAction() );
    396 		return helpMenu;
    397 	}
    398
    399 	@SuppressWarnings("unchecked")
    400 	private JMenu buildToolsMenu()
    401 	{
    402 		toolsMenu = new JMenu( "Tools" );
    403 		toolsMenu.setMnemonic( KeyEvent.VK_T );
    404
    405 		toolsMenu.add( SwingActionDelegate.createDelegate( WSToolsWsdl2JavaAction.SOAPUI_ACTION_ID ));
    406 		toolsMenu.add( SwingActionDelegate.createDelegate( JBossWSConsumeAction.SOAPUI_ACTION_ID ));
    407 		toolsMenu.addSeparator();
    408 		toolsMenu.add( SwingActionDelegate.createDelegate( WSCompileAction.SOAPUI_ACTION_ID ));
    409 		toolsMenu.add( SwingActionDelegate.createDelegate( WSImportAction.SOAPUI_ACTION_ID ));
    410 		toolsMenu.addSeparator();
    411 		toolsMenu.add( SwingActionDelegate.createDelegate( Axis1XWSDL2JavaAction.SOAPUI_ACTION_ID ));
    412 		toolsMenu.add( SwingActionDelegate.createDelegate( Axis2WSDL2CodeAction.SOAPUI_ACTION_ID ));
    413 		toolsMenu.add( SwingActionDelegate.createDelegate( XFireAction.SOAPUI_ACTION_ID ));
    414 		toolsMenu.add( SwingActionDelegate.createDelegate( OracleWsaGenProxyAction.SOAPUI_ACTION_ID ));
    415 		toolsMenu.addSeparator();
    416 		toolsMenu.add( SwingActionDelegate.createDelegate( XmlBeans2Action.SOAPUI_ACTION_ID ));
    417 		toolsMenu.add( SwingActionDelegate.createDelegate( JaxbXjcAction.SOAPUI_ACTION_ID ));
    418 		toolsMenu.addSeparator();
    419 		toolsMenu.add( SwingActionDelegate.createDelegate( DotNetWsdlAction.SOAPUI_ACTION_ID ));
    420 		toolsMenu.add( SwingActionDelegate.createDelegate( GSoapAction.SOAPUI_ACTION_ID ));
    421 		toolsMenu.addSeparator();
    422 		toolsMenu.add( SwingActionDelegate.createDelegate( TcpMonAction.SOAPUI_ACTION_ID ));
    423 		// toolsMenu.addSeparator();
    424 		// toolsMenu.add( new XQueryXPathTesterAction());
    425
    426 		return toolsMenu;
    427 	}
    428
    429 	private JMenu buildFileMenu()
    430 	{
    431 		fileMenu = new JMenu( "File" );
    432 		fileMenu.setMnemonic( KeyEvent.VK_F );
    433
    434 		ActionList actions = ActionListBuilder.buildActions( workspace );
    435 		actions.removeAction( actions.getActionCount()-1 );
    436
    437 		ActionSupport.addActions( actions, fileMenu );
    438
    439 		fileMenu.add( SoapUIPreferencesAction.getInstance() );
    440 		fileMenu.add( new SavePreferencesAction() );
    441 		fileMenu.add( new ImportPreferencesAction() );
    442
    443 		fileMenu.addSeparator();
    444 		fileMenu.add( new ExitAction() );
    445 		fileMenu.add( new ExitWithoutSavingAction() );
    446 		fileMenu.addSeparator();
    447 		fileMenu.add( new ShowOnlineHelpAction( HelpUrls.OVERVIEW_HELP_URL ));
    448
    449 		return fileMenu;
    450 	}
    451
    452 	public JFrame getFrame()
    453 	{
    454 		return frame;
    455 	}
    456
    457 	private JComponent buildMainPanel()
    458 	{
    459 		JSplitPane splitPane = UISupport.createVerticalSplit();
    460
    461 		splitPane.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
    462
    463 		splitPane.setTopComponent( navigator );
    464 		splitPane.setBottomComponent( buildOverviewPanel() );
    465 		splitPane.setDividerLocation( 500 );
    466 		splitPane.setResizeWeight( 0.6 );
    467 		return splitPane;
    468 	}
    469
    470 	private Component buildOverviewPanel()
    471 	{
    472 		JTabbedPane detailTabs = new JTabbedPane( JTabbedPane.BOTTOM );
    473
    474 		overviewPanel = new JPanel( new BorderLayout() );
    475 		detailTabs.addTab( "Details", overviewPanel );
    476 		detailTabs.addTab( "Windows", new JScrollPane( desktopPanelsList ) );
    477
    478 		return UISupport.createTabPanel( detailTabs, true );
    479 	}
    480
    481 	private void setOverviewPanel( Component panel )
    482 	{
    483 		if( overviewPanel.getComponentCount() == 0 && panel == null )
    484 			return;
    485
    486 		overviewPanel.removeAll();
    487 		if( panel != null )
    488 			overviewPanel.add( panel, BorderLayout.CENTER );
    489 		overviewPanel.revalidate();
    490 		overviewPanel.repaint();
    491 	}
    492
    493 	private Component buildContentPanel()
    494 	{
    495 		contentSplit = UISupport.createVerticalSplit();
    496 		contentSplit.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
    497
    498 		contentSplit.setTopComponent( desktop.getDesktopComponent() );
    499 		contentSplit.setBottomComponent( buildLogPanel( true, "soapUI log" ) );
    500 		contentSplit.setDividerLocation( 550 );
    501 		contentSplit.setResizeWeight( 1 );
    502 		return contentSplit;
    503 	}
    504
    505 	public Component buildLogPanel( boolean hasDefault, String defaultName )
    506 	{
    507 		logMonitor = new Log4JMonitor();
    508 		logMonitor.addLogArea( defaultName, "com.eviware.soapui", hasDefault ).setLevel( Level.DEBUG );
    509 		logMonitor.addLogArea( "http log", "httpclient.wire", false ).setLevel( Level.DEBUG );
    510 		logMonitor.addLogArea( "jetty log", "jetty", false ).setLevel( Level.INFO );
    511 		logMonitor.addLogArea( "error log", "soapui.errorlog", false ).setLevel( Level.DEBUG );
    512
    513 		for( Object message : logCache )
    514 		{
    515 			logMonitor.logEvent( message );
    516 		}
    517
    518 		return UISupport.createTabPanel( logMonitor, true );
    519 	}
    520
    521 	// -------------------------- OTHER METHODS --------------------------
    522
    523 	public static synchronized void log( final Object msg )
    524 	{
    525 		if( instance == null || instance.logMonitor == null )
    526 		{
    527 			logCache.add( msg );
    528 			return;
    529 		}
    530
    531 		if( SwingUtilities.isEventDispatchThread() )
    532 		{
    533 			instance.logMonitor.logEvent( msg );
    534 		}
    535 		else
    536 		{
    537 			SwingUtilities.invokeLater( new Runnable()
    538 			{
    539 				public void run()
    540 				{
    541 					instance.logMonitor.logEvent( msg );
    542 				}
    543 			} );
    544 		}
    545 	}
    546
    547 	// -------------------------- INNER CLASSES --------------------------
    548
    549 	private final class InternalDesktopListener extends DesktopListenerAdapter
    550 	{
    551 		public void desktopPanelSelected( DesktopPanel desktopPanel )
    552 		{
    553 			ModelItem modelItem = desktopPanel.getModelItem();
    554 			if( modelItem != null )
    555 				navigator.selectModelItem( modelItem );
    556 		}
    557 	}
    558
    559 	private final class MainFrameWindowListener extends WindowAdapter
    560 	{
    561 		public void windowClosing( WindowEvent e )
    562 		{
    563 			if( saveOnExit )
    564 			{
    565 				String question = "Exit SoapUI?";
    566
    567 				if( getTestMonitor().hasRunningTests() )
    568 					question += "\n(Projects with running tests will not be saved)";
    569
    570 				if( !UISupport.confirm( question, "Question" ) )
    571 					return;
    572
    573 				try
    574 				{
    575 					saveSettings();
    576 					workspace.onClose();
    577 				}
    578 				catch( IOException e1 )
    579 				{
    580 					SoapUI.logError( e1 );
    581 				}
    582 			}
    583 			else
    584 			{
    585 				if( !UISupport.confirm( "Exit SoapUI without saving?", "Question" ) )
    586 				{
    587 					saveOnExit = true;
    588 					return;
    589 				}
    590 			}
    591
    592 			frame.dispose();
    593 		}
    594
    595 		public void windowClosed( WindowEvent e )
    596 		{
    597 			System.out.println( "exiting.." );
    598 			System.exit( 0 );
    599 		}
    600 	}
    601
    602 	/***
    603 	 * Adapted theme for soapUI Look and Feel
    604 	 *
    605 	 * @author ole.matzura
    606 	 */
    607
    608 	public static class SoapUITheme extends SkyBluer
    609 	{
    610 		public static final Color BACKGROUND_COLOR = new Color( 240, 240, 240 );
    611
    612 		public ColorUIResource getControl()
    613 		{
    614 			return new ColorUIResource( BACKGROUND_COLOR );
    615 		}
    616
    617 		public ColorUIResource getMenuBackground()
    618 		{
    619 			return getControl();
    620 		}
    621
    622 		public ColorUIResource getMenuItemBackground()
    623 		{
    624 			return new ColorUIResource( new Color( 248, 248, 248 ) );
    625 		}
    626 	}
    627
    628 	// --------------------------- main() method ---------------------------
    629
    630 	public static void main( String[] args ) throws Exception
    631 	{
    632 		String title = "soapUI " + SOAPUI_VERSION;
    633 		String splashImage = "soapui-splash.gif";
    634
    635 		startSoapUI( args, title, findSplash( splashImage ));
    636 	}
    637
    638 	public static URL findSplash( String filename )
    639 	{
    640 		File file = new File( filename );
    641 		URL url = null;
    642
    643 		try
    644 		{
    645 			if( !file.exists() )
    646 				url = SoapUI.class.getResource( "/" + filename );
    647 			else
    648 				url = file.toURL();
    649 		}
    650 		catch( Exception e1 )
    651 		{
    652 		}
    653
    654 		try
    655 		{
    656 			if( url == null )
    657 				url = new URL( "http://www.soapui.org/images/" + filename );
    658 		}
    659 		catch( Exception e2 )
    660 		{
    661 			SoapUI.logError( e2 );
    662 		}
    663
    664 		return url;
    665 	}
    666
    667 	public static SoapUI startSoapUI( String[] args, String title, URL splashImage ) throws FactoryConfigurationError, SoapUIException
    668 	{
    669 		isStandalone = true;
    670
    671 		// force loading of SoapVersion
    672 		SoapVersion.Soap11.equals( SoapVersion.Soap12 );
    673
    674 		initSoapUILog();
    675
    676 		frame = new JFrame( title );
    677 		new SoapUISplash( splashImage );
    678
    679 		initSoapUILookAndFeel();
    680 		prepareSwingUI();
    681 		loadExtLibs();
    682
    683 		DesktopRegistry.getInstance().addDesktop( "Default", new StandaloneDesktopFactory() );
    684
    685 		// Run with the currently installed license.
    686 		SoapUI soapUI = new SoapUI();
    687
    688 		Workspace workspace = null;
    689
    690 		if( args.length > 0 )
    691 		{
    692 			workspace = WorkspaceFactory.getInstance().openWorkspace( args );
    693 			getSettings().setString( CURRENT_SOAPUI_WORKSPACE, args[0] );
    694 		}
    695 		else
    696 		{
    697 			String wsfile = getSettings().getString( CURRENT_SOAPUI_WORKSPACE, System.getProperty( "user.home" ) + File.separatorChar
    698 						+ DEFAULT_WORKSPACE_FILE );
    699 			workspace = WorkspaceFactory.getInstance().openWorkspace( new String[] { wsfile } );
    700 		}
    701
    702 		soapUI.show( workspace );
    703 		return soapUI;
    704 	}
    705
    706 	public static boolean isStandalone()
    707 	{
    708 		return isStandalone;
    709 	}
    710
    711 	public static void loadExtLibs()
    712 	{
    713 		if( loadedExtLibs )
    714 			return;
    715
    716 		try
    717 		{
    718 			File dir = new File( "ext" );
    719
    720 			if( dir.exists() && dir.isDirectory() )
    721 			{
    722 				File[] files = dir.listFiles();
    723 				for( File file : files )
    724 				{
    725 					if( file.getName().toLowerCase().endsWith( ".jar" ))
    726 					{
    727 						ClasspathHacker.addFile( file );
    728 					}
    729 				}
    730 			}
    731 			else
    732 			{
    733 				log.info( "Missing folder [" + dir.getAbsolutePath() + "] for external libraries" );
    734 			}
    735
    736 			loadedExtLibs = true;
    737 		}
    738 		catch( IOException e )
    739 		{
    740 			SoapUI.logError( e );
    741 		}
    742 	}
    743
    744 	public static void prepareSwingUI()
    745 	{
    746 		UISupport.setToolHost( new SwingToolHost() );
    747       XFormFactory.Factory.instance = new SwingFormFactory();
    748 	}
    749
    750 	public static void initSoapUILookAndFeel()
    751 	{
    752 		try
    753 		{
    754 			if( getSettings().getBoolean( UISettings.NATIVE_LAF ))
    755 			{
    756 				javax.swing.UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    757 			}
    758 			else
    759 			{
    760 				SoapUITheme theme = new SoapUITheme();
    761
    762 				PlasticXPLookAndFeel.setCurrentTheme( theme );
    763 				PlasticXPLookAndFeel.setTabStyle( "Metal" );
    764
    765 				UIManager.setLookAndFeel( new PlasticXPLookAndFeel() );
    766 				UIManager.put( "TabbedPane.tabAreaInsets", new Insets( 3, 2, 0, 0 ) );
    767 				UIManager.put( "TabbedPane.unselectedBackground", new Color( 220, 220, 220 ) );
    768 				UIManager.put( "TabbedPane.selected", new Color( 240, 240, 240 ) );
    769
    770 				PlasticXPLookAndFeel.setPlasticTheme( theme );
    771 			}
    772 		}
    773 		catch( Throwable e )
    774 		{
    775 			System.err.println( "Error initializing PlasticXPLookAndFeel; " + e.getMessage() );
    776 		}
    777 	}
    778
    779 	public static JMenuBar getMenuBar()
    780 	{
    781 		return instance == null ? null : instance.menuBar;
    782 	}
    783
    784 	public static void initSoapUILog() throws FactoryConfigurationError
    785 	{
    786 		if( !logIsInitialized )
    787 		{
    788 			File log4jconfig = new File( "soapui-log4j.xml" );
    789 			if( log4jconfig.exists() )
    790 			{
    791 				System.out.println( "Configuring log4j from [" + log4jconfig + "]" );
    792 				DOMConfigurator.configureAndWatch( log4jconfig.getAbsolutePath(), 5000 );
    793 			}
    794 			else
    795 			{
    796 				URL log4jUrl = SoapUI.class.getResource( "/soapui-log4j.xml" );
    797 				System.out.println( "Configuring log4j from [" + log4jUrl + "]" );
    798 				DOMConfigurator.configure( log4jUrl );
    799 			}
    800
    801 			logIsInitialized = true;
    802 		}
    803 	}
    804
    805 	private void show( Workspace workspace )
    806 	{
    807 		SoapUI.workspace = workspace;
    808
    809 		String desktopType = getSettings().getString( UISettings.DESKTOP_TYPE, "Default");
    810 		desktop = DesktopRegistry.getInstance().createDesktop( desktopType, workspace );
    811
    812 		if( desktop == null )
    813 			desktop = new StandaloneDesktop( workspace );
    814
    815 		getSettings().addSettingsListener( new SettingsListener() {
    816
    817 			public void settingChanged( String name, String newValue, String oldValue )
    818 			{
    819 				if( name.equals( UISettings.DESKTOP_TYPE ))
    820 				{
    821 					changeDesktop( DesktopRegistry.getInstance().createDesktop( newValue, SoapUI.workspace ));
    822 				}
    823 			}
    824 		} );
    825
    826 		buildUI();
    827 		testMonitor.addTestMonitorListener( new LogDisablingTestMonitorListener() );
    828 		testMonitor.init( workspace );
    829 		frame.setVisible( true );
    830 	}
    831
    832 	private void changeDesktop(SoapUIDesktop newDesktop )
    833 	{
    834 		desktopPanelsList.setDesktop( newDesktop );
    835 		desktop.removeDesktopListener( internalDesktopListener );
    836
    837 		desktop.transferTo( newDesktop );
    838 		desktop.release();
    839
    840 		desktop = newDesktop;
    841 		contentSplit.setTopComponent( desktop.getDesktopComponent() );
    842
    843 		desktop.addDesktopListener( internalDesktopListener );
    844
    845 		desktopMenu.removeAll();
    846 		ActionSupport.addActions( desktop.getActions(), desktopMenu );
    847 	}
    848
    849 	public static void logError( Throwable e )
    850 	{
    851 		String msg = e.getMessage();
    852 		if( msg == null )
    853 			msg = e.toString();
    854
    855 		log.error( "An error occured [" + msg + "], see error log for details" );
    856 		errorLog.error(e.toString(), e );
    857 	}
    858
    859 	public static synchronized Logger ensureGroovyLog()
    860 	{
    861 		if( !checkedGroovyLogMonitor )
    862 		{
    863 			Log4JMonitor logMonitor = getLogMonitor();
    864 			if( logMonitor != null && !logMonitor.hasLogArea( "groovy.log" ))
    865 				logMonitor.addLogArea( "groovy log", "groovy.log", false );
    866
    867 			checkedGroovyLogMonitor = true;
    868 		}
    869
    870 		return Logger.getLogger( "groovy.log" );
    871 	}
    872
    873 	public class InternalNavigatorListener implements NavigatorListener
    874 	{
    875 		public void nodeSelected( SoapUITreeNode treeNode )
    876 		{
    877 			if( treeNode == null )
    878 			{
    879 				setOverviewPanel( null );
    880 			}
    881 			else
    882 			{
    883 				PanelBuilder<ModelItem> panelBuilder = PanelBuilderRegistry.getPanelBuilder( treeNode.getModelItem() );
    884 				if( panelBuilder != null && panelBuilder.hasOverviewPanel() )
    885 				{
    886 					setOverviewPanel( panelBuilder.buildOverviewPanel( treeNode.getModelItem() ) );
    887 				}
    888 				else
    889 				{
    890 					setOverviewPanel( null );
    891 				}
    892 			}
    893 		}
    894 	}
    895
    896 	private class ExitAction extends AbstractAction
    897 	{
    898 		public ExitAction()
    899 		{
    900 			super( "Exit" );
    901 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
    902 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu Q" ) );
    903 		}
    904
    905 		public void actionPerformed( ActionEvent e )
    906 		{
    907 			saveOnExit = true;
    908 			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
    909 			frame.dispatchEvent( windowEvent );
    910 		}
    911 	}
    912
    913 	private class ShowSystemPropertiesAction extends AbstractAction
    914 	{
    915 		public ShowSystemPropertiesAction()
    916 		{
    917 			super( "System Properties" );
    918 			putValue( Action.SHORT_DESCRIPTION, "Shows the current systems properties" );
    919 		}
    920
    921 		public void actionPerformed( ActionEvent e )
    922 		{
    923 			StringBuffer buffer = new StringBuffer();
    924 			Properties properties = System.getProperties();
    925
    926 			List<String> keys = new ArrayList<String>();
    927 			for( Object key : properties.keySet() )
    928 				keys.add( key.toString() );
    929
    930 			Collections.sort( keys );
    931
    932 			String lastKey = null;
    933
    934 			for( String key : keys )
    935 			{
    936 				if( lastKey != null )
    937 				{
    938 					if( !key.startsWith( lastKey ))
    939 						buffer.append(  "\r\n" );
    940 				}
    941
    942 				int ix = key.indexOf( '.' );
    943 				lastKey = ix == -1 ? key : key.substring( 0, ix );
    944
    945 				buffer.append( key ).append( '=' ).append( properties.get( key )).append( "\r\n" );
    946 			}
    947
    948 			UISupport.showExtendedInfo( "System Properties", "Current system properties",
    949 						"<html><body><pre><font size=-1>" + buffer.toString() + "</font></pre></body></html>",
    950 						new Dimension( 600, 400 ));
    951 		}
    952 	}
    953
    954 	private class AboutAction extends AbstractAction
    955 	{
    956 		public AboutAction()
    957 		{
    958 			super( "About soapUI" );
    959 			putValue( Action.SHORT_DESCRIPTION, "Shows information on soapUI" );
    960 		}
    961
    962 		public void actionPerformed( ActionEvent e )
    963 		{
    964 			URI splashURI = null;
    965 			try
    966 			{
    967 				splashURI = SoapUI.findSplash( SoapUI.SOAPUI_SPLASH_GIF ).toURI();
    968 			}
    969 			catch( URISyntaxException e1 )
    970 			{
    971 				SoapUI.logError( e1 );
    972 			}
    973
    974 			Properties props = new Properties();
    975 			try
    976 			{
    977 				props.load( SoapUI.class.getResourceAsStream( "/buildinfo.txt" ) );
    978 			}
    979 			catch( Exception e1 )
    980 			{
    981 				SoapUI.logError( e1 );
    982 			}
    983
    984
    985 			UISupport.showExtendedInfo( "About soapUI", null,
    986 						"<html><body><p align=center><img src=\"" + splashURI + "\"><br>soapUI " +
    987 						SOAPUI_VERSION + ", copyright (C) 2004-2007 eviware.com<br>" +
    988 						"<a href=\"http://www.soapui.org\">http://www.soapui.org</a> | " +
    989 						"<a href=\"http://www.eviware.com\">http://www.eviware.com</a><br>" +
    990 									"Build " + props.getProperty( "build.number" ) + ", Build Date " +
    991 									props.getProperty( "build.date" ) + "</p></body></html>",
    992
    993 						new Dimension( 470, 350 ));
    994 		}
    995 	}
    996
    997
    998 	private class ExitWithoutSavingAction extends AbstractAction
    999 	{
    1000 		public ExitWithoutSavingAction()
    1001 		{
    1002 			super( "Exit without saving" );
    1003 			putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
    1004 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "ctrl alt Q" ) );
    1005 		}
    1006
    1007 		public void actionPerformed( ActionEvent e )
    1008 		{
    1009 			saveOnExit = false;
    1010 			WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
    1011 			frame.dispatchEvent( windowEvent );
    1012 		}
    1013 	}
    1014
    1015 	private class SavePreferencesAction extends AbstractAction
    1016 	{
    1017 		public SavePreferencesAction()
    1018 		{
    1019 			super( "Save Preferences" );
    1020 			putValue( Action.SHORT_DESCRIPTION, "Saves all global preferences" );
    1021 		}
    1022
    1023 		public void actionPerformed( ActionEvent e )
    1024 		{
    1025 			try
    1026 			{
    1027 				saveSettings();
    1028 			}
    1029 			catch( IOException e1 )
    1030 			{
    1031 				UISupport.showErrorMessage( e1 );
    1032 			}
    1033 		}
    1034 	}
    1035
    1036 	private class ImportPreferencesAction extends AbstractAction
    1037 	{
    1038 		public ImportPreferencesAction()
    1039 		{
    1040 			super( "Import Preferences" );
    1041 			putValue( Action.SHORT_DESCRIPTION, "Imports soapUI Settings from another settings-file" );
    1042 		}
    1043
    1044 		public void actionPerformed( ActionEvent e )
    1045 		{
    1046 			try
    1047 			{
    1048 				// prompt for import
    1049 				File file = UISupport.getFileDialogs().open( null, "Import Preferences", ".xml", "soapUI Settings XML (*.xml)", null );
    1050 				if( file != null )
    1051 				{
    1052 					SoapuiSettingsDocumentConfig doc = SoapuiSettingsDocumentConfig.Factory.parse( file );
    1053 					settingsDocument.set( doc );
    1054 				}
    1055 			}
    1056 			catch( Exception e1 )
    1057 			{
    1058 				UISupport.showErrorMessage( e1 );
    1059 			}
    1060 		}
    1061 	}
    1062
    1063 	public static TestMonitor getTestMonitor()
    1064 	{
    1065 		return testMonitor;
    1066 	}
    1067
    1068 	public static void setTestMonitor( TestMonitor monitor )
    1069 	{
    1070 		testMonitor = monitor;
    1071 	}
    1072
    1073 	public static Log4JMonitor getLogMonitor()
    1074 	{
    1075 		return instance == null ? null : instance.logMonitor;
    1076 	}
    1077
    1078 	public static void setLogMonitor( Log4JMonitor monitor )
    1079 	{
    1080 		if( instance != null )
    1081 			instance.logMonitor = monitor;
    1082 	}
    1083
    1084 	public static Settings getSettings()
    1085 	{
    1086 		if( settings == null )
    1087 		{
    1088 			if( settingsDocument == null )
    1089 				initSettings( DEFAULT_SETTINGS_FILE );
    1090
    1091 			if( settingsDocument.getSoapuiSettings() == null )
    1092 			{
    1093 				settingsDocument.addNewSoapuiSettings();
    1094 				settings = new XmlBeansSettingsImpl( null, null, settingsDocument.getSoapuiSettings() );
    1095
    1096 				settings.setBoolean( WsdlSettings.CACHE_WSDLS, true );
    1097 				settings.setBoolean( WsdlSettings.PRETTY_PRINT_RESPONSE_MESSAGES, true );
    1098
    1099 				settings.setBoolean( HttpSettings.INCLUDE_REQUEST_IN_TIME_TAKEN, true );
    1100 				settings.setBoolean( HttpSettings.INCLUDE_RESPONSE_IN_TIME_TAKEN, true );
    1101 			}
    1102 			else
    1103 			{
    1104 				settings = new XmlBeansSettingsImpl( null, null, settingsDocument.getSoapuiSettings() );
    1105 			}
    1106
    1107 			if( !settings.isSet( WsdlSettings.EXCLUDED_TYPES ))
    1108 			{
    1109 				StringList list = new StringList();
    1110 				list.add( "schema@http://www.w3.org/2001/XMLSchema");
    1111 				settings.setString( WsdlSettings.EXCLUDED_TYPES, list.toXml() );
    1112 			}
    1113
    1114 			if( !settings.isSet( WsdlSettings.NAME_WITH_BINDING ))
    1115 			{
    1116 				settings.setBoolean( WsdlSettings.NAME_WITH_BINDING, true );
    1117 			}
    1118
    1119 			if( !settings.isSet(  HttpSettings.MAX_CONNECTIONS_PER_HOST ))
    1120 			{
    1121 				settings.setLong( HttpSettings.MAX_CONNECTIONS_PER_HOST, 500 );
    1122 			}
    1123
    1124 			if( !settings.isSet(  HttpSettings.MAX_TOTAL_CONNECTIONS ))
    1125 			{
    1126 				settings.setLong( HttpSettings.MAX_TOTAL_CONNECTIONS, 2000 );
    1127 			}
    1128 		}
    1129
    1130 		return settings;
    1131 	}
    1132
    1133 	public static void saveSettings() throws IOException
    1134 	{
    1135 		File file = new File( DEFAULT_SETTINGS_FILE );
    1136 		settingsDocument.save( file );
    1137 		log.info( "Saved global preferences to [" + file.getAbsolutePath() + "]" );
    1138 	}
    1139
    1140 	/***
    1141 	 * Initializes the soapui settings from the specified file. Must be called on
    1142 	 * startup before any model items are created.
    1143 	 *
    1144 	 * @param fileName
    1145 	 */
    1146
    1147 	public static void initSettings( String fileName )
    1148 	{
    1149 		try
    1150 		{
    1151 			File settingsFile = new File( fileName );
    1152 			if( !settingsFile.exists() )
    1153 			{
    1154 				if( isStandalone )
    1155 				{
    1156 					settingsFile = importSettingsOnStartup( settingsFile );
    1157 				}
    1158
    1159 				if( settingsDocument == null )
    1160 				{
    1161 					log.info( "Creating new settings at [" + settingsFile.getAbsolutePath() + "]" );
    1162 					settingsDocument = SoapuiSettingsDocumentConfig.Factory.newInstance();
    1163 				}
    1164 			}
    1165 			else
    1166 			{
    1167 				settingsDocument = SoapuiSettingsDocumentConfig.Factory.parse( settingsFile );
    1168 				log.info( "initialized soapui-settings from [" + settingsFile.getAbsolutePath() + "]" );
    1169 			}
    1170 		}
    1171 		catch( Exception e )
    1172 		{
    1173 			log.warn( "Failed to load settings from [" + e.getMessage() + "], creating new" );
    1174 			settingsDocument = SoapuiSettingsDocumentConfig.Factory.newInstance();
    1175 		}
    1176 	}
    1177
    1178 	private static File importSettingsOnStartup( File settingsFile ) throws Exception
    1179 	{
    1180 		javax.swing.UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    1181 		if( JOptionPane.showConfirmDialog( null, "Missing soapUI Settings, import from existing installation?",
    1182 					"Import Preferences", JOptionPane.YES_NO_OPTION ) == JOptionPane.YES_OPTION )
    1183 		{
    1184 			while( true )
    1185 			{
    1186 				settingsFile = SwingFileDialogs.openFile( null, "Import Preferences", ".xml", "soapUI settings XML", settingsFile.getAbsolutePath() );
    1187 				if( settingsFile != null )
    1188 				{
    1189 					try
    1190 					{
    1191 						settingsDocument = SoapuiSettingsDocumentConfig.Factory.parse( settingsFile );
    1192 						log.info( "imported soapui-settings from [" + settingsFile.getAbsolutePath() + "]" );
    1193 						break;
    1194 					}
    1195 					catch( Exception e )
    1196 					{
    1197 						if( JOptionPane.showConfirmDialog( null, "Error loading settings from [" + settingsFile.getAbsolutePath() + "]\r\nspecify another?",
    1198 									"Error Importing", JOptionPane.OK_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE ) == JOptionPane.CANCEL_OPTION )
    1199 						{
    1200 							break;
    1201 						}
    1202 					}
    1203 				}
    1204 			}
    1205 		}
    1206
    1207 		return settingsFile;
    1208 	}
    1209
    1210 	// instance is null in Eclipse. /Lars
    1211 	// eclipse-version(s) should provide SoapUIDesktop implementation
    1212 	public static SoapUIDesktop getDesktop()
    1213 	{
    1214 		return instance != null ? instance.desktop : null;
    1215 	}
    1216
    1217 	public static void setDesktop( SoapUIDesktop desktop )
    1218 	{
    1219 		if( instance != null )
    1220 			instance.desktop = desktop;
    1221 	}
    1222
    1223 	public static Navigator getNavigator()
    1224 	{
    1225 		return instance != null ? instance.navigator : null;
    1226 	}
    1227
    1228 	public static SoapUIActionRegistry getActionRegistry()
    1229 	{
    1230 		return actionRegistry;
    1231 	}
    1232
    1233 	public static void setNavigator( Navigator navigator )
    1234 	{
    1235 		if( instance != null )
    1236 			instance.navigator = navigator;
    1237 	}
    1238
    1239 	static class SoapUISplash extends JWindow
    1240 	{
    1241 		public SoapUISplash( URL splashImage )
    1242 		{
    1243 			super( frame );
    1244 			JLabel l = new JLabel( new ImageIcon( splashImage ) );
    1245 			getContentPane().add( l, BorderLayout.CENTER );
    1246 			pack();
    1247 			Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    1248 			Dimension labelSize = l.getPreferredSize();
    1249 			setLocation( screenSize.width / 2 - ( labelSize.width / 2 ), screenSize.height / 2
    1250 						- ( labelSize.height / 2 ) );
    1251 			addMouseListener( new MouseAdapter()
    1252 			{
    1253 				public void mousePressed( MouseEvent e )
    1254 				{
    1255 					if( frame.isVisible())
    1256 					{
    1257 						setVisible( false );
    1258 						dispose();
    1259 					}
    1260 				}
    1261 			} );
    1262 			final int pause = 1000;
    1263 			final Runnable closerRunner = new Runnable()
    1264 			{
    1265 				public void run()
    1266 				{
    1267 					setVisible( false );
    1268 					dispose();
    1269 				}
    1270 			};
    1271
    1272 			Runnable waitRunner = new Runnable()
    1273 			{
    1274 				public void run()
    1275 				{
    1276 					try
    1277 					{
    1278 						do
    1279 						{
    1280 							Thread.sleep( pause );
    1281 						}
    1282 						while( !frame.isVisible() );
    1283
    1284 						SwingUtilities.invokeAndWait( closerRunner );
    1285 					}
    1286 					catch( Exception e )
    1287 					{
    1288 						SoapUI.logError( e );
    1289 						// can catch InvocationTargetException
    1290 						// can catch InterruptedException
    1291 					}
    1292 				}
    1293 			};
    1294 			setVisible( true );
    1295 			Thread splashThread = new Thread( waitRunner, "SplashThread" );
    1296 			splashThread.start();
    1297 		}
    1298 	}
    1299
    1300 	public static MockEngine getMockEngine()
    1301 	{
    1302 		if( mockEngine == null )
    1303 			mockEngine = new MockEngine();
    1304
    1305 		return mockEngine;
    1306 	}
    1307
    1308 	public static String getSchemaDirectory()
    1309 	{
    1310 		return SoapUI.getSettings().getString( WsdlSettings.SCHEMA_DIRECTORY, null );
    1311 	}
    1312
    1313 	public static Collection<? extends QName> getExcludedTypes()
    1314 	{
    1315 		List<QName> result = new ArrayList<QName>();
    1316
    1317 		String excluded = SoapUI.getSettings().getString( WsdlSettings.EXCLUDED_TYPES, null );
    1318       if( excluded != null && excluded.trim().length() > 0 )
    1319       {
    1320     	  	try
    1321 			{
    1322 			   StringList names = StringList.fromXml( excluded );
    1323 			   for( String name : names )
    1324 			   {
    1325 			   	int ix = name.indexOf( '@' );
    1326 			   	result.add( new QName( name.substring( ix+1 ), name.substring( 0, ix )));
    1327 			   }
    1328 		 	}
    1329 			catch( Exception e )
    1330 			{
    1331 				SoapUI.logError( e );
    1332 			}
    1333       }
    1334
    1335 		return result;
    1336 	}
    1337
    1338 	public static void setStandalone( boolean b )
    1339 	{
    1340 		SoapUI.isStandalone = b;
    1341 	}
    1342 }