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.getString( HttpSettings.HTTP_VERSION, HttpSettings.HTTP_VERSION_1_1 ).equals(
256 				HttpSettings.HTTP_VERSION_0_9 ) )
257 		{
258 			settings.setString( HttpSettings.HTTP_VERSION, HttpSettings.HTTP_VERSION_1_1 );
259 		}
260 
261 		setIfNotSet( WsdlSettings.NAME_WITH_BINDING, true );
262 		setIfNotSet( WsdlSettings.NAME_WITH_BINDING, 500 );
263 		setIfNotSet( HttpSettings.HTTP_VERSION, HttpSettings.HTTP_VERSION_1_1 );
264 		setIfNotSet( HttpSettings.MAX_TOTAL_CONNECTIONS, 2000 );
265 		setIfNotSet( HttpSettings.RESPONSE_COMPRESSION, true );
266 		setIfNotSet( HttpSettings.LEAVE_MOCKENGINE, true );
267 		setIfNotSet( UISettings.AUTO_SAVE_PROJECTS_ON_EXIT, true );
268 		setIfNotSet( UISettings.SHOW_DESCRIPTIONS, true );
269 		setIfNotSet( WsdlSettings.XML_GENERATION_ALWAYS_INCLUDE_OPTIONAL_ELEMENTS, true );
270 		setIfNotSet( WsaSettings.USE_DEFAULT_RELATES_TO, true );
271 		setIfNotSet( WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE, true );
272 		setIfNotSet( UISettings.SHOW_STARTUP_PAGE, true );
273 		setIfNotSet( UISettings.GC_INTERVAL, "60" );
274 		setIfNotSet( WsdlSettings.CACHE_WSDLS, true );
275 		setIfNotSet( WsdlSettings.PRETTY_PRINT_RESPONSE_MESSAGES, true );
276 		setIfNotSet( HttpSettings.RESPONSE_COMPRESSION, true );
277 		setIfNotSet( HttpSettings.INCLUDE_REQUEST_IN_TIME_TAKEN, true );
278 		setIfNotSet( HttpSettings.INCLUDE_RESPONSE_IN_TIME_TAKEN, true );
279 		setIfNotSet( HttpSettings.LEAVE_MOCKENGINE, true );
280 		setIfNotSet( UISettings.AUTO_SAVE_INTERVAL, "0" );
281 		setIfNotSet( UISettings.GC_INTERVAL, "60" );
282 		setIfNotSet( UISettings.SHOW_STARTUP_PAGE, true );
283 		setIfNotSet( WsaSettings.SOAP_ACTION_OVERRIDES_WSA_ACTION, false );
284 		setIfNotSet( WsaSettings.USE_DEFAULT_RELATIONSHIP_TYPE, true );
285 		setIfNotSet( WsaSettings.USE_DEFAULT_RELATES_TO, true );
286 		setIfNotSet( WsaSettings.OVERRIDE_EXISTING_HEADERS, false );
287 		setIfNotSet( WsaSettings.ENABLE_FOR_OPTIONAL, false );
288 
289 		if( StringUtils.isNullOrEmpty( settings.getString( WSISettings.WSI_LOCATION, null ) ) )
290 		{
291 			String wsiDir = System.getProperty( "wsi.dir", new File( "." ).getAbsolutePath() );
292 			settings.setString( WSISettings.WSI_LOCATION, wsiDir );
293 		}
294 		
295 		return settings;
296 	}
297 
298 	private void setIfNotSet( String id, boolean value )
299 	{
300 		if( !settings.isSet( id ) )
301 			settings.setBoolean( id, true );
302 	}
303 
304 	private void setIfNotSet( String id, String value )
305 	{
306 		if( !settings.isSet( id ) )
307 			settings.setString( id, value );
308 	}
309 
310 	private void setIfNotSet( String id, long value )
311 	{
312 		if( !settings.isSet( id ) )
313 			settings.setLong( id, value );
314 	}
315 
316 	/*
317 	 * (non-Javadoc)
318 	 * 
319 	 * @see com.eviware.soapui.SoapUICore#importSettings(java.io.File)
320 	 */
321 	public void importSettings( File file ) throws Exception
322 	{
323 		if( file != null )
324 		{
325 			log.info( "Importing preferences from [" + file.getAbsolutePath() + "]" );
326 			initSettings( file.getAbsolutePath() );
327 		}
328 	}
329 
330 	/*
331 	 * (non-Javadoc)
332 	 * 
333 	 * @see com.eviware.soapui.SoapUICore#getSettings()
334 	 */
335 	public Settings getSettings()
336 	{
337 		if( settings == null )
338 		{
339 			initSettings( DEFAULT_SETTINGS_FILE );
340 		}
341 
342 		return settings;
343 	}
344 
345 	protected void initDefaultSettings( Settings settings2 )
346 	{
347 
348 	}
349 
350 	/*
351 	 * (non-Javadoc)
352 	 * 
353 	 * @see com.eviware.soapui.SoapUICore#saveSettings()
354 	 */
355 	public String saveSettings() throws Exception
356 	{
357 		if( settingsFile == null )
358 			settingsFile = DEFAULT_SETTINGS_FILE;
359 
360 		// Save settings to root or user.home
361 		File file = new File( new File( getRoot() ), DEFAULT_SETTINGS_FILE );
362 		if( !file.canWrite() )
363 		{
364 			file = new File( new File( System.getProperty( "user.home", "." ) ), DEFAULT_SETTINGS_FILE );
365 		}
366 
367 		SoapuiSettingsDocumentConfig settingsDocument = ( SoapuiSettingsDocumentConfig )this.settingsDocument.copy();
368 		String password = settings.getString( SecuritySettings.SHADOW_PASSWORD, null );
369 
370 		if( password != null && password.length() > 0 )
371 		{
372 			try
373 			{
374 				byte[] data = settingsDocument.xmlText().getBytes();
375 				byte[] encryptedData = OpenSSL.encrypt( "des3", password.toCharArray(), data );
376 				settingsDocument.setSoapuiSettings( null );
377 				settingsDocument.getSoapuiSettings().setEncryptedContent( encryptedData );
378 			}
379 			catch( UnsupportedEncodingException e )
380 			{
381 				log.error( "Encryption error", e );
382 			}
383 			catch( IOException e )
384 			{
385 				log.error( "Encryption error", e );
386 			}
387 			catch( GeneralSecurityException e )
388 			{
389 				log.error( "Encryption error", e );
390 			}
391 		}
392 
393 		settingsDocument.save( file );
394 		log.info( "Settings saved to [" + file.getAbsolutePath() + "]" );
395 		return file.getAbsolutePath();
396 	}
397 
398 	public String getSettingsFile()
399 	{
400 		return settingsFile;
401 	}
402 
403 	public void setSettingsFile( String settingsFile )
404 	{
405 		this.settingsFile = settingsFile;
406 	}
407 
408 	protected void initLog()
409 	{
410 		if( !logIsInitialized )
411 		{
412 			File log4jconfig = root == null ? new File( "soapui-log4j.xml" ) : new File( new File( getRoot() ),
413 					"soapui-log4j.xml" );
414 			if( log4jconfig.exists() )
415 			{
416 				System.out.println( "Configuring log4j from [" + log4jconfig.getAbsolutePath() + "]" );
417 				DOMConfigurator.configureAndWatch( log4jconfig.getAbsolutePath(), 5000 );
418 			}
419 			else
420 			{
421 				URL url = SoapUI.class.getResource( "/com/eviware/soapui/resources/conf/soapui-log4j.xml" );
422 				if( url != null )
423 				{
424 					DOMConfigurator.configure( url );
425 				}
426 				else
427 					System.err.println( "Missing soapui-log4j.xml configuration" );
428 			}
429 
430 			logIsInitialized = true;
431 
432 			log = Logger.getLogger( DefaultSoapUICore.class );
433 		}
434 	}
435 
436 	protected void loadExternalLibraries()
437 	{
438 		try
439 		{
440 			String extDir = System.getProperty( "soapui.ext.libraries" );
441 
442 			File dir = extDir != null ? new File( extDir ) : new File( new File( getRoot() ), "ext" );
443 
444 			if( dir.exists() && dir.isDirectory() )
445 			{
446 				File[] files = dir.listFiles();
447 				for( File file : files )
448 				{
449 					if( file.getName().toLowerCase().endsWith( ".jar" ) )
450 					{
451 						ClasspathHacker.addFile( file );
452 					}
453 				}
454 			}
455 			else
456 			{
457 				log.warn( "Missing folder [" + dir.getAbsolutePath() + "] for external libraries" );
458 			}
459 		}
460 		catch( Exception e )
461 		{
462 			log.error( e.toString() );
463 		}
464 	}
465 
466 	/*
467 	 * (non-Javadoc)
468 	 * 
469 	 * @see com.eviware.soapui.SoapUICore#getMockEngine()
470 	 */
471 	public MockEngine getMockEngine()
472 	{
473 		if( mockEngine == null )
474 			mockEngine = new MockEngine();
475 
476 		return mockEngine;
477 	}
478 
479 	/*
480 	 * (non-Javadoc)
481 	 * 
482 	 * @see com.eviware.soapui.SoapUICore#getListenerRegistry()
483 	 */
484 	public SoapUIListenerRegistry getListenerRegistry()
485 	{
486 		if( listenerRegistry == null )
487 			initListenerRegistry();
488 
489 		return listenerRegistry;
490 	}
491 
492 	protected void initListenerRegistry()
493 	{
494 		listenerRegistry = new SoapUIListenerRegistry( null );
495 	}
496 
497 	/*
498 	 * (non-Javadoc)
499 	 * 
500 	 * @see com.eviware.soapui.SoapUICore#getActionRegistry()
501 	 */
502 	public SoapUIActionRegistry getActionRegistry()
503 	{
504 		if( actionRegistry == null )
505 			actionRegistry = initActionRegistry();
506 
507 		return actionRegistry;
508 	}
509 
510 	protected SoapUIActionRegistry initActionRegistry()
511 	{
512 		return new SoapUIActionRegistry( DefaultSoapUICore.class
513 				.getResourceAsStream( "/com/eviware/soapui/resources/conf/soapui-actions.xml" ) );
514 	}
515 
516 	protected void addExternalListeners( String folder, ClassLoader classLoader )
517 	{
518 		File[] actionFiles = new File( folder ).listFiles();
519 		if( actionFiles != null )
520 		{
521 			for( File actionFile : actionFiles )
522 			{
523 				if( actionFile.isDirectory() )
524 				{
525 					addExternalListeners( actionFile.getAbsolutePath(), classLoader );
526 					continue;
527 				}
528 
529 				if( !actionFile.getName().toLowerCase().endsWith( "-listeners.xml" ) )
530 					continue;
531 
532 				try
533 				{
534 					log.info( "Adding listeners from [" + actionFile.getAbsolutePath() + "]" );
535 
536 					SoapUI.getListenerRegistry().addConfig( new FileInputStream( actionFile ), classLoader );
537 				}
538 				catch( Exception e )
539 				{
540 					SoapUI.logError( e );
541 				}
542 			}
543 		}
544 	}
545 }