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