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