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.impl.wsdl;
14  
15  import java.beans.PropertyChangeEvent;
16  import java.beans.PropertyChangeListener;
17  import java.beans.PropertyChangeSupport;
18  import java.io.BufferedReader;
19  import java.io.BufferedWriter;
20  import java.io.File;
21  import java.io.FileNotFoundException;
22  import java.io.FileOutputStream;
23  import java.io.FileReader;
24  import java.io.FileWriter;
25  import java.io.IOException;
26  import java.net.MalformedURLException;
27  import java.net.URL;
28  import java.security.GeneralSecurityException;
29  import java.util.ArrayList;
30  import java.util.Arrays;
31  import java.util.HashMap;
32  import java.util.HashSet;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Set;
36  
37  import javax.swing.ImageIcon;
38  import javax.xml.namespace.QName;
39  
40  import org.apache.commons.ssl.OpenSSL;
41  import org.apache.log4j.Logger;
42  import org.apache.xmlbeans.XmlError;
43  import org.apache.xmlbeans.XmlException;
44  import org.apache.xmlbeans.XmlObject;
45  import org.apache.xmlbeans.XmlOptions;
46  
47  import com.eviware.soapui.SoapUI;
48  import com.eviware.soapui.config.InterfaceConfig;
49  import com.eviware.soapui.config.MockServiceConfig;
50  import com.eviware.soapui.config.MockServiceDocumentConfig;
51  import com.eviware.soapui.config.ProjectConfig;
52  import com.eviware.soapui.config.SoapuiProjectDocumentConfig;
53  import com.eviware.soapui.config.TestSuiteConfig;
54  import com.eviware.soapui.config.TestSuiteDocumentConfig;
55  import com.eviware.soapui.config.TestSuiteRunTypesConfig;
56  import com.eviware.soapui.config.TestSuiteRunTypesConfig.Enum;
57  import com.eviware.soapui.impl.WorkspaceImpl;
58  import com.eviware.soapui.impl.WsdlInterfaceFactory;
59  import com.eviware.soapui.impl.rest.support.RestRequestConverter.RestConversionException;
60  import com.eviware.soapui.impl.settings.XmlBeansSettingsImpl;
61  import com.eviware.soapui.impl.support.AbstractInterface;
62  import com.eviware.soapui.impl.wsdl.endpoint.DefaultEndpointStrategy;
63  import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
64  import com.eviware.soapui.impl.wsdl.support.PathUtils;
65  import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
66  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlLoader;
67  import com.eviware.soapui.impl.wsdl.support.wss.DefaultWssContainer;
68  import com.eviware.soapui.impl.wsdl.testcase.WsdlProjectRunner;
69  import com.eviware.soapui.model.ModelItem;
70  import com.eviware.soapui.model.iface.Interface;
71  import com.eviware.soapui.model.mock.MockService;
72  import com.eviware.soapui.model.project.EndpointStrategy;
73  import com.eviware.soapui.model.project.Project;
74  import com.eviware.soapui.model.project.ProjectListener;
75  import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
76  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
77  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
78  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
79  import com.eviware.soapui.model.settings.Settings;
80  import com.eviware.soapui.model.support.ModelSupport;
81  import com.eviware.soapui.model.testsuite.ProjectRunContext;
82  import com.eviware.soapui.model.testsuite.ProjectRunListener;
83  import com.eviware.soapui.model.testsuite.ProjectRunner;
84  import com.eviware.soapui.model.testsuite.TestRunnable;
85  import com.eviware.soapui.model.testsuite.TestSuite;
86  import com.eviware.soapui.model.testsuite.TestSuite.TestSuiteRunType;
87  import com.eviware.soapui.settings.ProjectSettings;
88  import com.eviware.soapui.settings.UISettings;
89  import com.eviware.soapui.settings.WsdlSettings;
90  import com.eviware.soapui.support.SoapUIException;
91  import com.eviware.soapui.support.StringUtils;
92  import com.eviware.soapui.support.Tools;
93  import com.eviware.soapui.support.UISupport;
94  import com.eviware.soapui.support.resolver.ResolveContext;
95  import com.eviware.soapui.support.resolver.ResolveDialog;
96  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
97  import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
98  import com.eviware.soapui.support.types.StringToObjectMap;
99  
100 /***
101  * WSDL project implementation
102  * 
103  * @author Ole.Matzura
104  */
105 
106 public class WsdlProject extends AbstractTestPropertyHolderWsdlModelItem<ProjectConfig> implements Project,
107 		PropertyExpansionContainer, PropertyChangeListener, TestRunnable
108 {
109 	public final static String AFTER_LOAD_SCRIPT_PROPERTY = WsdlProject.class.getName() + "@setupScript";
110 	public final static String BEFORE_SAVE_SCRIPT_PROPERTY = WsdlProject.class.getName() + "@tearDownScript";
111 	public final static String RESOURCE_ROOT_PROPERTY = WsdlProject.class.getName() + "@resourceRoot";
112 
113 	private WorkspaceImpl workspace;
114 	protected String path;
115 	protected List<AbstractInterface<?>> interfaces = new ArrayList<AbstractInterface<?>>();
116 	protected List<WsdlTestSuite> testSuites = new ArrayList<WsdlTestSuite>();
117 	protected List<WsdlMockService> mockServices = new ArrayList<WsdlMockService>();
118 	private Set<ProjectListener> projectListeners = new HashSet<ProjectListener>();
119 	protected SoapuiProjectDocumentConfig projectDocument;
120 	private ImageIcon disabledIcon;
121 	private ImageIcon closedIcon;
122 	private ImageIcon remoteIcon;
123 	private ImageIcon openEncyptedIcon;
124 	protected EndpointStrategy endpointStrategy = new DefaultEndpointStrategy();
125 	protected long lastModified;
126 	private boolean remote;
127 	private boolean open = true;
128 	private boolean disabled;
129 
130 	private SoapUIScriptEngine afterLoadScriptEngine;
131 	private SoapUIScriptEngine beforeSaveScriptEngine;
132 	private PropertyExpansionContext context = new DefaultPropertyExpansionContext( this );
133 	protected DefaultWssContainer wssContainer;
134 	private String projectPassword = null;
135 
136 	/*
137 	 * 3 state flag: 1. 0 - project not encrypted 2. 1 - encrypted , good
138 	 * password, means that it could be successfully decrypted 3. -1 - encrypted,
139 	 * but with bad password or no password.
140 	 */
141 
142 	protected int encrypted;
143 	private ImageIcon closedEncyptedIcon;
144 	protected final PropertyChangeSupport pcs;
145 	private SoapUIScriptEngine afterRunScriptEngine;
146 	private SoapUIScriptEngine beforeRunScriptEngine;
147 	private Set<ProjectRunListener> runListeners = new HashSet<ProjectRunListener>();
148 
149 	protected final static Logger log = Logger.getLogger( WsdlProject.class );
150 
151 	public WsdlProject() throws XmlException, IOException, SoapUIException
152 	{
153 		this( ( WorkspaceImpl )null );
154 	}
155 
156 	public WsdlProject( String path ) throws XmlException, IOException, SoapUIException
157 	{
158 		this( path, ( WorkspaceImpl )null );
159 	}
160 
161 	public WsdlProject( String projectFile, String projectPassword )
162 	{
163 		this( projectFile, null, true, true, null, projectPassword );
164 	}
165 
166 	public WsdlProject( WorkspaceImpl workspace )
167 	{
168 		this( null, workspace, true );
169 	}
170 
171 	public WsdlProject( String path, WorkspaceImpl workspace )
172 	{
173 		this( path, workspace, true );
174 	}
175 
176 	public WsdlProject( String path, WorkspaceImpl workspace, boolean create )
177 	{
178 		this( path, workspace, create, true, null, null );
179 	}
180 
181 	public WsdlProject( String path, WorkspaceImpl workspace, boolean create, boolean open, String tempName,
182 			String projectPassword )
183 	{
184 		super( null, workspace, "/project.gif" );
185 
186 		pcs = new PropertyChangeSupport( this );
187 
188 		this.workspace = workspace;
189 		this.path = path;
190 		this.projectPassword = projectPassword;
191 
192 		for( ProjectListener listener : SoapUI.getListenerRegistry().getListeners( ProjectListener.class ) )
193 		{
194 			addProjectListener( listener );
195 		}
196 
197 		for( ProjectRunListener listener : SoapUI.getListenerRegistry().getListeners( ProjectRunListener.class ) )
198 		{
199 			addProjectRunListener( listener );
200 		}
201 
202 		try
203 		{
204 			if( path != null && open )
205 			{
206 				File file = new File( path.trim() );
207 				if( file.exists() )
208 				{
209 					try
210 					{
211 						loadProject( new URL( "file:" + file.getAbsolutePath() ) );
212 						lastModified = file.lastModified();
213 					}
214 					catch( MalformedURLException e )
215 					{
216 						SoapUI.logError( e );
217 						disabled = true;
218 					}
219 				}
220 				else
221 				{
222 					try
223 					{
224 						if( !PathUtils.isHttpPath( path ) )
225 							SoapUI.log.info( "File [" + file.getAbsolutePath() + "] does not exist, trying URL instead" );
226 
227 						remote = true;
228 						loadProject( new URL( path ) );
229 					}
230 					catch( MalformedURLException e )
231 					{
232 						SoapUI.logError( e );
233 						disabled = true;
234 					}
235 				}
236 			}
237 		}
238 		catch( SoapUIException e )
239 		{
240 			SoapUI.logError( e );
241 			disabled = true;
242 		}
243 		finally
244 		{
245 			closedIcon = UISupport.createImageIcon( "/closedProject.gif" );
246 			remoteIcon = UISupport.createImageIcon( "/remoteProject.gif" );
247 			disabledIcon = UISupport.createImageIcon( "/disabledProject.gif" );
248 			openEncyptedIcon = UISupport.createImageIcon( "/openEncryptedProject.gif" );
249 			closedEncyptedIcon = UISupport.createImageIcon( "/closedEncryptedProject.gif" );
250 
251 			this.open = open && !disabled && ( this.encrypted != -1 );
252 
253 			if( projectDocument == null )
254 			{
255 				projectDocument = SoapuiProjectDocumentConfig.Factory.newInstance();
256 				setConfig( projectDocument.addNewSoapuiProject() );
257 				if( tempName != null || path != null )
258 					getConfig().setName( StringUtils.isNullOrEmpty( tempName ) ? getNameFromPath() : tempName );
259 
260 				setPropertiesConfig( getConfig().addNewProperties() );
261 				wssContainer = new DefaultWssContainer( this, getConfig().addNewWssContainer() );
262 				// setResourceRoot("${projectDir}");
263 			}
264 
265 			if( getConfig() != null )
266 			{
267 				endpointStrategy.init( this );
268 			}
269 			if( getSettings() != null )
270 			{
271 				setProjectRoot( path );
272 			}
273 
274 			addPropertyChangeListener( this );
275 		}
276 	}
277 
278 	protected PropertyChangeSupport getPropertyChangeSupport()
279 	{
280 		return pcs;
281 	}
282 
283 	public boolean isRemote()
284 	{
285 		return remote;
286 	}
287 
288 	public void loadProject( URL file ) throws SoapUIException
289 	{
290 		try
291 		{
292 			UISupport.setHourglassCursor();
293 
294 			UrlWsdlLoader loader = new UrlWsdlLoader( file.toString(), this );
295 			loader.setUseWorker( false );
296 			projectDocument = SoapuiProjectDocumentConfig.Factory.parse( loader.load() );
297 
298 			// see if there is encoded data
299 			this.encrypted = checkForEncodedData( projectDocument.getSoapuiProject() );
300 
301 			setConfig( projectDocument.getSoapuiProject() );
302 
303 			// removed cached definitions if caching is disabled
304 			if( !getSettings().getBoolean( WsdlSettings.CACHE_WSDLS ) )
305 			{
306 				removeDefinitionCaches( projectDocument );
307 			}
308 
309 			log.info( "Loaded project from [" + file.toString() + "]" );
310 
311 			try
312 			{
313 				int majorVersion = Integer
314 						.parseInt( projectDocument.getSoapuiProject().getSoapuiVersion().split( "//." )[0] );
315 				if( majorVersion > Integer.parseInt( SoapUI.SOAPUI_VERSION.split( "//." )[0] ) )
316 					log.warn( "Project '" + projectDocument.getSoapuiProject().getName() + "' is from a newer version ("
317 							+ projectDocument.getSoapuiProject().getSoapuiVersion() + ") of soapUI than this ("
318 							+ SoapUI.SOAPUI_VERSION + ") and parts of it may be incompatible or incorrect. "
319 							+ "Saving this project with this version of soapUI may cause it to function differently." );
320 			}
321 			catch( Exception e )
322 			{
323 			}
324 
325 			List<InterfaceConfig> interfaceConfigs = getConfig().getInterfaceList();
326 			for( InterfaceConfig config : interfaceConfigs )
327 			{
328 				AbstractInterface<?> iface = InterfaceFactoryRegistry.build( this, config );
329 				interfaces.add( iface );
330 			}
331 
332 			List<TestSuiteConfig> testSuiteConfigs = getConfig().getTestSuiteList();
333 			for( TestSuiteConfig config : testSuiteConfigs )
334 			{
335 				testSuites.add( buildTestSuite( config ) );
336 			}
337 
338 			List<MockServiceConfig> mockServiceConfigs = getConfig().getMockServiceList();
339 			for( MockServiceConfig config : mockServiceConfigs )
340 			{
341 				mockServices.add( new WsdlMockService( this, config ) );
342 			}
343 
344 			if( !getConfig().isSetWssContainer() )
345 				getConfig().addNewWssContainer();
346 
347 			wssContainer = new DefaultWssContainer( this, getConfig().getWssContainer() );
348 
349 			endpointStrategy.init( this );
350 
351 			if( !getConfig().isSetProperties() )
352 				getConfig().addNewProperties();
353 
354 			if( !getConfig().isSetAbortOnError() )
355 				getConfig().setAbortOnError( false );
356 
357 			// if( !getConfig().isSetFailOnErrors() )
358 			// getConfig().setFailOnErrors( true );
359 
360 			if( !getConfig().isSetRunType() )
361 				getConfig().setRunType( TestSuiteRunTypesConfig.SEQUENTIAL );
362 
363 			setPropertiesConfig( getConfig().getProperties() );
364 			afterLoad();
365 		}
366 		catch( Exception e )
367 		{
368 			if( e instanceof XmlException )
369 			{
370 				XmlException xe = ( XmlException )e;
371 				XmlError error = xe.getError();
372 				if( error != null )
373 					System.err.println( "Error at line " + error.getLine() + ", column " + error.getColumn() );
374 			}
375 
376 			if( e instanceof RestConversionException )
377 			{
378 				log.error( "Project file needs to be updated manually, please reload the project." );
379 				throw new SoapUIException( "Failed to load project from file [" + file.toString() + "]", e );
380 			}
381 
382 			e.printStackTrace();
383 			throw new SoapUIException( "Failed to load project from file [" + file.toString() + "]", e );
384 		}
385 		finally
386 		{
387 			UISupport.resetCursor();
388 		}
389 	}
390 
391 	protected WsdlTestSuite buildTestSuite( TestSuiteConfig config )
392 	{
393 		return new WsdlTestSuite( this, config );
394 	}
395 
396 	/***
397 	 * Decode encrypted data and restore user/pass
398 	 * 
399 	 * @param soapuiProject
400 	 * @return 0 - not encrypted, 1 - successfull decryption , -1 error while
401 	 *         decrypting, bad password, no password.
402 	 * @throws IOException
403 	 * @throws GeneralSecurityException
404 	 * @author robert nemet
405 	 */
406 	protected int checkForEncodedData( ProjectConfig soapuiProject ) throws IOException, GeneralSecurityException
407 	{
408 
409 		byte[] encryptedContent = soapuiProject.getEncryptedContent();
410 		char[] password = null;
411 
412 		// no encrypted data then go back
413 		if( encryptedContent == null || encryptedContent.length == 0 )
414 			return 0;
415 
416 		String projectPassword = null;
417 		if( workspace != null )
418 		{
419 			projectPassword = workspace.getProjectPassword( soapuiProject.getName() );
420 		}
421 		else
422 		{
423 			projectPassword = this.projectPassword;
424 		}
425 		if( projectPassword == null )
426 		{
427 			password = UISupport.promptPassword( "Enter Password:", soapuiProject.getName() );
428 		}
429 		else
430 		{
431 			password = projectPassword.toCharArray();
432 		}
433 		byte[] data = null;
434 		// no pass go back.
435 		if( password == null )
436 		{
437 			return -1;
438 		}
439 
440 		try
441 		{
442 			data = OpenSSL.decrypt( "des3", password, encryptedContent );
443 		}
444 		catch( Exception e )
445 		{
446 			e.printStackTrace();
447 			return -1;
448 		}
449 
450 		String decryptedData = new String( data, "UTF-8" );
451 
452 		if( decryptedData != null )
453 		{
454 			if( decryptedData.length() > 0 )
455 			{
456 				try
457 				{
458 					projectDocument.getSoapuiProject().set( XmlObject.Factory.parse( decryptedData ) );
459 				}
460 				catch( XmlException e )
461 				{
462 					UISupport.showErrorMessage( "Wrong password. Project need to be reloaded." );
463 					getWorkspace().clearProjectPassword( soapuiProject.getName() );
464 					return -1;
465 				}
466 			}
467 		}
468 		else
469 		{
470 			UISupport.showErrorMessage( "Wrong project password" );
471 			getWorkspace().clearProjectPassword( soapuiProject.getName() );
472 			return -1;
473 		}
474 		projectDocument.getSoapuiProject().setEncryptedContent( null );
475 		return 1;
476 	}
477 
478 	@Override
479 	public void afterLoad()
480 	{
481 		super.afterLoad();
482 
483 		try
484 		{
485 			ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
486 
487 			for( int c = 0; c < a.length; c++ )
488 			{
489 				a[c].afterLoad( this );
490 			}
491 
492 			runAfterLoadScript();
493 		}
494 		catch( Exception e )
495 		{
496 			SoapUI.logError( e );
497 		}
498 	}
499 
500 	protected void setProjectRoot( String path )
501 	{
502 		if( path != null && projectDocument != null )
503 		{
504 			int ix = path.lastIndexOf( File.separatorChar );
505 			if( ix > 0 )
506 				getSettings().setString( ProjectSettings.PROJECT_ROOT, path.substring( 0, ix ) );
507 		}
508 	}
509 
510 	public void setResourceRoot( String resourceRoot )
511 	{
512 		String old = getResourceRoot();
513 
514 		getConfig().setResourceRoot( resourceRoot );
515 		notifyPropertyChanged( RESOURCE_ROOT_PROPERTY, old, resourceRoot );
516 	}
517 
518 	public String getResourceRoot()
519 	{
520 		if( !getConfig().isSetResourceRoot() )
521 			getConfig().setResourceRoot( "" );
522 
523 		return getConfig().getResourceRoot();
524 	}
525 
526 	@Override
527 	public ImageIcon getIcon()
528 	{
529 		if( isDisabled() )
530 			return disabledIcon;
531 		else if( getEncrypted() != 0 )
532 		{
533 			if( isOpen() )
534 			{
535 				return openEncyptedIcon;
536 			}
537 			else
538 			{
539 				return closedEncyptedIcon;
540 			}
541 		}
542 		else if( !isOpen() )
543 			return closedIcon;
544 		else if( isRemote() )
545 			return remoteIcon;
546 		else
547 			return super.getIcon();
548 	}
549 
550 	private String getNameFromPath()
551 	{
552 		int ix = path.lastIndexOf( isRemote() ? '/' : File.separatorChar );
553 		String name = ix == -1 ? path : path.substring( ix + 1 );
554 		return name;
555 	}
556 
557 	@Override
558 	public String getDescription()
559 	{
560 		if( isOpen() )
561 			return super.getDescription();
562 
563 		String name = getName();
564 
565 		if( isDisabled() )
566 			name += " - disabled [" + getPath() + "]";
567 		else
568 			name += " - closed [" + getPath() + "]";
569 
570 		return name;
571 	}
572 
573 	public WorkspaceImpl getWorkspace()
574 	{
575 		return workspace;
576 	}
577 
578 	public AbstractInterface<?> getInterfaceAt( int index )
579 	{
580 		return interfaces.get( index );
581 	}
582 
583 	public AbstractInterface<?> getInterfaceByName( String interfaceName )
584 	{
585 		return ( AbstractInterface<?> )getWsdlModelItemByName( interfaces, interfaceName );
586 	}
587 
588 	public AbstractInterface<?> getInterfaceByTechnicalId( String technicalId )
589 	{
590 		for( int c = 0; c < getInterfaceCount(); c++ )
591 		{
592 			if( getInterfaceAt( c ).getTechnicalId().equals( technicalId ) )
593 				return getInterfaceAt( c );
594 		}
595 
596 		return null;
597 	}
598 
599 	public int getInterfaceCount()
600 	{
601 		return interfaces.size();
602 	}
603 
604 	public String getPath()
605 	{
606 		return path;
607 	}
608 
609 	public boolean save() throws IOException
610 	{
611 		return save( null );
612 	}
613 
614 	public boolean save( String folder ) throws IOException
615 	{
616 		if( !isOpen() || isDisabled() || isRemote() )
617 			return true;
618 
619 		if( path == null || isRemote() )
620 		{
621 			path = getName() + "-soapui-project.xml";
622 			if( folder != null )
623 			{
624 				path = folder + File.separatorChar + path;
625 			}
626 
627 			File file = null;
628 
629 			while( file == null
630 					|| ( file.exists() && !UISupport.confirm( "File [" + file.getName() + "] exists, overwrite?",
631 							"Overwrite File?" ) ) )
632 			{
633 				file = UISupport.getFileDialogs().saveAs( this, "Save project " + getName(), ".xml", "XML Files (*.xml)",
634 						new File( path ) );
635 				if( file == null )
636 					return false;
637 			}
638 
639 			path = file.getAbsolutePath();
640 		}
641 
642 		File projectFile = new File( path );
643 
644 		while( projectFile.exists() && !projectFile.canWrite() )
645 		{
646 			if( UISupport.confirm( "Project file [" + path + "] can not be written to, save to new file?", "Save Project" ) )
647 			{
648 				projectFile = UISupport.getFileDialogs().saveAs( this, "Save project " + getName(), ".xml",
649 						"XML Files (*.xml)", projectFile );
650 
651 				if( projectFile == null )
652 					return false;
653 
654 				path = projectFile.getAbsolutePath();
655 			}
656 			else
657 				return false;
658 		}
659 
660 		// check modified
661 		if( projectFile.exists() && lastModified != 0 && lastModified < projectFile.lastModified() )
662 		{
663 			if( !UISupport.confirm( "Project file for [" + getName() + "] has been modified externally, overwrite?",
664 					"Save Project" ) )
665 				return false;
666 		}
667 
668 		if( projectFile.exists() && getSettings().getBoolean( UISettings.CREATE_BACKUP ) )
669 		{
670 			createBackup( projectFile );
671 		}
672 
673 		return saveIn( projectFile );
674 	}
675 
676 	public boolean saveBackup() throws IOException
677 	{
678 		File projectFile;
679 		if( path == null || isRemote() )
680 		{
681 			projectFile = new File( getName() + "-soapui-project.xml" );
682 		}
683 		else
684 		{
685 			projectFile = new File( path );
686 		}
687 		File backupFile = getBackupFile( projectFile );
688 		return saveIn( backupFile );
689 	}
690 
691 	public boolean saveIn( File projectFile ) throws IOException
692 	{
693 		long size = 0;
694 
695 		beforeSave();
696 		// work with copy beacuse we do not want to change working project while
697 		// working with it
698 		// if user choose save project, save all etc.
699 		SoapuiProjectDocumentConfig projectDocument = ( SoapuiProjectDocumentConfig )this.projectDocument.copy();
700 
701 		// check for caching
702 		if( !getSettings().getBoolean( WsdlSettings.CACHE_WSDLS ) )
703 		{
704 			// no caching -> create copy and remove definition cachings
705 			removeDefinitionCaches( projectDocument );
706 		}
707 
708 		// remove project root
709 		XmlBeansSettingsImpl tempSettings = new XmlBeansSettingsImpl( this, null, projectDocument.getSoapuiProject()
710 				.getSettings() );
711 		tempSettings.clearSetting( ProjectSettings.PROJECT_ROOT );
712 
713 		// check for encryption
714 		String passwordForEncryption = getSettings().getString( ProjectSettings.SHADOW_PASSWORD, null );
715 
716 		// if it has encryptedContend that means it is not decrypted corectly( bad
717 		// password, etc ), so do not encrypt it again.
718 		if( projectDocument.getSoapuiProject().getEncryptedContent() == null )
719 		{
720 			if( passwordForEncryption != null )
721 			{
722 				if( passwordForEncryption.length() > 1 )
723 				{
724 					// we have password so do encryption
725 					try
726 					{
727 						String data = getConfig().xmlText();
728 						byte[] encrypted = OpenSSL.encrypt( "des3", passwordForEncryption.toCharArray(), data.getBytes() );
729 						projectDocument.getSoapuiProject().setEncryptedContent( encrypted );
730 						projectDocument.getSoapuiProject().setInterfaceArray( null );
731 						projectDocument.getSoapuiProject().setTestSuiteArray( null );
732 						projectDocument.getSoapuiProject().setMockServiceArray( null );
733 						projectDocument.getSoapuiProject().unsetSettings();
734 						projectDocument.getSoapuiProject().unsetProperties();
735 
736 					}
737 					catch( GeneralSecurityException e )
738 					{
739 						UISupport.showErrorMessage( "Encryption Error" );
740 					}
741 				}
742 				else
743 				{
744 					// no password no encryption.
745 					projectDocument.getSoapuiProject().setEncryptedContent( null );
746 				}
747 			}
748 		}
749 		// end of encryption.
750 
751 		XmlOptions options = new XmlOptions();
752 		if( SoapUI.getSettings().getBoolean( WsdlSettings.PRETTY_PRINT_PROJECT_FILES ) )
753 			options.setSavePrettyPrint();
754 
755 		projectDocument.getSoapuiProject().setSoapuiVersion( SoapUI.SOAPUI_VERSION );
756 
757 		try
758 		{
759 			File tempFile = File.createTempFile( "project-temp-", ".xml", projectFile.getParentFile() );
760 
761 			// save once to make sure it can be saved
762 			FileOutputStream tempOut = new FileOutputStream( tempFile );
763 			projectDocument.save( tempOut, options );
764 			tempOut.close();
765 
766 			if( getSettings().getBoolean( UISettings.LINEBREAK ) )
767 				normalizeLineBreak( projectFile, tempFile );
768 			else
769 			{
770 				// now save it for real
771 				FileOutputStream projectOut = new FileOutputStream( projectFile );
772 				projectDocument.save( projectOut, options );
773 				projectOut.close();
774 				// delete tempFile here so we have it as backup in case second save
775 				// fails
776 				if( !tempFile.delete() )
777 				{
778 					SoapUI.getErrorLog().warn( "Failed to delete temporary project file; " + tempFile.getAbsolutePath() );
779 					tempFile.deleteOnExit();
780 				}
781 			}
782 			size = projectFile.length();
783 		}
784 		catch( Throwable t )
785 		{
786 			SoapUI.logError( t );
787 			UISupport.showErrorMessage( "Failed to save project [" + getName() + "]: " + t.toString() );
788 			return false;
789 		}
790 
791 		lastModified = projectFile.lastModified();
792 		log.info( "Saved project [" + getName() + "] to [" + projectFile.getAbsolutePath() + " - " + size + " bytes" );
793 		setProjectRoot( getPath() );
794 		return true;
795 	}
796 
797 	private static void normalizeLineBreak( File target, File tmpFile )
798 	{
799 		try
800 		{
801 			FileReader fr = new FileReader( tmpFile );
802 			BufferedReader in = new BufferedReader( fr );
803 			FileWriter fw = new FileWriter( target );
804 			BufferedWriter out = new BufferedWriter( fw );
805 			String line = "";
806 			while( ( line = in.readLine() ) != null )
807 			{
808 				out.write( line );
809 				out.newLine();
810 				out.flush();
811 			}
812 			out.close();
813 			fw.close();
814 			in.close();
815 			fr.close();
816 		}
817 		catch( FileNotFoundException e )
818 		{
819 			// TODO Auto-generated catch block
820 			e.printStackTrace();
821 		}
822 		catch( IOException e )
823 		{
824 			// TODO Auto-generated catch block
825 			e.printStackTrace();
826 		}
827 
828 		if( !tmpFile.delete() )
829 		{
830 			SoapUI.getErrorLog().warn( "Failed to delete temporary file: " + tmpFile.getAbsolutePath() );
831 			tmpFile.deleteOnExit();
832 		}
833 	}
834 
835 	public void beforeSave()
836 	{
837 		try
838 		{
839 			ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
840 
841 			for( int c = 0; c < a.length; c++ )
842 			{
843 				a[c].beforeSave( this );
844 			}
845 
846 			runBeforeSaveScript();
847 		}
848 		catch( Exception e )
849 		{
850 			SoapUI.logError( e );
851 		}
852 
853 		// notify
854 		for( AbstractInterface<?> iface : interfaces )
855 			iface.beforeSave();
856 
857 		for( WsdlTestSuite testSuite : testSuites )
858 			testSuite.beforeSave();
859 
860 		for( WsdlMockService mockService : mockServices )
861 			mockService.beforeSave();
862 
863 		endpointStrategy.onSave();
864 	}
865 
866 	protected void createBackup( File projectFile ) throws IOException
867 	{
868 		File backupFile = getBackupFile( projectFile );
869 		log.info( "Backing up [" + projectFile + "] to [" + backupFile + "]" );
870 		Tools.copyFile( projectFile, backupFile, true );
871 	}
872 
873 	protected File getBackupFile( File projectFile )
874 	{
875 		String backupFolderName = getSettings().getString( UISettings.BACKUP_FOLDER, "" );
876 
877 		File backupFolder = new File( backupFolderName );
878 		if( !backupFolder.isAbsolute() )
879 		{
880 			backupFolder = new File( projectFile.getParentFile(), backupFolderName );
881 		}
882 
883 		if( !backupFolder.exists() )
884 			backupFolder.mkdirs();
885 
886 		File backupFile = new File( backupFolder, projectFile.getName() + ".backup" );
887 		return backupFile;
888 	}
889 
890 	protected void removeDefinitionCaches( SoapuiProjectDocumentConfig config )
891 	{
892 		for( InterfaceConfig ifaceConfig : config.getSoapuiProject().getInterfaceList() )
893 		{
894 			if( ifaceConfig.isSetDefinitionCache() )
895 			{
896 				log.info( "Removing definition cache from interface [" + ifaceConfig.getName() + "]" );
897 				ifaceConfig.unsetDefinitionCache();
898 			}
899 		}
900 	}
901 
902 	public AbstractInterface<?> addNewInterface( String name, String type )
903 	{
904 		AbstractInterface<?> iface = ( AbstractInterface<?> )InterfaceFactoryRegistry.createNew( this, type, name );
905 		if( iface != null )
906 		{
907 			iface.getConfig().setType( type );
908 
909 			interfaces.add( iface );
910 			fireInterfaceAdded( iface );
911 		}
912 
913 		return iface;
914 	}
915 
916 	public void addProjectListener( ProjectListener listener )
917 	{
918 		projectListeners.add( listener );
919 	}
920 
921 	public void removeProjectListener( ProjectListener listener )
922 	{
923 		projectListeners.remove( listener );
924 	}
925 
926 	public void fireInterfaceAdded( AbstractInterface<?> iface )
927 	{
928 		ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
929 
930 		for( int c = 0; c < a.length; c++ )
931 		{
932 			a[c].interfaceAdded( iface );
933 		}
934 	}
935 
936 	public void fireInterfaceRemoved( AbstractInterface<?> iface )
937 	{
938 		ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
939 
940 		for( int c = 0; c < a.length; c++ )
941 		{
942 			a[c].interfaceRemoved( iface );
943 		}
944 	}
945 
946 	public void fireInterfaceUpdated( AbstractInterface<?> iface )
947 	{
948 		ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
949 
950 		for( int c = 0; c < a.length; c++ )
951 		{
952 			a[c].interfaceUpdated( iface );
953 		}
954 	}
955 
956 	public void fireTestSuiteAdded( WsdlTestSuite testSuite )
957 	{
958 		ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
959 
960 		for( int c = 0; c < a.length; c++ )
961 		{
962 			a[c].testSuiteAdded( testSuite );
963 		}
964 	}
965 
966 	private void fireTestSuiteMoved( WsdlTestSuite testCase, int ix, int offset )
967 	{
968 		ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
969 
970 		for( int c = 0; c < a.length; c++ )
971 		{
972 			a[c].testSuiteMoved( testCase, ix, offset );
973 		}
974 	}
975 
976 	public void fireTestSuiteRemoved( WsdlTestSuite testSuite )
977 	{
978 		ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
979 
980 		for( int c = 0; c < a.length; c++ )
981 		{
982 			a[c].testSuiteRemoved( testSuite );
983 		}
984 	}
985 
986 	public void fireMockServiceAdded( WsdlMockService mockService )
987 	{
988 		ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
989 
990 		for( int c = 0; c < a.length; c++ )
991 		{
992 			a[c].mockServiceAdded( mockService );
993 		}
994 	}
995 
996 	public void fireMockServiceRemoved( WsdlMockService mockService )
997 	{
998 		ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
999 
1000 		for( int c = 0; c < a.length; c++ )
1001 		{
1002 			a[c].mockServiceRemoved( mockService );
1003 		}
1004 	}
1005 
1006 	public void removeInterface( AbstractInterface<?> iface )
1007 	{
1008 		int ix = interfaces.indexOf( iface );
1009 		interfaces.remove( ix );
1010 		try
1011 		{
1012 			fireInterfaceRemoved( iface );
1013 		}
1014 		finally
1015 		{
1016 			iface.release();
1017 			getConfig().removeInterface( ix );
1018 		}
1019 	}
1020 
1021 	public void removeTestSuite( WsdlTestSuite testSuite )
1022 	{
1023 		int ix = testSuites.indexOf( testSuite );
1024 		testSuites.remove( ix );
1025 
1026 		try
1027 		{
1028 			fireTestSuiteRemoved( testSuite );
1029 		}
1030 		finally
1031 		{
1032 			testSuite.release();
1033 			getConfig().removeTestSuite( ix );
1034 		}
1035 	}
1036 
1037 	public boolean isDisabled()
1038 	{
1039 		return disabled;
1040 	}
1041 
1042 	public int getTestSuiteCount()
1043 	{
1044 		return testSuites.size();
1045 	}
1046 
1047 	public WsdlTestSuite getTestSuiteAt( int index )
1048 	{
1049 		return testSuites.get( index );
1050 	}
1051 
1052 	public WsdlTestSuite getTestSuiteByName( String testSuiteName )
1053 	{
1054 		return ( WsdlTestSuite )getWsdlModelItemByName( testSuites, testSuiteName );
1055 	}
1056 
1057 	public WsdlTestSuite addNewTestSuite( String name )
1058 	{
1059 		WsdlTestSuite testSuite = buildTestSuite( getConfig().addNewTestSuite() );
1060 		testSuite.setName( name );
1061 		testSuites.add( testSuite );
1062 		fireTestSuiteAdded( testSuite );
1063 
1064 		return testSuite;
1065 	}
1066 
1067 	public boolean isCacheDefinitions()
1068 	{
1069 		return getSettings().getBoolean( WsdlSettings.CACHE_WSDLS );
1070 	}
1071 
1072 	public void setCacheDefinitions( boolean cacheDefinitions )
1073 	{
1074 		getSettings().setBoolean( WsdlSettings.CACHE_WSDLS, cacheDefinitions );
1075 	}
1076 
1077 	public boolean saveAs( String fileName ) throws IOException
1078 	{
1079 		if( !isOpen() || isDisabled() )
1080 			return false;
1081 
1082 		String oldPath = path;
1083 		path = fileName;
1084 		boolean result = save();
1085 		if( !result )
1086 			path = oldPath;
1087 		else
1088 			remote = false;
1089 
1090 		setProjectRoot( path );
1091 
1092 		return result;
1093 	}
1094 
1095 	@Override
1096 	public void release()
1097 	{
1098 		super.release();
1099 
1100 		if( isOpen() )
1101 		{
1102 			endpointStrategy.release();
1103 
1104 			for( WsdlTestSuite testSuite : testSuites )
1105 				testSuite.release();
1106 
1107 			for( WsdlMockService mockService : mockServices )
1108 				mockService.release();
1109 
1110 			for( AbstractInterface<?> iface : interfaces )
1111 				iface.release();
1112 
1113 			if( wssContainer != null )
1114 			{
1115 				wssContainer.release();
1116 				wssContainer = null;
1117 			}
1118 		}
1119 
1120 		projectListeners.clear();
1121 
1122 		if( afterLoadScriptEngine != null )
1123 			afterLoadScriptEngine.release();
1124 
1125 		if( beforeSaveScriptEngine != null )
1126 			beforeSaveScriptEngine.release();
1127 	}
1128 
1129 	public WsdlMockService addNewMockService( String name )
1130 	{
1131 		WsdlMockService mockService = new WsdlMockService( this, getConfig().addNewMockService() );
1132 		mockService.setName( name );
1133 		mockServices.add( mockService );
1134 		fireMockServiceAdded( mockService );
1135 
1136 		return mockService;
1137 	}
1138 
1139 	public WsdlMockService getMockServiceAt( int index )
1140 	{
1141 		return mockServices.get( index );
1142 	}
1143 
1144 	public WsdlMockService getMockServiceByName( String mockServiceName )
1145 	{
1146 		return ( WsdlMockService )getWsdlModelItemByName( mockServices, mockServiceName );
1147 	}
1148 
1149 	public int getMockServiceCount()
1150 	{
1151 		return mockServices.size();
1152 	}
1153 
1154 	public void removeMockService( WsdlMockService mockService )
1155 	{
1156 		int ix = mockServices.indexOf( mockService );
1157 		mockServices.remove( ix );
1158 
1159 		try
1160 		{
1161 			fireMockServiceRemoved( mockService );
1162 		}
1163 		finally
1164 		{
1165 			mockService.release();
1166 			getConfig().removeMockService( ix );
1167 		}
1168 	}
1169 
1170 	public List<TestSuite> getTestSuiteList()
1171 	{
1172 		return new ArrayList<TestSuite>( testSuites );
1173 	}
1174 
1175 	public List<MockService> getMockServiceList()
1176 	{
1177 		return new ArrayList<MockService>( mockServices );
1178 	}
1179 
1180 	public List<Interface> getInterfaceList()
1181 	{
1182 		return new ArrayList<Interface>( interfaces );
1183 	}
1184 
1185 	public Map<String, Interface> getInterfaces()
1186 	{
1187 		Map<String, Interface> result = new HashMap<String, Interface>();
1188 		for( Interface iface : interfaces )
1189 			result.put( iface.getName(), iface );
1190 
1191 		return result;
1192 	}
1193 
1194 	public Map<String, TestSuite> getTestSuites()
1195 	{
1196 		Map<String, TestSuite> result = new HashMap<String, TestSuite>();
1197 		for( TestSuite iface : testSuites )
1198 			result.put( iface.getName(), iface );
1199 
1200 		return result;
1201 	}
1202 
1203 	public Map<String, MockService> getMockServices()
1204 	{
1205 		Map<String, MockService> result = new HashMap<String, MockService>();
1206 		for( MockService mockService : mockServices )
1207 			result.put( mockService.getName(), mockService );
1208 
1209 		return result;
1210 	}
1211 
1212 	public void reload() throws SoapUIException
1213 	{
1214 		reload( path );
1215 	}
1216 
1217 	public void reload( String path ) throws SoapUIException
1218 	{
1219 		this.path = path;
1220 		getWorkspace().reloadProject( this );
1221 	}
1222 
1223 	public boolean hasNature( String natureId )
1224 	{
1225 		Settings projectSettings = getSettings();
1226 		String projectNature = projectSettings.getString( ProjectSettings.PROJECT_NATURE, null );
1227 		return natureId.equals( projectNature );
1228 	}
1229 
1230 	public AbstractInterface<?> importInterface( AbstractInterface<?> iface, boolean importEndpoints, boolean createCopy )
1231 	{
1232 		iface.beforeSave();
1233 
1234 		InterfaceConfig ifaceConfig = ( InterfaceConfig )iface.getConfig().copy();
1235 		ifaceConfig = ( InterfaceConfig )getConfig().addNewInterface().set( ifaceConfig );
1236 
1237 		AbstractInterface<?> imported = InterfaceFactoryRegistry.build( this, ifaceConfig );
1238 		interfaces.add( imported );
1239 
1240 		if( iface.getProject() != this && importEndpoints )
1241 		{
1242 			endpointStrategy.importEndpoints( iface );
1243 		}
1244 
1245 		if( createCopy )
1246 			ModelSupport.unsetIds( imported );
1247 
1248 		imported.afterLoad();
1249 		fireInterfaceAdded( imported );
1250 
1251 		return imported;
1252 	}
1253 
1254 	public WsdlTestSuite importTestSuite( WsdlTestSuite testSuite, String name, int index, boolean createCopy,
1255 			String description )
1256 	{
1257 		testSuite.beforeSave();
1258 		TestSuiteConfig testSuiteConfig = index == -1 ? ( TestSuiteConfig )getConfig().addNewTestSuite().set(
1259 				testSuite.getConfig().copy() ) : ( TestSuiteConfig )getConfig().insertNewTestSuite( index ).set(
1260 				testSuite.getConfig().copy() );
1261 
1262 		testSuiteConfig.setName( name );
1263 
1264 		testSuite = buildTestSuite( testSuiteConfig );
1265 		if( description != null )
1266 			testSuite.setDescription( description );
1267 
1268 		if( index == -1 )
1269 			testSuites.add( testSuite );
1270 		else
1271 			testSuites.add( index, testSuite );
1272 
1273 		if( createCopy )
1274 			ModelSupport.unsetIds( testSuite );
1275 
1276 		testSuite.afterLoad();
1277 		fireTestSuiteAdded( testSuite );
1278 
1279 		resolveImportedTestSuite( testSuite );
1280 
1281 		return testSuite;
1282 	}
1283 
1284 	public WsdlMockService importMockService( WsdlMockService mockService, String name, boolean createCopy,
1285 			String description )
1286 	{
1287 		mockService.beforeSave();
1288 		MockServiceConfig mockServiceConfig = ( MockServiceConfig )getConfig().addNewMockService().set(
1289 				mockService.getConfig().copy() );
1290 		mockServiceConfig.setName( name );
1291 		if( mockServiceConfig.isSetId() && createCopy )
1292 			mockServiceConfig.unsetId();
1293 		mockService = new WsdlMockService( this, mockServiceConfig );
1294 		mockService.setDescription( description );
1295 		mockServices.add( mockService );
1296 		if( createCopy )
1297 			ModelSupport.unsetIds( mockService );
1298 
1299 		mockService.afterLoad();
1300 
1301 		fireMockServiceAdded( mockService );
1302 
1303 		return mockService;
1304 	}
1305 
1306 	public EndpointStrategy getEndpointStrategy()
1307 	{
1308 		return endpointStrategy;
1309 	}
1310 
1311 	public boolean isOpen()
1312 	{
1313 		return open;
1314 	}
1315 
1316 	public List<? extends ModelItem> getChildren()
1317 	{
1318 		ArrayList<ModelItem> list = new ArrayList<ModelItem>();
1319 		list.addAll( getInterfaceList() );
1320 		list.addAll( getTestSuiteList() );
1321 		list.addAll( getMockServiceList() );
1322 		return list;
1323 	}
1324 
1325 	public void setAfterLoadScript( String script )
1326 	{
1327 		String oldScript = getAfterLoadScript();
1328 
1329 		if( !getConfig().isSetAfterLoadScript() )
1330 			getConfig().addNewAfterLoadScript();
1331 
1332 		getConfig().getAfterLoadScript().setStringValue( script );
1333 		if( afterLoadScriptEngine != null )
1334 			afterLoadScriptEngine.setScript( script );
1335 
1336 		notifyPropertyChanged( AFTER_LOAD_SCRIPT_PROPERTY, oldScript, script );
1337 	}
1338 
1339 	public String getAfterLoadScript()
1340 	{
1341 		return getConfig().isSetAfterLoadScript() ? getConfig().getAfterLoadScript().getStringValue() : null;
1342 	}
1343 
1344 	public void setBeforeSaveScript( String script )
1345 	{
1346 		String oldScript = getBeforeSaveScript();
1347 
1348 		if( !getConfig().isSetBeforeSaveScript() )
1349 			getConfig().addNewBeforeSaveScript();
1350 
1351 		getConfig().getBeforeSaveScript().setStringValue( script );
1352 		if( beforeSaveScriptEngine != null )
1353 			beforeSaveScriptEngine.setScript( script );
1354 
1355 		notifyPropertyChanged( BEFORE_SAVE_SCRIPT_PROPERTY, oldScript, script );
1356 	}
1357 
1358 	public String getBeforeSaveScript()
1359 	{
1360 		return getConfig().isSetBeforeSaveScript() ? getConfig().getBeforeSaveScript().getStringValue() : null;
1361 	}
1362 
1363 	public Object runAfterLoadScript() throws Exception
1364 	{
1365 		String script = getAfterLoadScript();
1366 		if( StringUtils.isNullOrEmpty( script ) )
1367 			return null;
1368 
1369 		if( afterLoadScriptEngine == null )
1370 		{
1371 			afterLoadScriptEngine = SoapUIScriptEngineRegistry.create( this );
1372 			afterLoadScriptEngine.setScript( script );
1373 		}
1374 
1375 		afterLoadScriptEngine.setVariable( "context", context );
1376 		afterLoadScriptEngine.setVariable( "project", this );
1377 		afterLoadScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
1378 		return afterLoadScriptEngine.run();
1379 	}
1380 
1381 	public Object runBeforeSaveScript() throws Exception
1382 	{
1383 		String script = getBeforeSaveScript();
1384 		if( StringUtils.isNullOrEmpty( script ) )
1385 			return null;
1386 
1387 		if( beforeSaveScriptEngine == null )
1388 		{
1389 			beforeSaveScriptEngine = SoapUIScriptEngineRegistry.create( this );
1390 			beforeSaveScriptEngine.setScript( script );
1391 		}
1392 
1393 		beforeSaveScriptEngine.setVariable( "context", context );
1394 		beforeSaveScriptEngine.setVariable( "project", this );
1395 		beforeSaveScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
1396 		return beforeSaveScriptEngine.run();
1397 	}
1398 
1399 	public PropertyExpansionContext getContext()
1400 	{
1401 		return context;
1402 	}
1403 
1404 	public DefaultWssContainer getWssContainer()
1405 	{
1406 		return wssContainer;
1407 	}
1408 
1409 	@Override
1410 	public void resolve( ResolveContext<?> context )
1411 	{
1412 		super.resolve( context );
1413 
1414 		wssContainer.resolve( context );
1415 	}
1416 
1417 	public PropertyExpansion[] getPropertyExpansions()
1418 	{
1419 		List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
1420 
1421 		result.addAll( Arrays.asList( wssContainer.getPropertyExpansions() ) );
1422 		// result.addAll(Arrays.asList(databaseConnectionContainer.
1423 		// getPropertyExpansions()));
1424 
1425 		return result.toArray( new PropertyExpansion[result.size()] );
1426 
1427 	}
1428 
1429 	public String getPropertiesLabel()
1430 	{
1431 		return "Custom Properties";
1432 	}
1433 
1434 	public String getShadowPassword()
1435 	{
1436 		projectPassword = getSettings() == null ? projectPassword : getSettings().getString(
1437 				ProjectSettings.SHADOW_PASSWORD, null );
1438 		return projectPassword;
1439 	}
1440 
1441 	public void setShadowPassword( String password )
1442 	{
1443 		String oldPassword = getSettings().getString( ProjectSettings.SHADOW_PASSWORD, null );
1444 		getSettings().setString( ProjectSettings.SHADOW_PASSWORD, password );
1445 		this.pcs.firePropertyChange( "projectPassword", oldPassword, password );
1446 	}
1447 
1448 	public void inspect()
1449 	{
1450 
1451 		if( !isOpen() )
1452 			return;
1453 
1454 		byte data[] = projectDocument.getSoapuiProject().getEncryptedContent();
1455 		if( data != null && data.length > 0 )
1456 		{
1457 			try
1458 			{
1459 				reload();
1460 			}
1461 			catch( SoapUIException e )
1462 			{
1463 				e.printStackTrace();
1464 			}
1465 		}
1466 	}
1467 
1468 	public int getEncrypted()
1469 	{
1470 		return this.encrypted;
1471 	}
1472 
1473 	public int setEncrypted( int code )
1474 	{
1475 		return this.encrypted = code;
1476 	}
1477 
1478 	public void addPropertyChangeListener( PropertyChangeListener listener )
1479 	{
1480 		this.pcs.addPropertyChangeListener( listener );
1481 	}
1482 
1483 	public void propertyChange( PropertyChangeEvent evt )
1484 	{
1485 		if( "projectPassword".equals( evt.getPropertyName() ) )
1486 		{
1487 			if( encrypted == 0 & ( evt.getOldValue() == null || ( ( String )evt.getOldValue() ).length() == 0 ) )
1488 			{
1489 				encrypted = 1;
1490 			}
1491 			if( encrypted == 1 & ( evt.getNewValue() == null || ( ( String )evt.getNewValue() ).length() == 0 ) )
1492 			{
1493 				encrypted = 0;
1494 			}
1495 			SoapUI.getNavigator().repaint();
1496 		}
1497 
1498 	}
1499 
1500 	public SoapuiProjectDocumentConfig getProjectDocument()
1501 	{
1502 		return projectDocument;
1503 	}
1504 
1505 	public int getInterfaceCount( String type )
1506 	{
1507 		int result = 0;
1508 
1509 		for( AbstractInterface<?> iface : interfaces )
1510 		{
1511 			if( iface.getType().equals( type ) )
1512 				result++ ;
1513 		}
1514 
1515 		return result;
1516 	}
1517 
1518 	public List<AbstractInterface<?>> getInterfaces( String type )
1519 	{
1520 		ArrayList<AbstractInterface<?>> result = new ArrayList<AbstractInterface<?>>();
1521 
1522 		for( AbstractInterface<?> iface : interfaces )
1523 		{
1524 			if( iface.getType().equals( type ) )
1525 				result.add( iface );
1526 		}
1527 
1528 		return result;
1529 	}
1530 
1531 	public void importTestSuite( File file )
1532 	{
1533 		if( !file.exists() )
1534 		{
1535 			UISupport.showErrorMessage( "Error loading test case " );
1536 			return;
1537 		}
1538 
1539 		TestSuiteDocumentConfig newTestSuiteConfig = null;
1540 
1541 		try
1542 		{
1543 			newTestSuiteConfig = TestSuiteDocumentConfig.Factory.parse( file );
1544 		}
1545 		catch( Exception e )
1546 		{
1547 			SoapUI.logError( e );
1548 		}
1549 
1550 		if( newTestSuiteConfig == null )
1551 		{
1552 			UISupport.showErrorMessage( "Not valild test case xml" );
1553 		}
1554 		else
1555 		{
1556 			TestSuiteConfig config = ( TestSuiteConfig )projectDocument.getSoapuiProject().addNewTestSuite().set(
1557 					newTestSuiteConfig.getTestSuite() );
1558 			WsdlTestSuite testSuite = buildTestSuite( config );
1559 
1560 			ModelSupport.unsetIds( testSuite );
1561 			testSuite.afterLoad();
1562 
1563 			testSuites.add( testSuite );
1564 			fireTestSuiteAdded( testSuite );
1565 
1566 			resolveImportedTestSuite( testSuite );
1567 		}
1568 	}
1569 
1570 	private void resolveImportedTestSuite( WsdlTestSuite testSuite )
1571 	{
1572 		ResolveDialog resolver = new ResolveDialog( "Validate TestSuite", "Checks TestSuite for inconsistencies", null );
1573 		resolver.setShowOkMessage( false );
1574 		resolver.resolve( testSuite );
1575 	}
1576 
1577 	/***
1578 	 * @see com.eviware.soapui.impl.WsdlInterfaceFactory.importWsdl
1579 	 * @deprecated
1580 	 */
1581 
1582 	public WsdlInterface[] importWsdl( String url, boolean createRequests ) throws SoapUIException
1583 	{
1584 		return WsdlInterfaceFactory.importWsdl( this, url, createRequests );
1585 	}
1586 
1587 	/***
1588 	 * @see com.eviware.soapui.impl.WsdlInterfaceFactory.importWsdl
1589 	 * @deprecated see WsdlInterfaceFactory
1590 	 */
1591 
1592 	public WsdlInterface[] importWsdl( String url, boolean createRequests, WsdlLoader wsdlLoader )
1593 			throws SoapUIException
1594 	{
1595 		return WsdlInterfaceFactory.importWsdl( this, url, createRequests, null, wsdlLoader );
1596 	}
1597 
1598 	/***
1599 	 * @see com.eviware.soapui.impl.WsdlInterfaceFactory.importWsdl
1600 	 * @deprecated see WsdlInterfaceFactory
1601 	 */
1602 
1603 	public WsdlInterface[] importWsdl( String url, boolean createRequests, QName bindingName, WsdlLoader wsdlLoader )
1604 			throws SoapUIException
1605 	{
1606 		return WsdlInterfaceFactory.importWsdl( this, url, createRequests, bindingName, wsdlLoader );
1607 	}
1608 
1609 	public void setDefaultScriptLanguage( String id )
1610 	{
1611 		getConfig().setDefaultScriptLanguage( id );
1612 	}
1613 
1614 	public String getDefaultScriptLanguage()
1615 	{
1616 		if( getConfig().isSetDefaultScriptLanguage() )
1617 			return getConfig().getDefaultScriptLanguage();
1618 		else
1619 			return SoapUIScriptEngineRegistry.DEFAULT_SCRIPT_ENGINE_ID;
1620 	}
1621 
1622 	public int getIndexOfTestSuite( TestSuite testSuite )
1623 	{
1624 		return testSuites.indexOf( testSuite );
1625 	}
1626 
1627 	public String getBeforeRunScript()
1628 	{
1629 		return getConfig().isSetBeforeRunScript() ? getConfig().getBeforeRunScript().getStringValue() : null;
1630 	}
1631 
1632 	public void setBeforeRunScript( String script )
1633 	{
1634 		String oldScript = getBeforeRunScript();
1635 
1636 		if( !getConfig().isSetBeforeRunScript() )
1637 			getConfig().addNewBeforeRunScript();
1638 
1639 		getConfig().getBeforeRunScript().setStringValue( script );
1640 		if( beforeRunScriptEngine != null )
1641 			beforeRunScriptEngine.setScript( script );
1642 
1643 		notifyPropertyChanged( "beforeRunScript", oldScript, script );
1644 	}
1645 
1646 	public Object runBeforeRunScript( ProjectRunContext context, ProjectRunner runner ) throws Exception
1647 	{
1648 		String script = getBeforeRunScript();
1649 		if( StringUtils.isNullOrEmpty( script ) )
1650 			return null;
1651 
1652 		if( beforeRunScriptEngine == null )
1653 		{
1654 			beforeRunScriptEngine = SoapUIScriptEngineRegistry.create( this );
1655 			beforeRunScriptEngine.setScript( script );
1656 		}
1657 
1658 		beforeRunScriptEngine.setVariable( "runner", runner );
1659 		beforeRunScriptEngine.setVariable( "context", context );
1660 		beforeRunScriptEngine.setVariable( "project", this );
1661 		beforeRunScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
1662 		return beforeRunScriptEngine.run();
1663 	}
1664 
1665 	public String getAfterRunScript()
1666 	{
1667 		return getConfig().isSetAfterRunScript() ? getConfig().getAfterRunScript().getStringValue() : null;
1668 	}
1669 
1670 	public void setAfterRunScript( String script )
1671 	{
1672 		String oldScript = getAfterRunScript();
1673 
1674 		if( !getConfig().isSetAfterRunScript() )
1675 			getConfig().addNewAfterRunScript();
1676 
1677 		getConfig().getAfterRunScript().setStringValue( script );
1678 		if( afterRunScriptEngine != null )
1679 			afterRunScriptEngine.setScript( script );
1680 
1681 		notifyPropertyChanged( "afterRunScript", oldScript, script );
1682 	}
1683 
1684 	public Object runAfterRunScript( ProjectRunContext context, ProjectRunner runner ) throws Exception
1685 	{
1686 		String script = getAfterRunScript();
1687 		if( StringUtils.isNullOrEmpty( script ) )
1688 			return null;
1689 
1690 		if( afterRunScriptEngine == null )
1691 		{
1692 			afterRunScriptEngine = SoapUIScriptEngineRegistry.create( this );
1693 			afterRunScriptEngine.setScript( script );
1694 		}
1695 
1696 		afterRunScriptEngine.setVariable( "runner", runner );
1697 		afterRunScriptEngine.setVariable( "context", context );
1698 		afterRunScriptEngine.setVariable( "project", this );
1699 		afterRunScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
1700 		return afterRunScriptEngine.run();
1701 	}
1702 
1703 	public void addProjectRunListener( ProjectRunListener projectRunListener )
1704 	{
1705 		runListeners.add( projectRunListener );
1706 	}
1707 
1708 	public void removeProjectRunListener( ProjectRunListener projectRunListener )
1709 	{
1710 		runListeners.remove( projectRunListener );
1711 	}
1712 
1713 	public WsdlProjectRunner run( StringToObjectMap context, boolean async )
1714 	{
1715 		WsdlProjectRunner runner = new WsdlProjectRunner( this, context );
1716 		runner.start( async );
1717 		return runner;
1718 	}
1719 
1720 	public boolean isAbortOnError()
1721 	{
1722 		return getConfig().getAbortOnError();
1723 	}
1724 
1725 	// public boolean isFailOnErrors()
1726 	// {
1727 	// return getConfig().getFailOnErrors();
1728 	// }
1729 	//	
1730 	// public void setFailOnErrors( boolean arg0 )
1731 	// {
1732 	// getConfig().setFailOnErrors( arg0 );
1733 	// }
1734 
1735 	public void setAbortOnError( boolean arg0 )
1736 	{
1737 		getConfig().setAbortOnError( arg0 );
1738 	}
1739 
1740 	public long getTimeout()
1741 	{
1742 		return getConfig().getTimeout();
1743 	}
1744 
1745 	public void setTimeout( long timeout )
1746 	{
1747 		getConfig().setTimeout( timeout );
1748 	}
1749 
1750 	public ProjectRunListener[] getProjectRunListeners()
1751 	{
1752 		return runListeners.toArray( new ProjectRunListener[runListeners.size()] );
1753 	}
1754 
1755 	public TestSuiteRunType getRunType()
1756 	{
1757 		Enum runType = getConfig().getRunType();
1758 
1759 		if( TestSuiteRunTypesConfig.PARALLELL.equals( runType ) )
1760 			return TestSuiteRunType.PARALLEL;
1761 		else
1762 			return TestSuiteRunType.SEQUENTIAL;
1763 	}
1764 
1765 	public void setRunType( TestSuiteRunType runType )
1766 	{
1767 		TestSuiteRunType oldRunType = getRunType();
1768 
1769 		if( runType == TestSuiteRunType.PARALLEL && oldRunType != TestSuiteRunType.PARALLEL )
1770 		{
1771 			getConfig().setRunType( TestSuiteRunTypesConfig.PARALLELL );
1772 			notifyPropertyChanged( "runType", oldRunType, runType );
1773 		}
1774 		else if( runType == TestSuiteRunType.SEQUENTIAL && oldRunType != TestSuiteRunType.SEQUENTIAL )
1775 		{
1776 			getConfig().setRunType( TestSuiteRunTypesConfig.SEQUENTIAL );
1777 			notifyPropertyChanged( "runType", oldRunType, runType );
1778 		}
1779 	}
1780 
1781 	public WsdlTestSuite moveTestSuite( int ix, int offset )
1782 	{
1783 		WsdlTestSuite testSuite = testSuites.get( ix );
1784 
1785 		if( offset == 0 )
1786 			return testSuite;
1787 
1788 		testSuites.remove( ix );
1789 		testSuites.add( ix + offset, testSuite );
1790 
1791 		TestSuiteConfig[] configs = new TestSuiteConfig[testSuites.size()];
1792 
1793 		for( int c = 0; c < testSuites.size(); c++ )
1794 		{
1795 			if( offset > 0 )
1796 			{
1797 				if( c < ix )
1798 					configs[c] = ( TestSuiteConfig )getConfig().getTestSuiteArray( c ).copy();
1799 				else if( c < ( ix + offset ) )
1800 					configs[c] = ( TestSuiteConfig )getConfig().getTestSuiteArray( c + 1 ).copy();
1801 				else if( c == ix + offset )
1802 					configs[c] = ( TestSuiteConfig )getConfig().getTestSuiteArray( ix ).copy();
1803 				else
1804 					configs[c] = ( TestSuiteConfig )getConfig().getTestSuiteArray( c ).copy();
1805 			}
1806 			else
1807 			{
1808 				if( c < ix + offset )
1809 					configs[c] = ( TestSuiteConfig )getConfig().getTestSuiteArray( c ).copy();
1810 				else if( c == ix + offset )
1811 					configs[c] = ( TestSuiteConfig )getConfig().getTestSuiteArray( ix ).copy();
1812 				else if( c <= ix )
1813 					configs[c] = ( TestSuiteConfig )getConfig().getTestSuiteArray( c - 1 ).copy();
1814 				else
1815 					configs[c] = ( TestSuiteConfig )getConfig().getTestSuiteArray( c ).copy();
1816 			}
1817 		}
1818 
1819 		getConfig().setTestSuiteArray( configs );
1820 		for( int c = 0; c < configs.length; c++ )
1821 		{
1822 			testSuites.get( c ).resetConfigOnMove( getConfig().getTestSuiteArray( c ) );
1823 		}
1824 
1825 		fireTestSuiteMoved( testSuite, ix, offset );
1826 		return testSuite;
1827 
1828 	}
1829 
1830 	public void importMockService( File file )
1831 	{
1832 		if( !file.exists() )
1833 		{
1834 			UISupport.showErrorMessage( "Error loading test case " );
1835 			return;
1836 		}
1837 
1838 		MockServiceDocumentConfig newMockServiceConfig = null;
1839 
1840 		try
1841 		{
1842 			newMockServiceConfig = MockServiceDocumentConfig.Factory.parse( file );
1843 		}
1844 		catch( Exception e )
1845 		{
1846 			SoapUI.logError( e );
1847 		}
1848 
1849 		if( newMockServiceConfig == null )
1850 		{
1851 			UISupport.showErrorMessage( "Not valid mock service xml" );
1852 		}
1853 		else
1854 		{
1855 			MockServiceConfig config = ( MockServiceConfig )projectDocument.getSoapuiProject().addNewMockService().set(
1856 					newMockServiceConfig.getMockService() );
1857 			WsdlMockService mockService = new WsdlMockService( this, config );
1858 
1859 			ModelSupport.unsetIds( mockService );
1860 			mockService.afterLoad();
1861 
1862 			mockServices.add( mockService );
1863 			fireMockServiceAdded( mockService );
1864 
1865 			resolveImportedMockService( mockService );
1866 		}
1867 	}
1868 
1869 	private void resolveImportedMockService( WsdlMockService mockService )
1870 	{
1871 		ResolveDialog resolver = new ResolveDialog( "Validate MockService", "Checks MockService for inconsistencies",
1872 				null );
1873 		resolver.setShowOkMessage( false );
1874 		resolver.resolve( mockService );
1875 	}
1876 }