View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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 com.eviware.soapui.actions.SaveAllProjectsAction;
16  import com.eviware.soapui.actions.SoapUIPreferencesAction;
17  import com.eviware.soapui.actions.SwitchDesktopPanelAction;
18  import com.eviware.soapui.impl.WorkspaceImpl;
19  import com.eviware.soapui.impl.actions.ImportWsdlProjectAction;
20  import com.eviware.soapui.impl.actions.NewWsdlProjectAction;
21  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
22  import com.eviware.soapui.impl.wsdl.WsdlProject;
23  import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis1.Axis1XWSDL2JavaAction;
24  import com.eviware.soapui.impl.wsdl.actions.iface.tools.axis2.Axis2WSDL2CodeAction;
25  import com.eviware.soapui.impl.wsdl.actions.iface.tools.cxf.CXFAction;
26  import com.eviware.soapui.impl.wsdl.actions.iface.tools.dotnet.DotNetWsdlAction;
27  import com.eviware.soapui.impl.wsdl.actions.iface.tools.gsoap.GSoapAction;
28  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jaxb.JaxbXjcAction;
29  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.JBossWSConsumeAction;
30  import com.eviware.soapui.impl.wsdl.actions.iface.tools.jbossws.WSToolsWsdl2JavaAction;
31  import com.eviware.soapui.impl.wsdl.actions.iface.tools.oracle.OracleWsaGenProxyAction;
32  import com.eviware.soapui.impl.wsdl.actions.iface.tools.tcpmon.TcpMonAction;
33  import com.eviware.soapui.impl.wsdl.actions.iface.tools.wscompile.WSCompileAction;
34  import com.eviware.soapui.impl.wsdl.actions.iface.tools.wsimport.WSImportAction;
35  import com.eviware.soapui.impl.wsdl.actions.iface.tools.xfire.XFireAction;
36  import com.eviware.soapui.impl.wsdl.actions.iface.tools.xmlbeans.XmlBeans2Action;
37  import com.eviware.soapui.impl.wsdl.actions.support.OpenUrlAction;
38  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
39  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
40  import com.eviware.soapui.model.ModelItem;
41  import com.eviware.soapui.model.PanelBuilder;
42  import com.eviware.soapui.model.TestPropertyHolder;
43  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
44  import com.eviware.soapui.model.settings.Settings;
45  import com.eviware.soapui.model.settings.SettingsListener;
46  import com.eviware.soapui.model.tree.SoapUITreeNode;
47  import com.eviware.soapui.model.util.PanelBuilderRegistry;
48  import com.eviware.soapui.model.workspace.Workspace;
49  import com.eviware.soapui.model.workspace.WorkspaceFactory;
50  import com.eviware.soapui.monitor.MockEngine;
51  import com.eviware.soapui.monitor.TestMonitor;
52  import com.eviware.soapui.settings.UISettings;
53  import com.eviware.soapui.support.UISupport;
54  import com.eviware.soapui.support.action.SoapUIActionRegistry;
55  import com.eviware.soapui.support.action.swing.ActionList;
56  import com.eviware.soapui.support.action.swing.ActionListBuilder;
57  import com.eviware.soapui.support.action.swing.ActionSupport;
58  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
59  import com.eviware.soapui.support.components.*;
60  import com.eviware.soapui.support.dnd.DropType;
61  import com.eviware.soapui.support.dnd.NavigatorDragAndDropable;
62  import com.eviware.soapui.support.dnd.SoapUIDragAndDropHandler;
63  import com.eviware.soapui.support.listener.SoapUIListenerRegistry;
64  import com.eviware.soapui.support.log.InspectorLog4JMonitor;
65  import com.eviware.soapui.support.log.JLogList;
66  import com.eviware.soapui.support.log.Log4JMonitor;
67  import com.eviware.soapui.support.log.LogDisablingTestMonitorListener;
68  import com.eviware.soapui.support.monitor.MonitorPanel;
69  import com.eviware.soapui.support.monitor.RuntimeMemoryMonitorSource;
70  import com.eviware.soapui.support.types.StringToStringMap;
71  import com.eviware.soapui.ui.JDesktopPanelsList;
72  import com.eviware.soapui.ui.Navigator;
73  import com.eviware.soapui.ui.NavigatorListener;
74  import com.eviware.soapui.ui.URLDesktopPanel;
75  import com.eviware.soapui.ui.desktop.DesktopPanel;
76  import com.eviware.soapui.ui.desktop.DesktopRegistry;
77  import com.eviware.soapui.ui.desktop.SoapUIDesktop;
78  import com.eviware.soapui.ui.desktop.standalone.StandaloneDesktop;
79  import com.eviware.soapui.ui.support.DesktopListenerAdapter;
80  import com.jgoodies.looks.HeaderStyle;
81  import com.jgoodies.looks.Options;
82  import org.apache.commons.cli.CommandLine;
83  import org.apache.commons.cli.CommandLineParser;
84  import org.apache.commons.cli.HelpFormatter;
85  import org.apache.commons.cli.PosixParser;
86  import org.apache.log4j.Level;
87  import org.apache.log4j.Logger;
88  
89  import javax.swing.*;
90  import java.awt.*;
91  import java.awt.dnd.DnDConstants;
92  import java.awt.dnd.DragSource;
93  import java.awt.event.ActionEvent;
94  import java.awt.event.KeyEvent;
95  import java.awt.event.WindowAdapter;
96  import java.awt.event.WindowEvent;
97  import java.io.File;
98  import java.net.URI;
99  import java.net.URISyntaxException;
100 import java.net.URLEncoder;
101 import java.util.*;
102 import java.util.List;
103 import java.util.Timer;
104 
105 /***
106  * Main SoapUI entry point.
107  */
108 
109 public class SoapUI
110 {
111    public static final String DEFAULT_DESKTOP = "Default";
112    public static final String CURRENT_SOAPUI_WORKSPACE = SoapUI.class.getName() + "@workspace";
113    public final static Logger log = Logger.getLogger( SoapUI.class );
114    public final static String SOAPUI_VERSION = "2.5";
115    public static final String DEFAULT_WORKSPACE_FILE = "default-soapui-workspace.xml";
116    public static final String SOAPUI_SPLASH_GIF = "soapui-splash.jpg";
117    private static final int DEFAULT_DESKTOP_ACTIONS_COUNT = 3;
118    public static final String BUILDINFO_RESOURCE = "/com/eviware/soapui/resources/conf/buildinfo.txt";
119 
120    public static String PUSH_PAGE_URL = "http://www.soapui.org/appindex/soapui_start.php";
121    public static String FRAME_ICON = "/16-perc.gif";
122    public static String PUSH_PAGE_ERROR_URL =
123               SoapUI.class.getResource( "/com/eviware/soapui/resources/html/starter-page.html" ).toString();
124 
125    // ------------------------------ FIELDS ------------------------------
126 
127    //	private static SoapUI instance;
128    private static List<Object> logCache = new ArrayList<Object>();
129 
130    private static SoapUICore soapUICore;
131    private static JFrame frame;
132 
133    private static Navigator navigator;
134    private static SoapUIDesktop desktop;
135    private static Workspace workspace;
136    private static Log4JMonitor logMonitor;
137    private static Logger errorLog = Logger.getLogger( "soapui.errorlog" );
138    private static boolean isStandalone;
139    private static TestMonitor testMonitor;
140 
141    private JMenu desktopMenu;
142    private JMenu helpMenu;
143    private JMenu fileMenu;
144    private static JMenuBar menuBar;
145    private JDesktopPanelsList desktopPanelsList;
146 
147    public static boolean checkedGroovyLogMonitor;
148 
149    private JPanel overviewPanel;
150    private JMenu toolsMenu;
151    private boolean saveOnExit = true;
152    private InternalDesktopListener internalDesktopListener = new InternalDesktopListener();
153    private JInspectorPanel mainInspector;
154 
155    private static Timer autoSaveTimer;
156    private static AutoSaveTimerTask autoSaveTimerTask;
157    private static String workspaceName;
158    private static StringToStringMap projectOptions = new StringToStringMap();
159    private static URLDesktopPanel urlDesktopPanel;
160 
161    // --------------------------- CONSTRUCTORS ---------------------------
162 
163    private SoapUI()
164    {
165    }
166 
167    private void buildUI()
168    {
169       frame.addWindowListener( new MainFrameWindowListener() );
170       UISupport.setMainFrame( frame );
171 
172       navigator = new Navigator( workspace );
173       navigator.addNavigatorListener( new InternalNavigatorListener() );
174 
175       desktopPanelsList = new JDesktopPanelsList( desktop );
176 
177       mainInspector = JInspectorPanelFactory.build( buildContentPanel(), SwingConstants.LEFT );
178       mainInspector.addInspector( new JComponentInspector<JComponent>( buildMainPanel(), "Navigator", "The soapUI Navigator", true ) );
179       mainInspector.setCurrentInspector( "Navigator" );
180 
181       frame.setJMenuBar( buildMainMenu() );
182       frame.getContentPane().add( buildToolbar(), BorderLayout.NORTH );
183       frame.getContentPane().add( mainInspector.getComponent(), BorderLayout.CENTER );
184       frame.setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
185       frame.setSize( 1000, 750 );
186 
187       mainInspector.setDividerLocation( 250 );
188       mainInspector.setResizeWeight( 0.1 );
189       navigator.selectModelItem( workspace );
190 
191       desktop.addDesktopListener( internalDesktopListener );
192 
193       ToolTipManager.sharedInstance().setInitialDelay( 200 );
194 
195       JTree mainTree = navigator.getMainTree();
196       DragSource dragSource = DragSource.getDefaultDragSource();
197       SoapUIDragAndDropHandler navigatorDragAndDropHandler = new SoapUIDragAndDropHandler(
198               new NavigatorDragAndDropable( mainTree ), DropType.ON + DropType.AFTER );
199 
200       dragSource.createDefaultDragGestureRecognizer( mainTree, DnDConstants.ACTION_COPY_OR_MOVE,
201               navigatorDragAndDropHandler );
202 
203       desktop.init();
204    }
205 
206    private JComponent buildToolbar()
207    {
208       JXToolBar toolbar = new JXToolBar();
209       toolbar.setRollover( true );
210       toolbar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
211       toolbar.add( new NewWsdlProjectActionDelegate() );
212       toolbar.add( new ImportWsdlProjectActionDelegate() );
213       toolbar.add( new SaveAllActionDelegate() );
214       toolbar.addSeparator();
215       toolbar.add( new PreferencesActionDelegate() );
216       toolbar.add( new ExitButtonAction() );
217       toolbar.addGlue();
218 
219       toolbar.add( new ShowOnlineHelpAction( HelpUrls.USERGUIDE_HELP_URL ) );
220 
221       toolbar.setBorder( BorderFactory.createEtchedBorder() );
222 
223       return toolbar;
224    }
225 
226    private JMenuBar buildMainMenu()
227    {
228       menuBar = new JMenuBar();
229       menuBar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
230 
231       menuBar.add( buildFileMenu() );
232       menuBar.add( buildToolsMenu() );
233       menuBar.add( buildDesktopMenu() );
234       menuBar.add( buildHelpMenu() );
235 
236       return menuBar;
237    }
238 
239    public static Workspace getWorkspace()
240    {
241       return workspace;
242    }
243 
244    private JMenu buildDesktopMenu()
245    {
246       desktopMenu = new JMenu( "Desktop" );
247       desktopMenu.setMnemonic( KeyEvent.VK_D );
248       desktopMenu.add( new SwitchDesktopPanelAction( desktopPanelsList ) );
249       desktopMenu.add( new MaximizeDesktopAction( (InspectorLog4JMonitor) logMonitor ) );
250       desktopMenu.addSeparator();
251 
252       ActionSupport.addActions( desktop.getActions(), desktopMenu );
253 
254       return desktopMenu;
255    }
256 
257    private JMenu buildHelpMenu()
258    {
259       helpMenu = new JMenu( "Help" );
260       helpMenu.setMnemonic( KeyEvent.VK_H );
261 
262       helpMenu.add( new ShowPushPageAction() );
263       helpMenu.add( new ShowOnlineHelpAction( "User Guide", HelpUrls.USERGUIDE_HELP_URL ) );
264       helpMenu.add( new ShowOnlineHelpAction( "Getting Started",
265               HelpUrls.GETTINGSTARTED_HELP_URL ) );
266       helpMenu.addSeparator();
267 
268       helpMenu.add( new ShowSystemPropertiesAction() );
269 
270       helpMenu.addSeparator();
271       helpMenu.add( new OpenUrlAction( "soapui.org", "http://www.soapui.org" ) );
272       helpMenu.add( new AboutAction() );
273       return helpMenu;
274    }
275 
276    private JMenu buildToolsMenu()
277    {
278       toolsMenu = new JMenu( "Tools" );
279       toolsMenu.setMnemonic( KeyEvent.VK_T );
280 
281       toolsMenu.add( SwingActionDelegate.createDelegate( WSToolsWsdl2JavaAction.SOAPUI_ACTION_ID ) );
282       toolsMenu.add( SwingActionDelegate.createDelegate( JBossWSConsumeAction.SOAPUI_ACTION_ID ) );
283       toolsMenu.addSeparator();
284       toolsMenu.add( SwingActionDelegate.createDelegate( WSCompileAction.SOAPUI_ACTION_ID ) );
285       toolsMenu.add( SwingActionDelegate.createDelegate( WSImportAction.SOAPUI_ACTION_ID ) );
286       toolsMenu.addSeparator();
287       toolsMenu.add( SwingActionDelegate.createDelegate( Axis1XWSDL2JavaAction.SOAPUI_ACTION_ID ) );
288       toolsMenu.add( SwingActionDelegate.createDelegate( Axis2WSDL2CodeAction.SOAPUI_ACTION_ID ) );
289       toolsMenu.add( SwingActionDelegate.createDelegate( CXFAction.SOAPUI_ACTION_ID ) );
290       toolsMenu.add( SwingActionDelegate.createDelegate( XFireAction.SOAPUI_ACTION_ID ) );
291       toolsMenu.add( SwingActionDelegate.createDelegate( OracleWsaGenProxyAction.SOAPUI_ACTION_ID ) );
292       toolsMenu.addSeparator();
293       toolsMenu.add( SwingActionDelegate.createDelegate( XmlBeans2Action.SOAPUI_ACTION_ID ) );
294       toolsMenu.add( SwingActionDelegate.createDelegate( JaxbXjcAction.SOAPUI_ACTION_ID ) );
295       toolsMenu.addSeparator();
296       toolsMenu.add( SwingActionDelegate.createDelegate( DotNetWsdlAction.SOAPUI_ACTION_ID ) );
297       toolsMenu.add( SwingActionDelegate.createDelegate( GSoapAction.SOAPUI_ACTION_ID ) );
298       toolsMenu.addSeparator();
299       toolsMenu.add( SwingActionDelegate.createDelegate( TcpMonAction.SOAPUI_ACTION_ID ) );
300       // toolsMenu.addSeparator();
301       // toolsMenu.add( new XQueryXPathTesterAction());
302 
303       return toolsMenu;
304    }
305 
306    private JMenu buildFileMenu()
307    {
308       fileMenu = new JMenu( "File" );
309       fileMenu.setMnemonic( KeyEvent.VK_F );
310 
311       ActionList actions = ActionListBuilder.buildActions( workspace );
312       actions.removeAction( actions.getActionCount() - 1 );
313 
314       ActionSupport.addActions( actions, fileMenu );
315 
316       fileMenu.add( SoapUIPreferencesAction.getInstance() );
317       fileMenu.add( new SavePreferencesAction() );
318       fileMenu.add( new ImportPreferencesAction() );
319 
320       fileMenu.addSeparator();
321       fileMenu.add( buildRecentMenu() );
322       fileMenu.addSeparator();
323       fileMenu.add( new ExitAction() );
324       fileMenu.add( new ExitWithoutSavingAction() );
325       fileMenu.addSeparator();
326       fileMenu.add( new ShowOnlineHelpAction( HelpUrls.OVERVIEW_HELP_URL ) );
327 
328       return fileMenu;
329    }
330 
331    private JMenuItem buildRecentMenu()
332    {
333       JMenu recentMenu = new JMenu( "Recent" );
334 
335       JMenu recentProjectsMenu = new JMenu( "Projects" );
336       JMenu recentWorkspacesMenu = new JMenu( "Workspaces" );
337       JMenu recentEditorsMenu = new JMenu( "Editors" );
338 
339       recentMenu.add( recentEditorsMenu );
340       recentMenu.add( recentProjectsMenu );
341       recentMenu.add( recentWorkspacesMenu );
342 
343       RecentItemsListener recentItemsListener = new RecentItemsListener( recentWorkspacesMenu, recentProjectsMenu, recentEditorsMenu );
344       workspace.addWorkspaceListener( recentItemsListener );
345       desktop.addDesktopListener( recentItemsListener );
346 
347       return recentMenu;
348    }
349 
350    public JFrame getFrame()
351    {
352       return frame;
353    }
354 
355    private JComponent buildMainPanel()
356    {
357       JInspectorPanel inspectorPanel = JInspectorPanelFactory.build( navigator );
358       inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildOverviewPanel(),
359               "Properties", "Properties for the currently selected item", true ) );
360       inspectorPanel.setDividerLocation( 500 );
361       inspectorPanel.setResizeWeight( 0.6 );
362       inspectorPanel.setCurrentInspector( "Properties" );
363 
364       return inspectorPanel.getComponent();
365    }
366 
367    private JComponent buildOverviewPanel()
368    {
369       overviewPanel = new JPanel( new BorderLayout() );
370       overviewPanel.setBorder( BorderFactory.createEmptyBorder( 3, 0, 0, 2 ) );
371 
372       return overviewPanel;
373    }
374 
375    private void setOverviewPanel( Component panel )
376    {
377       if( overviewPanel.getComponentCount() == 0 && panel == null )
378          return;
379 
380       overviewPanel.removeAll();
381       if( panel != null )
382          overviewPanel.add( panel, BorderLayout.CENTER );
383       overviewPanel.revalidate();
384       overviewPanel.repaint();
385    }
386 
387    private JComponent buildContentPanel()
388    {
389       return buildLogPanel( true, "soapUI log" );
390    }
391 
392    private JComponent buildLogPanel( boolean hasDefault, String defaultName )
393    {
394       InspectorLog4JMonitor inspectorLog4JMonitor = new InspectorLog4JMonitor( desktop.getDesktopComponent() );
395 
396       JComponent monitor = initLogMonitor( hasDefault, defaultName, inspectorLog4JMonitor );
397 
398       if( !SoapUI.getSettings().getBoolean( UISettings.SHOW_LOGS_AT_STARTUP ) )
399          inspectorLog4JMonitor.activate( null );
400 
401       MonitorPanel monitorPanel = new MonitorPanel( new RuntimeMemoryMonitorSource() );
402       monitorPanel.start();
403       inspectorLog4JMonitor.addInspector( new JComponentInspector<JComponent>(
404               monitorPanel, "memory log", "Shows runtime memory consumtion", true ) );
405 
406       return monitor;
407    }
408 
409    public static JComponent initLogMonitor( boolean hasDefault, String defaultName, Log4JMonitor logMonitor )
410    {
411       SoapUI.logMonitor = logMonitor;
412       logMonitor.addLogArea( defaultName, "com.eviware.soapui", hasDefault ).setLevel( Level.DEBUG );
413       logMonitor.addLogArea( "http log", "httpclient.wire", false ).setLevel( Level.DEBUG );
414       logMonitor.addLogArea( "jetty log", "jetty", false ).setLevel( Level.INFO );
415       logMonitor.addLogArea( "error log", "soapui.errorlog", false ).setLevel( Level.DEBUG );
416 
417       for( Object message : logCache )
418       {
419          logMonitor.logEvent( message );
420       }
421 
422       return logMonitor.getComponent();
423    }
424 
425    // -------------------------- OTHER METHODS --------------------------
426 
427    public static synchronized void log( final Object msg )
428    {
429       if( logMonitor == null )
430       {
431          logCache.add( msg );
432          return;
433       }
434 
435       if( SwingUtilities.isEventDispatchThread() )
436       {
437          logMonitor.logEvent( msg );
438       }
439       else
440       {
441          SwingUtilities.invokeLater( new Runnable()
442          {
443             public void run()
444             {
445                logMonitor.logEvent( msg );
446             }
447          } );
448       }
449    }
450 
451    // -------------------------- INNER CLASSES --------------------------
452 
453    private final class InternalDesktopListener extends DesktopListenerAdapter
454    {
455       public void desktopPanelSelected( DesktopPanel desktopPanel )
456       {
457          ModelItem modelItem = desktopPanel.getModelItem();
458          if( modelItem != null )
459             navigator.selectModelItem( modelItem );
460       }
461    }
462 
463    private final class MainFrameWindowListener extends WindowAdapter
464    {
465       public void windowClosing( WindowEvent e )
466       {
467          if( onExit() )
468             frame.dispose();
469       }
470 
471       public void windowClosed( WindowEvent e )
472       {
473          System.out.println( "exiting.." );
474          System.exit( 0 );
475       }
476    }
477 
478    public static void main( String[] args ) throws Exception
479    {
480       startSoapUI( args, "soapUI " + SOAPUI_VERSION, "soapui-splash.gif", new StandaloneSoapUICore( true ) );
481    }
482 
483    public static SoapUI startSoapUI( String[] args, String title, String splashImage, SwingSoapUICore core ) throws Exception
484    {
485       frame = new JFrame( title );
486 
487       SoapUISplash splash = new SoapUISplash( splashImage, frame );
488 
489       frame.setIconImage( UISupport.createImageIcon( FRAME_ICON ).getImage() );
490 
491       isStandalone = true;
492       soapUICore = core;
493 
494       SoapUI soapUI = new SoapUI();
495       Workspace workspace = null;
496 
497       org.apache.commons.cli.Options options = initSoapUIOptions();
498       CommandLineParser parser = new PosixParser();
499       CommandLine cmd = parser.parse( options, args );
500 
501       if( validateCommandLineArgs( cmd, options ) )
502       {
503          System.exit( 1 );
504       }
505 
506       if( workspaceName != null )
507       {
508          workspace = WorkspaceFactory.getInstance().openWorkspace( workspaceName, projectOptions );
509          soapUICore.getSettings().setString( CURRENT_SOAPUI_WORKSPACE, workspaceName );
510       }
511       else
512       {
513          String wsfile = soapUICore.getSettings().getString( CURRENT_SOAPUI_WORKSPACE, System.getProperty( "user.home" ) + File.separatorChar
514                  + DEFAULT_WORKSPACE_FILE );
515          workspace = WorkspaceFactory.getInstance().openWorkspace( wsfile, projectOptions );
516       }
517 
518       core.prepareUI();
519       soapUI.show( workspace );
520       core.afterStartup( workspace );
521       Thread.sleep( 500 );
522       splash.setVisible( false );
523 
524       if( getSettings().getBoolean( UISettings.SHOW_STARTUP_PAGE ) )
525       {
526          SwingUtilities.invokeLater( new Runnable()
527          {
528             public void run()
529             {
530                showPushPage();
531             }
532          } );
533 
534       }
535 //		SoapUI.workspace.inspectProjects();
536 
537       return soapUI;
538    }
539 
540    private static boolean validateCommandLineArgs( CommandLine cmd, org.apache.commons.cli.Options options )
541    {
542       if( cmd.hasOption( 'w' ) )
543       {
544          workspaceName = cmd.getOptionValue( 'w' );
545       }
546 
547       if( cmd.hasOption( 'p' ) )
548       {
549          for( String projectNamePassword : cmd.getOptionValues( 'p' ) )
550          {
551             String[] nameAndPassword = projectNamePassword.split( ":" );
552             projectOptions.put( nameAndPassword[0], nameAndPassword[1] );
553          }
554       }
555 
556       if( cmd.getArgs().length > 0 )
557       {
558          HelpFormatter formatter = new HelpFormatter();
559          formatter.printHelp( "soapui.sh [options]", options );
560          return true;
561       }
562 
563       return false;
564 
565    }
566 
567    private static org.apache.commons.cli.Options initSoapUIOptions()
568    {
569 
570       org.apache.commons.cli.Options options = new org.apache.commons.cli.Options();
571       options.addOption( "w", true, "Specified the name of the workspace xml file" );
572       options.addOption( "p", true, "Sets project name and its password in format <project name>:<password>" );
573 
574       return options;
575    }
576 
577    public static SoapUICore getSoapUICore()
578    {
579       return soapUICore;
580    }
581 
582    public static TestPropertyHolder getGlobalProperties()
583    {
584       return PropertyExpansionUtils.getGlobalProperties();
585    }
586 
587    public static void setSoapUICore( SoapUICore soapUICore )
588    {
589       SoapUI.soapUICore = soapUICore;
590    }
591 
592    public static boolean isStandalone()
593    {
594       return isStandalone;
595    }
596 
597    public static JMenuBar getMenuBar()
598    {
599       return menuBar;
600    }
601 
602    private void show( Workspace workspace )
603    {
604       SoapUI.workspace = workspace;
605 
606       String desktopType = soapUICore.getSettings().getString( UISettings.DESKTOP_TYPE, SoapUI.DEFAULT_DESKTOP );
607       desktop = DesktopRegistry.getInstance().createDesktop( desktopType, workspace );
608 
609       if( desktop == null )
610          desktop = new StandaloneDesktop( workspace );
611 
612       if( testMonitor == null )
613          testMonitor = new TestMonitor();
614 
615       soapUICore.getSettings().addSettingsListener( new SettingsListener()
616       {
617          public void settingChanged( String name, String newValue, String oldValue )
618          {
619             if( name.equals( UISettings.DESKTOP_TYPE ) )
620             {
621                changeDesktop( DesktopRegistry.getInstance().createDesktop( newValue, SoapUI.workspace ) );
622             }
623          }
624       } );
625 
626       buildUI();
627 
628       testMonitor.addTestMonitorListener( new LogDisablingTestMonitorListener() );
629       testMonitor.init( workspace );
630       frame.setVisible( true );
631 
632       initAutoSaveTimer();
633    }
634 
635    private void changeDesktop( SoapUIDesktop newDesktop )
636    {
637       desktopPanelsList.setDesktop( newDesktop );
638       desktop.removeDesktopListener( internalDesktopListener );
639 
640       desktop.transferTo( newDesktop );
641       desktop.release();
642 
643       desktop = newDesktop;
644 
645       if( logMonitor instanceof InspectorLog4JMonitor )
646          ( (InspectorLog4JMonitor) logMonitor ).setContentComponent( desktop.getDesktopComponent() );
647 
648       desktop.addDesktopListener( internalDesktopListener );
649 
650       while( desktopMenu.getItemCount() > DEFAULT_DESKTOP_ACTIONS_COUNT )
651          desktopMenu.remove( DEFAULT_DESKTOP_ACTIONS_COUNT );
652 
653       ActionSupport.addActions( desktop.getActions(), desktopMenu );
654 
655       desktop.init();
656    }
657 
658    protected boolean onExit()
659    {
660       if( saveOnExit )
661       {
662          String question = "Exit SoapUI?";
663 
664          if( getTestMonitor().hasRunningTests() )
665             question += "\n(Projects with running tests will not be saved)";
666 
667          if( !UISupport.confirm( question, "Question" ) )
668             return false;
669 
670          try
671          {
672             PropertyExpansionUtils.saveGlobalProperties();
673             soapUICore.saveSettings();
674             workspace.onClose();
675          }
676          catch( Exception e1 )
677          {
678             SoapUI.logError( e1 );
679          }
680       }
681       else
682       {
683          if( !UISupport.confirm( "Exit SoapUI without saving?", "Question" ) )
684          {
685             saveOnExit = true;
686             return false;
687          }
688       }
689 
690       return true;
691    }
692 
693    public static void logError( Throwable e )
694    {
695       String msg = e.getMessage();
696       if( msg == null )
697          msg = e.toString();
698 
699       log.error( "An error occured [" + msg + "], see error log for details" );
700       errorLog.error( e.toString(), e );
701       if( !isStandalone() || "true".equals( System.getProperty( "soapui.stacktrace" ) ) )
702          e.printStackTrace();
703    }
704 
705    public static synchronized Logger ensureGroovyLog()
706    {
707       if( !checkedGroovyLogMonitor )
708       {
709          Log4JMonitor logMonitor = getLogMonitor();
710          if( logMonitor != null && !logMonitor.hasLogArea( "groovy.log" ) )
711          {
712             logMonitor.addLogArea( "groovy log", "groovy.log", false );
713             checkedGroovyLogMonitor = true;
714          }
715       }
716 
717       return Logger.getLogger( "groovy.log" );
718    }
719 
720    public class InternalNavigatorListener implements NavigatorListener
721    {
722       public void nodeSelected( SoapUITreeNode treeNode )
723       {
724          if( treeNode == null )
725          {
726             setOverviewPanel( null );
727          }
728          else
729          {
730             ModelItem modelItem = treeNode.getModelItem();
731             PropertyHolderTable propertyHolderTable = null;
732 
733             if( modelItem instanceof TestPropertyHolder )
734             {
735                // check for closed project -> this should be solved with a separate ClosedWsdlProject modelItem
736                if( !( modelItem instanceof WsdlProject ) || ( (WsdlProject) modelItem ).isOpen() )
737                {
738                   propertyHolderTable = new PropertyHolderTable( (TestPropertyHolder) modelItem );
739                }
740             }
741 
742             PanelBuilder<ModelItem> panelBuilder = PanelBuilderRegistry.getPanelBuilder( modelItem );
743             if( panelBuilder != null && panelBuilder.hasOverviewPanel() )
744             {
745                Component overviewPanel = panelBuilder.buildOverviewPanel( modelItem );
746                if( propertyHolderTable != null )
747                {
748                   JTabbedPane tabs = new JTabbedPane();
749                   if( overviewPanel instanceof JPropertiesTable )
750                   {
751                      JPropertiesTable<?> t = (JPropertiesTable<?>) overviewPanel;
752                      tabs.addTab( t.getTitle(), overviewPanel );
753                      t.setTitle( null );
754                   }
755                   else
756                   {
757                      tabs.addTab( "Overview", overviewPanel );
758                   }
759 
760                   tabs.addTab( ( (TestPropertyHolder) modelItem ).getPropertiesLabel(), propertyHolderTable );
761                   overviewPanel = UISupport.createTabPanel( tabs, false );
762                }
763 
764                setOverviewPanel( overviewPanel );
765             }
766             else
767             {
768                setOverviewPanel( null );
769             }
770          }
771       }
772    }
773 
774    private class ExitAction extends AbstractAction
775    {
776       public ExitAction()
777       {
778          super( "Exit" );
779          putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
780          putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu Q" ) );
781       }
782 
783       public void actionPerformed( ActionEvent e )
784       {
785          saveOnExit = true;
786          WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
787          frame.dispatchEvent( windowEvent );
788       }
789    }
790 
791    private class ExitButtonAction extends AbstractAction
792    {
793       public ExitButtonAction()
794       {
795          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/system-log-out.png" ) );
796          putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
797       }
798 
799       public void actionPerformed( ActionEvent e )
800       {
801          saveOnExit = true;
802          WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
803          frame.dispatchEvent( windowEvent );
804       }
805    }
806 
807    private class ShowPushPageAction extends AbstractAction
808    {
809       public ShowPushPageAction()
810       {
811          super( "Starter Page" );
812          putValue( Action.SHORT_DESCRIPTION, "Shows the starter page" );
813       }
814 
815       public void actionPerformed( ActionEvent e )
816       {
817          showPushPage();
818       }
819    }
820 
821    public static void showPushPage()
822    {
823       if( urlDesktopPanel == null )
824       {
825          urlDesktopPanel = new URLDesktopPanel( "soapUI Starter Page", "Info on soapUI", null );
826       }
827       
828       DesktopPanel dp = UISupport.showDesktopPanel( urlDesktopPanel );
829       desktop.maximize( dp );
830 
831       urlDesktopPanel.navigate( PUSH_PAGE_URL + "?version=" + URLEncoder.encode( SOAPUI_VERSION ),
832               PUSH_PAGE_ERROR_URL, true);
833    }
834 
835    private static class ShowSystemPropertiesAction extends AbstractAction
836    {
837       public ShowSystemPropertiesAction()
838       {
839          super( "System Properties" );
840          putValue( Action.SHORT_DESCRIPTION, "Shows the current systems properties" );
841       }
842 
843       public void actionPerformed( ActionEvent e )
844       {
845          StringBuffer buffer = new StringBuffer();
846          Properties properties = System.getProperties();
847 
848          List<String> keys = new ArrayList<String>();
849          for( Object key : properties.keySet() )
850             keys.add( key.toString() );
851 
852          Collections.sort( keys );
853 
854          String lastKey = null;
855 
856          for( String key : keys )
857          {
858             if( lastKey != null )
859             {
860                if( !key.startsWith( lastKey ) )
861                   buffer.append( "\r\n" );
862             }
863 
864             int ix = key.indexOf( '.' );
865             lastKey = ix == -1 ? key : key.substring( 0, ix );
866 
867             buffer.append( key ).append( '=' ).append( properties.get( key ) ).append( "\r\n" );
868          }
869 
870          UISupport.showExtendedInfo( "System Properties", "Current system properties",
871                  "<html><body><pre><font size=-1>" + buffer.toString() + "</font></pre></body></html>",
872                  new Dimension( 600, 400 ) );
873       }
874    }
875 
876    private static class AboutAction extends AbstractAction
877    {
878       public AboutAction()
879       {
880          super( "About soapUI" );
881          putValue( Action.SHORT_DESCRIPTION, "Shows information on soapUI" );
882       }
883 
884       public void actionPerformed( ActionEvent e )
885       {
886          URI splashURI = null;
887          try
888          {
889             splashURI = UISupport.findSplash( SoapUI.SOAPUI_SPLASH_GIF ).toURI();
890          }
891          catch( URISyntaxException e1 )
892          {
893             SoapUI.logError( e1 );
894          }
895 
896          Properties props = new Properties();
897          try
898          {
899             props.load( SoapUI.class.getResourceAsStream( BUILDINFO_RESOURCE ) );
900          }
901          catch( Exception e1 )
902          {
903             SoapUI.logError( e1 );
904          }
905 
906          UISupport.showExtendedInfo( "About soapUI", null,
907                  "<html><body><p align=center><img src=\"" + splashURI + "\"><br>soapUI " +
908                          SOAPUI_VERSION + ", copyright (C) 2004-2008 eviware.com<br>" +
909                          "<a href=\"http://www.soapui.org\">http://www.soapui.org</a> | " +
910                          "<a href=\"http://www.eviware.com\">http://www.eviware.com</a><br>" +
911                          "Build " + props.getProperty( "build.number" ) + ", Build Date " +
912                          props.getProperty( "build.date" ) + "</p></body></html>",
913 
914                  new Dimension( 470, 350 ) );
915       }
916    }
917 
918    private class ExitWithoutSavingAction extends AbstractAction
919    {
920       public ExitWithoutSavingAction()
921       {
922          super( "Exit without saving" );
923          putValue( Action.SHORT_DESCRIPTION, "Saves all projects and exits SoapUI" );
924          putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "ctrl alt Q" ) );
925       }
926 
927       public void actionPerformed( ActionEvent e )
928       {
929          saveOnExit = false;
930          WindowEvent windowEvent = new WindowEvent( frame, WindowEvent.WINDOW_CLOSING );
931          frame.dispatchEvent( windowEvent );
932       }
933    }
934 
935    private class SavePreferencesAction extends AbstractAction
936    {
937       public SavePreferencesAction()
938       {
939          super( "Save Preferences" );
940          putValue( Action.SHORT_DESCRIPTION, "Saves all global preferences" );
941       }
942 
943       public void actionPerformed( ActionEvent e )
944       {
945          try
946          {
947             soapUICore.saveSettings();
948          }
949          catch( Exception e1 )
950          {
951             UISupport.showErrorMessage( e1 );
952          }
953       }
954    }
955 
956    public static TestMonitor getTestMonitor()
957    {
958       if( testMonitor == null )
959          testMonitor = new TestMonitor();
960 
961       return testMonitor;
962    }
963 
964    public static void setTestMonitor( TestMonitor monitor )
965    {
966       testMonitor = monitor;
967    }
968 
969    public static Log4JMonitor getLogMonitor()
970    {
971       return logMonitor;
972    }
973 
974    public static void setLogMonitor( Log4JMonitor monitor )
975    {
976       logMonitor = monitor;
977    }
978 
979    // instance is null in Eclipse. /Lars
980    // eclipse-version(s) should provide SoapUIDesktop implementation
981    public static SoapUIDesktop getDesktop()
982    {
983       return desktop;
984    }
985 
986    public static void setDesktop( SoapUIDesktop desktop )
987    {
988       SoapUI.desktop = desktop;
989    }
990 
991    public static Navigator getNavigator()
992    {
993       return navigator;
994    }
995 
996    public static SoapUIActionRegistry getActionRegistry()
997    {
998       if( soapUICore == null )
999          soapUICore = new DefaultSoapUICore();
1000 
1001       return soapUICore.getActionRegistry();
1002    }
1003 
1004    public static void setNavigator( Navigator navigator )
1005    {
1006       SoapUI.navigator = navigator;
1007    }
1008 
1009    public static void setStandalone( boolean standalone )
1010    {
1011       SoapUI.isStandalone = standalone;
1012    }
1013 
1014    private static class NewWsdlProjectActionDelegate extends AbstractAction
1015    {
1016       public NewWsdlProjectActionDelegate()
1017       {
1018          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/project.gif" ) );
1019          putValue( Action.SHORT_DESCRIPTION, "Creates a new WSDL Project" );
1020       }
1021 
1022       public void actionPerformed( ActionEvent e )
1023       {
1024          SoapUI.getActionRegistry().getAction( NewWsdlProjectAction.SOAPUI_ACTION_ID ).perform( workspace, null );
1025       }
1026    }
1027 
1028    private static class ImportWsdlProjectActionDelegate extends AbstractAction
1029    {
1030       public ImportWsdlProjectActionDelegate()
1031       {
1032          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/import_project.gif" ) );
1033          putValue( Action.SHORT_DESCRIPTION, "Imports an existing WSDL Project into the current workspace" );
1034       }
1035 
1036       public void actionPerformed( ActionEvent e )
1037       {
1038          SoapUI.getActionRegistry().getAction( ImportWsdlProjectAction.SOAPUI_ACTION_ID ).perform( workspace, null );
1039       }
1040    }
1041 
1042    private static class SaveAllActionDelegate extends AbstractAction
1043    {
1044       public SaveAllActionDelegate()
1045       {
1046          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/disk_multiple.png" ) );
1047          putValue( Action.SHORT_DESCRIPTION, "Saves all projects in the current workspace" );
1048       }
1049 
1050       public void actionPerformed( ActionEvent e )
1051       {
1052          SoapUI.getActionRegistry().getAction( SaveAllProjectsAction.SOAPUI_ACTION_ID ).perform( workspace, null );
1053       }
1054    }
1055 
1056    private class PreferencesActionDelegate extends AbstractAction
1057    {
1058       public PreferencesActionDelegate()
1059       {
1060          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ) );
1061          putValue( Action.SHORT_DESCRIPTION, "Sets Global soapUI Options" );
1062       }
1063 
1064       public void actionPerformed( ActionEvent e )
1065       {
1066          SoapUIPreferencesAction.getInstance().actionPerformed( null );
1067       }
1068    }
1069 
1070    public static class ImportPreferencesAction extends AbstractAction
1071    {
1072       public static final String IMPORT_PREFERENCES_ACTION_NAME = "Import Preferences";
1073 
1074       public ImportPreferencesAction()
1075       {
1076          super( ImportPreferencesAction.IMPORT_PREFERENCES_ACTION_NAME );
1077          putValue( Action.SHORT_DESCRIPTION, "Imports soapUI Settings from another settings-file" );
1078       }
1079 
1080       public void actionPerformed( ActionEvent e )
1081       {
1082          try
1083          {
1084             // prompt for import
1085             File file = UISupport.getFileDialogs().open( null, ImportPreferencesAction.IMPORT_PREFERENCES_ACTION_NAME, ".xml", "soapUI Settings XML (*.xml)", null );
1086             if( file != null )
1087                soapUICore.importSettings( file );
1088          }
1089          catch( Exception e1 )
1090          {
1091             UISupport.showErrorMessage( e1 );
1092          }
1093       }
1094    }
1095 
1096    public static SoapUIListenerRegistry getListenerRegistry()
1097    {
1098       if( soapUICore == null )
1099          soapUICore = DefaultSoapUICore.createDefault();
1100 
1101       return soapUICore.getListenerRegistry();
1102    }
1103 
1104    public static Settings getSettings()
1105    {
1106       if( soapUICore == null )
1107          soapUICore = DefaultSoapUICore.createDefault();
1108 
1109       return soapUICore.getSettings();
1110    }
1111 
1112    public static void importPreferences( File file ) throws Exception
1113    {
1114       if( soapUICore != null )
1115          soapUICore.importSettings( file );
1116    }
1117 
1118    public static MockEngine getMockEngine()
1119    {
1120       if( soapUICore == null )
1121          soapUICore = DefaultSoapUICore.createDefault();
1122 
1123       return soapUICore.getMockEngine();
1124    }
1125 
1126    public static String saveSettings() throws Exception
1127    {
1128       return soapUICore == null ? null : soapUICore.saveSettings();
1129    }
1130 
1131    public static void initDefaultCore()
1132    {
1133       if( soapUICore == null )
1134          soapUICore = DefaultSoapUICore.createDefault();
1135    }
1136 
1137    public class MaximizeDesktopAction extends AbstractAction
1138    {
1139       private JLogList lastLog;
1140       private int lastMainDividerLocation;
1141       private final InspectorLog4JMonitor log4JMonitor;
1142       private int lastLogDividerLocation;
1143 
1144       public MaximizeDesktopAction( InspectorLog4JMonitor log4JMonitor )
1145       {
1146          super( "Maximize Desktop" );
1147          this.log4JMonitor = log4JMonitor;
1148 
1149          putValue( SHORT_DESCRIPTION, "Hides/Shows the Navigator and Log tabs" );
1150          putValue( ACCELERATOR_KEY, UISupport.getKeyStroke( "menu M" ) );
1151       }
1152 
1153       public void actionPerformed( ActionEvent e )
1154       {
1155          if( mainInspector.getCurrentInspector() != null || logMonitor.getCurrentLog() != null )
1156          {
1157             lastMainDividerLocation = mainInspector.getDividerLocation();
1158             mainInspector.deactivate();
1159 
1160             lastLog = logMonitor.getCurrentLog();
1161             lastLogDividerLocation = log4JMonitor.getDividerLocation();
1162 
1163             log4JMonitor.deactivate();
1164          }
1165          else
1166          {
1167             mainInspector.setCurrentInspector( "Navigator" );
1168             mainInspector.setDividerLocation( lastMainDividerLocation == 0 ? 250 : lastMainDividerLocation );
1169 
1170             log4JMonitor.setCurrentLog( lastLog );
1171             log4JMonitor.setDividerLocation( lastLogDividerLocation == 0 ? 500 : lastLogDividerLocation );
1172          }
1173       }
1174    }
1175 
1176    public static void initAutoSaveTimer()
1177    {
1178       Settings settings = SoapUI.getSettings();
1179       long interval = settings.getLong( UISettings.AUTO_SAVE_INTERVAL, 0 );
1180 
1181       if( autoSaveTimerTask != null )
1182       {
1183          if( interval == 0 )
1184             SoapUI.log( "Cancelling AutoSave Timer" );
1185 
1186          autoSaveTimerTask.cancel();
1187          autoSaveTimerTask = null;
1188       }
1189 
1190       if( interval > 0 )
1191       {
1192          autoSaveTimerTask = new AutoSaveTimerTask();
1193 
1194          SoapUI.log( "Scheduling autosave every " + interval + " minutes" );
1195 
1196          if( autoSaveTimer == null )
1197             autoSaveTimer = new Timer( "AutoSave Timer" );
1198 
1199          autoSaveTimer.schedule( autoSaveTimerTask, interval * 1000 * 60, interval * 1000 * 60 );
1200       }
1201    }
1202 
1203    private static class AutoSaveTimerTask extends TimerTask
1204    {
1205       @Override
1206       public void run()
1207       {
1208          SoapUI.log( "Autosaving Workspace" );
1209          ( (WorkspaceImpl) SoapUI.getWorkspace() ).save( false, true );
1210       }
1211    }
1212 }