View Javadoc

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