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