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