View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui;
14  
15  import java.io.File;
16  import java.io.FileInputStream;
17  import java.io.IOException;
18  import java.io.UnsupportedEncodingException;
19  import java.net.URL;
20  import java.security.GeneralSecurityException;
21  
22  import javax.swing.JLabel;
23  import javax.swing.JOptionPane;
24  import javax.swing.JPasswordField;
25  
26  import org.apache.commons.ssl.OpenSSL;
27  import org.apache.log4j.Logger;
28  import org.apache.log4j.xml.DOMConfigurator;
29  
30  import com.eviware.soapui.config.SoapuiSettingsDocumentConfig;
31  import com.eviware.soapui.impl.settings.XmlBeansSettingsImpl;
32  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
33  import com.eviware.soapui.model.settings.Settings;
34  import com.eviware.soapui.monitor.MockEngine;
35  import com.eviware.soapui.settings.HttpSettings;
36  import com.eviware.soapui.settings.SecuritySettings;
37  import com.eviware.soapui.settings.UISettings;
38  import com.eviware.soapui.settings.WSISettings;
39  import com.eviware.soapui.settings.WsaSettings;
40  import com.eviware.soapui.settings.WsdlSettings;
41  import com.eviware.soapui.support.ClasspathHacker;
42  import com.eviware.soapui.support.StringUtils;
43  import com.eviware.soapui.support.action.SoapUIActionRegistry;
44  import com.eviware.soapui.support.listener.SoapUIListenerRegistry;
45  import com.eviware.soapui.support.types.StringList;
46  
47  /***
48   * Initializes core objects. Transform to a Spring "ApplicationContext"?
49   * 
50   * @author ole.matzura
51   */
52  
53  public class DefaultSoapUICore implements SoapUICore
54  {
55  	public static Logger log;
56  
57  	private boolean logIsInitialized;
58  	private String root;
59  	protected SoapuiSettingsDocumentConfig settingsDocument;
60  	private MockEngine mockEngine;
61  	private XmlBeansSettingsImpl settings;
62  	private SoapUIListenerRegistry listenerRegistry;
63  	private SoapUIActionRegistry actionRegistry;
64  
65  	private String settingsFile;
66  
67  	private String password;
68  
69  	protected boolean initialImport;
70  
71  	public boolean getInitialImport()
72  	{
73  		return initialImport;
74  	}
75  
76  	public void setInitialImport( boolean initialImport )
77  	{
78  		this.initialImport = initialImport;
79  	}
80  
81  	public static DefaultSoapUICore createDefault()
82  	{
83  		return new DefaultSoapUICore( null, DEFAULT_SETTINGS_FILE );
84  	}
85  
86  	public DefaultSoapUICore()
87  	{
88  	}
89  
90  	/*
91  	 * this method is added for enabling settings password (like in core) all the
92  	 * way down in hierarchy boolean setingPassword is a dummy parameter, because
93  	 * the constructor with only one string parameter already existed
94  	 */
95  	public DefaultSoapUICore( boolean settingPassword, String soapUISettingsPassword )
96  	{
97  		this.password = soapUISettingsPassword;
98  	}
99  
100 	public DefaultSoapUICore( String root )
101 	{
102 		this.root = root;
103 	}
104 
105 	public DefaultSoapUICore( String root, String settingsFile )
106 	{
107 		this( root );
108 		init( settingsFile );
109 	}
110 
111 	public DefaultSoapUICore( String root, String settingsFile, String password )
112 	{
113 		this( root );
114 		this.password = password;
115 		init( settingsFile );
116 	}
117 
118 	public void init( String settingsFile )
119 	{
120 		initLog();
121 
122 		SoapUI.setSoapUICore( this );
123 
124 		loadExternalLibraries();
125 		initSettings( settingsFile == null ? DEFAULT_SETTINGS_FILE : settingsFile );
126 
127 		initCoreComponents();
128 		initExtensions( getExtensionClassLoader() );
129 
130 		SoapVersion.Soap11.equals( SoapVersion.Soap12 );
131 
132 	}
133 
134 	protected void initExtensions( ClassLoader extensionClassLoader )
135 	{
136 		String extDir = System.getProperty( "soapui.ext.listeners" );
137 		addExternalListeners( extDir != null ? extDir : root == null ? "listeners" : root + File.separatorChar
138 				+ "listeners", extensionClassLoader );
139 	}
140 
141 	protected ClassLoader getExtensionClassLoader()
142 	{
143 		return SoapUI.class.getClassLoader();
144 	}
145 
146 	protected void initCoreComponents()
147 	{
148 	}
149 
150 	public String getRoot()
151 	{
152 		if( root == null || root.length() == 0 )
153 			root = System.getProperty( "soapui.home", new File( "." ).getAbsolutePath() );
154 		return root;
155 	}
156 
157 	protected Settings initSettings( String fileName )
158 	{
159 		// TODO Why try to load settings from current directory before using root?
160 		// This caused a bug in Eclipse:
161 		// https://sourceforge.net/tracker/?func=detail&atid=737763&aid=2620284&group_id=136013
162 		File settingsFile = new File( fileName ).exists() ? new File( fileName ) : null;
163 
164 		try
165 		{
166 			if( settingsFile == null )
167 			{
168 				settingsFile = new File( new File( getRoot() ), DEFAULT_SETTINGS_FILE );
169 				if( !settingsFile.exists() )
170 				{
171 					settingsFile = new File( new File( System.getProperty( "user.home", "." ) ), DEFAULT_SETTINGS_FILE );
172 				}
173 			}
174 			else
175 			{
176 				settingsFile = new File( fileName );
177 			}
178 			if( !settingsFile.exists() )
179 			{
180 				if( settingsDocument == null )
181 				{
182 					log.info( "Creating new settings at [" + settingsFile.getAbsolutePath() + "]" );
183 					settingsDocument = SoapuiSettingsDocumentConfig.Factory.newInstance();
184 					setInitialImport( true );
185 				}
186 			}
187 			else
188 			{
189 				settingsDocument = SoapuiSettingsDocumentConfig.Factory.parse( settingsFile );
190 
191 				byte[] encryptedContent = settingsDocument.getSoapuiSettings().getEncryptedContent();
192 				if( encryptedContent != null )
193 				{
194 					char[] password = null;
195 					if( this.password == null )
196 					{
197 						// swing element -!! uh!
198 						JPasswordField passwordField = new JPasswordField();
199 						JLabel qLabel = new JLabel( "Password" );
200 						JOptionPane.showConfirmDialog( null, new Object[] { qLabel, passwordField }, "Global Settings",
201 								JOptionPane.OK_CANCEL_OPTION );
202 						password = passwordField.getPassword();
203 					}
204 					else
205 					{
206 						password = this.password.toCharArray();
207 					}
208 
209 					byte[] data = OpenSSL.decrypt( "des3", password, encryptedContent );
210 					try
211 					{
212 						settingsDocument = SoapuiSettingsDocumentConfig.Factory.parse( new String( data, "UTF-8" ) );
213 					}
214 					catch( Exception e )
215 					{
216 						log.warn( "Wrong password." );
217 						JOptionPane.showMessageDialog( null, "Wrong password, creating backup settings file [ "
218 								+ settingsFile.getAbsolutePath() + ".bak.xml. ]\nSwitch to default settings.",
219 								"Error - Wrong Password", JOptionPane.ERROR_MESSAGE );
220 						settingsDocument.save( new File( settingsFile.getAbsolutePath() + ".bak.xml" ) );
221 						throw e;
222 					}
223 				}
224 
225 				log.info( "initialized soapui-settings from [" + settingsFile.getAbsolutePath() + "]" );
226 			}
227 		}
228 		catch( Exception e )
229 		{
230 			log.warn( "Failed to load settings from [" + e.getMessage() + "], creating new" );
231 			settingsDocument = SoapuiSettingsDocumentConfig.Factory.newInstance();
232 		}
233 
234 		if( settingsDocument.getSoapuiSettings() == null )
235 		{
236 			settingsDocument.addNewSoapuiSettings();
237 			settings = new XmlBeansSettingsImpl( null, null, settingsDocument.getSoapuiSettings() );
238 
239 			initDefaultSettings( settings );
240 		}
241 		else
242 		{
243 			settings = new XmlBeansSettingsImpl( null, null, settingsDocument.getSoapuiSettings() );
244 		}
245 
246 		this.settingsFile = settingsFile.getAbsolutePath();
247 
248 		if( !settings.isSet( WsdlSettings.EXCLUDED_TYPES ) )
249 		{
250 			StringList list = new StringList();
251 			list.add( "schema@http://www.w3.org/2001/XMLSchema" );
252 			settings.setString( WsdlSettings.EXCLUDED_TYPES, list.toXml() );
253 		}
254 
255 		if( !settings.isSet( WsdlSettings.NAME_WITH_BINDING ) )
256 		{
257 			settings.setBoolean( WsdlSettings.NAME_WITH_BINDING, true );
258 		}
259 
260 		if( !settings.isSet( HttpSettings.MAX_CONNECTIONS_PER_HOST ) )
261 		{
262 			settings.setLong( HttpSettings.MAX_CONNECTIONS_PER_HOST, 500 );
263 		}
264 
265 		if( !settings.isSet( HttpSettings.HTTP_VERSION ) )
266 		{
267 			settings.setString( HttpSettings.HTTP_VERSION, HttpSettings.HTTP_VERSION_1_1 );
268 		}
269 
270 		if( !settings.isSet( HttpSettings.MAX_TOTAL_CONNECTIONS ) )
271 		{
272 			settings.setLong( HttpSettings.MAX_TOTAL_CONNECTIONS, 2000 );
273 		}
274 
275 		if( !settings.isSet( HttpSettings.RESPONSE_COMPRESSION ) )
276 		{
277 			settings.setBoolean( HttpSettings.RESPONSE_COMPRESSION, true );
278 		}
279 
280 		if( !settings.isSet( HttpSettings.LEAVE_MOCKENGINE ) )
281 		{
282 			settings.setBoolean( HttpSettings.LEAVE_MOCKENGINE, true );
283 		}
284 
285 		if( !settings.isSet( UISettings.AUTO_SAVE_PROJECTS_ON_EXIT ) )
286 		{
287 			settings.setBoolean( UISettings.AUTO_SAVE_PROJECTS_ON_EXIT, true );
288 		}
289 
290 		if( !settings.isSet( UISettings.SHOW_DESCRIPTIONS ) )
291 		{
292 			settings.setBoolean( UISettings.SHOW_DESCRIPTIONS, true );
293 		}
294 
295 		if( !settings.isSet( WsaSettings.USE_DEFAULT_RELATES_TO ) )
296 		{
297 			settings.setBoolean( WsaSettings.USE_DEFAULT_RELATES_TO, true );
298 		}
299 
300 		if( !settings.isSet( WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE ) )
301 		{
302 			settings.setBoolean( WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE, true );
303 		}
304 
305 		if( !settings.isSet( UISettings.SHOW_STARTUP_PAGE ) )
306 		{
307 			settings.setBoolean( UISettings.SHOW_STARTUP_PAGE, true );
308 		}
309 
310 	        if( settings.getString( HttpSettings.HTTP_VERSION, HttpSettings.HTTP_VERSION_1_1 ).equals(
311 				HttpSettings.HTTP_VERSION_0_9 ) )
312 		{
313 			settings.setString( HttpSettings.HTTP_VERSION, HttpSettings.HTTP_VERSION_1_1 );
314 		}
315 
316 		if( StringUtils.isNullOrEmpty( settings.getString( WSISettings.WSI_LOCATION, null ) ) )
317 		{
318 			String wsiDir = System.getProperty( "wsi.dir", new File( "." ).getAbsolutePath() );
319 			settings.setString( WSISettings.WSI_LOCATION, wsiDir );
320 		}
321 		return settings;
322 	}
323 
324 	/*
325 	 * (non-Javadoc)
326 	 * 
327 	 * @see com.eviware.soapui.SoapUICore#importSettings(java.io.File)
328 	 */
329 	public void importSettings( File file ) throws Exception
330 	{
331 		if( file != null )
332 		{
333 			log.info( "Importing preferences from [" + file.getAbsolutePath() + "]" );
334 			initSettings( file.getAbsolutePath() );
335 		}
336 	}
337 
338 	/*
339 	 * (non-Javadoc)
340 	 * 
341 	 * @see com.eviware.soapui.SoapUICore#getSettings()
342 	 */
343 	public Settings getSettings()
344 	{
345 		if( settings == null )
346 		{
347 			initSettings( DEFAULT_SETTINGS_FILE );
348 		}
349 
350 		return settings;
351 	}
352 
353 	protected void initDefaultSettings( Settings settings2 )
354 	{
355 		settings.setBoolean( WsdlSettings.CACHE_WSDLS, true );
356 		settings.setBoolean( WsdlSettings.PRETTY_PRINT_RESPONSE_MESSAGES, true );
357 
358 		settings.setString( HttpSettings.HTTP_VERSION, HttpSettings.HTTP_VERSION_1_1 );
359 		settings.setBoolean( HttpSettings.RESPONSE_COMPRESSION, true );
360 		settings.setBoolean( HttpSettings.INCLUDE_REQUEST_IN_TIME_TAKEN, true );
361 		settings.setBoolean( HttpSettings.INCLUDE_RESPONSE_IN_TIME_TAKEN, true );
362 		settings.setBoolean( HttpSettings.LEAVE_MOCKENGINE, true );
363 
364 		settings.setString( UISettings.AUTO_SAVE_INTERVAL, "0" );
365 		settings.setBoolean( UISettings.SHOW_STARTUP_PAGE, true );
366 
367 		settings.setBoolean( WsaSettings.SOAP_ACTION_OVERRIDES_WSA_ACTION, false );
368 		settings.setBoolean( WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE, true );
369 		settings.setBoolean( WsaSettings.USE_DEFAULT_RELATES_TO, true );
370 		settings.setBoolean( WsaSettings.OVERRIDE_EXISTING_HEADERS, false );
371 		settings.setBoolean( WsaSettings.ENABLE_FOR_OPTIONAL, false );
372 	}
373 
374 	/*
375 	 * (non-Javadoc)
376 	 * 
377 	 * @see com.eviware.soapui.SoapUICore#saveSettings()
378 	 */
379 	public String saveSettings() throws Exception
380 	{
381 		if( settingsFile == null )
382 			settingsFile = DEFAULT_SETTINGS_FILE;
383 
384 		// Save settings to root or user.home
385 		File file = new File( new File( getRoot() ), DEFAULT_SETTINGS_FILE );
386 		if( !file.canWrite() )
387 		{
388 			file = new File( new File( System.getProperty( "user.home", "." ) ), DEFAULT_SETTINGS_FILE );
389 		}
390 
391 		SoapuiSettingsDocumentConfig settingsDocument = ( SoapuiSettingsDocumentConfig )this.settingsDocument.copy();
392 		String password = settings.getString( SecuritySettings.SHADOW_PASSWORD, null );
393 
394 		if( password != null && password.length() > 0 )
395 		{
396 			try
397 			{
398 				byte[] data = settingsDocument.xmlText().getBytes();
399 				byte[] encryptedData = OpenSSL.encrypt( "des3", password.toCharArray(), data );
400 				settingsDocument.setSoapuiSettings( null );
401 				settingsDocument.getSoapuiSettings().setEncryptedContent( encryptedData );
402 			}
403 			catch( UnsupportedEncodingException e )
404 			{
405 				log.error( "Encryption error", e );
406 			}
407 			catch( IOException e )
408 			{
409 				log.error( "Encryption error", e );
410 			}
411 			catch( GeneralSecurityException e )
412 			{
413 				log.error( "Encryption error", e );
414 			}
415 		}
416 
417 		settingsDocument.save( file );
418 		log.info( "Settings saved to [" + file.getAbsolutePath() + "]" );
419 		return file.getAbsolutePath();
420 	}
421 
422 	public String getSettingsFile()
423 	{
424 		return settingsFile;
425 	}
426 
427 	public void setSettingsFile( String settingsFile )
428 	{
429 		this.settingsFile = settingsFile;
430 	}
431 
432 	protected void initLog()
433 	{
434 		if( !logIsInitialized )
435 		{
436 			File log4jconfig = root == null ? new File( "soapui-log4j.xml" ) : new File( new File( getRoot() ),
437 					"soapui-log4j.xml" );
438 			if( log4jconfig.exists() )
439 			{
440 				System.out.println( "Configuring log4j from [" + log4jconfig.getAbsolutePath() + "]" );
441 				DOMConfigurator.configureAndWatch( log4jconfig.getAbsolutePath(), 5000 );
442 			}
443 			else
444 			{
445 				URL url = SoapUI.class.getResource( "/com/eviware/soapui/resources/conf/soapui-log4j.xml" );
446 				if( url != null )
447 				{
448 					DOMConfigurator.configure( url );
449 				}
450 				else
451 					System.err.println( "Missing soapui-log4j.xml configuration" );
452 			}
453 
454 			logIsInitialized = true;
455 
456 			log = Logger.getLogger( DefaultSoapUICore.class );
457 		}
458 	}
459 
460 	protected void loadExternalLibraries()
461 	{
462 		try
463 		{
464 			String extDir = System.getProperty( "soapui.ext.libraries" );
465 
466 			File dir = extDir != null ? new File( extDir ) : new File( new File( getRoot() ), "ext" );
467 
468 			if( dir.exists() && dir.isDirectory() )
469 			{
470 				File[] files = dir.listFiles();
471 				for( File file : files )
472 				{
473 					if( file.getName().toLowerCase().endsWith( ".jar" ) )
474 					{
475 						ClasspathHacker.addFile( file );
476 					}
477 				}
478 			}
479 			else
480 			{
481 				log.warn( "Missing folder [" + dir.getAbsolutePath() + "] for external libraries" );
482 			}
483 		}
484 		catch( Exception e )
485 		{
486 			log.error( e.toString() );
487 		}
488 	}
489 
490 	/*
491 	 * (non-Javadoc)
492 	 * 
493 	 * @see com.eviware.soapui.SoapUICore#getMockEngine()
494 	 */
495 	public MockEngine getMockEngine()
496 	{
497 		if( mockEngine == null )
498 			mockEngine = new MockEngine();
499 
500 		return mockEngine;
501 	}
502 
503 	/*
504 	 * (non-Javadoc)
505 	 * 
506 	 * @see com.eviware.soapui.SoapUICore#getListenerRegistry()
507 	 */
508 	public SoapUIListenerRegistry getListenerRegistry()
509 	{
510 		if( listenerRegistry == null )
511 			initListenerRegistry();
512 
513 		return listenerRegistry;
514 	}
515 
516 	protected void initListenerRegistry()
517 	{
518 		listenerRegistry = new SoapUIListenerRegistry( null );
519 	}
520 
521 	/*
522 	 * (non-Javadoc)
523 	 * 
524 	 * @see com.eviware.soapui.SoapUICore#getActionRegistry()
525 	 */
526 	public SoapUIActionRegistry getActionRegistry()
527 	{
528 		if( actionRegistry == null )
529 			actionRegistry = initActionRegistry();
530 
531 		return actionRegistry;
532 	}
533 
534 	protected SoapUIActionRegistry initActionRegistry()
535 	{
536 		return new SoapUIActionRegistry( DefaultSoapUICore.class
537 				.getResourceAsStream( "/com/eviware/soapui/resources/conf/soapui-actions.xml" ) );
538 	}
539 
540 	protected void addExternalListeners( String folder, ClassLoader classLoader )
541 	{
542 		File[] actionFiles = new File( folder ).listFiles();
543 		if( actionFiles != null )
544 		{
545 			for( File actionFile : actionFiles )
546 			{
547 				if( actionFile.isDirectory() )
548 				{
549 					addExternalListeners( actionFile.getAbsolutePath(), classLoader );
550 					continue;
551 				}
552 
553 				if( !actionFile.getName().toLowerCase().endsWith( "-listeners.xml" ) )
554 					continue;
555 
556 				try
557 				{
558 					log.info( "Adding listeners from [" + actionFile.getAbsolutePath() + "]" );
559 
560 					SoapUI.getListenerRegistry().addConfig( new FileInputStream( actionFile ), classLoader );
561 				}
562 				catch( Exception e )
563 				{
564 					SoapUI.logError( e );
565 				}
566 			}
567 		}
568 	}
569 }