View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.io.ByteArrayOutputStream;
16  import java.io.File;
17  import java.io.FileOutputStream;
18  import java.io.IOException;
19  import java.net.MalformedURLException;
20  import java.net.URL;
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import javax.swing.ImageIcon;
29  import javax.xml.namespace.QName;
30  
31  import org.apache.log4j.Logger;
32  import org.apache.xmlbeans.XmlException;
33  import org.apache.xmlbeans.XmlOptions;
34  
35  import com.eviware.soapui.SoapUI;
36  import com.eviware.soapui.config.InterfaceConfig;
37  import com.eviware.soapui.config.MockServiceConfig;
38  import com.eviware.soapui.config.ProjectConfig;
39  import com.eviware.soapui.config.SoapuiProjectDocumentConfig;
40  import com.eviware.soapui.config.TestSuiteConfig;
41  import com.eviware.soapui.impl.WorkspaceImpl;
42  import com.eviware.soapui.impl.wsdl.endpoint.DefaultEndpointStrategy;
43  import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
44  import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
45  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlImporter;
46  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlLoader;
47  import com.eviware.soapui.impl.wsdl.support.wss.DefaultWssContainer;
48  import com.eviware.soapui.model.ModelItem;
49  import com.eviware.soapui.model.iface.Interface;
50  import com.eviware.soapui.model.mock.MockService;
51  import com.eviware.soapui.model.project.EndpointStrategy;
52  import com.eviware.soapui.model.project.Project;
53  import com.eviware.soapui.model.project.ProjectListener;
54  import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
55  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
56  import com.eviware.soapui.model.settings.Settings;
57  import com.eviware.soapui.model.testsuite.TestSuite;
58  import com.eviware.soapui.settings.ProjectSettings;
59  import com.eviware.soapui.settings.UISettings;
60  import com.eviware.soapui.settings.WsdlSettings;
61  import com.eviware.soapui.support.SoapUIException;
62  import com.eviware.soapui.support.StringUtils;
63  import com.eviware.soapui.support.Tools;
64  import com.eviware.soapui.support.UISupport;
65  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
66  import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
67  
68  /***
69   * WSDL project implementation
70   * 
71   * @author Ole.Matzura
72   */
73  
74  public class WsdlProject extends AbstractTestPropertyHolderWsdlModelItem<ProjectConfig> implements Project
75  {
76  	public final static String AFTER_LOAD_SCRIPT_PROPERTY = WsdlTestSuite.class.getName() + "@setupScript";
77  	public final static String BEFORE_SAVE_SCRIPT_PROPERTY = WsdlTestSuite.class.getName() + "@tearDownScript";
78  	
79     private WorkspaceImpl workspace;
80     private String path;
81     private List<WsdlInterface> interfaces = new ArrayList<WsdlInterface>();
82     private List<WsdlTestSuite> testSuites = new ArrayList<WsdlTestSuite>();
83     private List<WsdlMockService> mockServices = new ArrayList<WsdlMockService>();
84     private Set<ProjectListener> projectListeners = new HashSet<ProjectListener>();
85     private SoapuiProjectDocumentConfig projectDocument;
86  	private ImageIcon disabledIcon;
87  	private ImageIcon closedIcon;
88  	private ImageIcon remoteIcon;
89  	private EndpointStrategy endpointStrategy = new DefaultEndpointStrategy();
90  	private long lastModified;
91  	private boolean remote;
92  	private boolean open = true;
93  	private boolean disabled;
94  	
95  	private SoapUIScriptEngine afterLoadScriptEngine;
96  	private SoapUIScriptEngine beforeSaveScriptEngine;
97  	private PropertyExpansionContext context = new DefaultPropertyExpansionContext( this );
98  	private DefaultWssContainer wssContainer;
99     
100    private final static Logger log = Logger.getLogger( WsdlProject.class );
101 
102    public WsdlProject() throws XmlException, IOException, SoapUIException
103    {
104    	this( (WorkspaceImpl)null );
105    }
106 
107    public WsdlProject( String path ) throws XmlException, IOException, SoapUIException
108    {
109    	this( path, null );
110    }
111    
112    public WsdlProject( WorkspaceImpl workspace ) 
113    {
114    	this( null, workspace, true );
115    }
116    
117    public WsdlProject(String path, WorkspaceImpl workspace ) 
118    {
119    	this( path, workspace, true );
120    }
121    
122    public WsdlProject(String path, WorkspaceImpl workspace, boolean create ) 
123    {
124    	this( path, workspace, create, true, null );
125    }
126    
127    public WsdlProject(String path, WorkspaceImpl workspace, boolean create, boolean open, String tempName ) 
128    {
129    	super( null, workspace, "/project.gif" );
130    	
131       this.workspace = workspace;
132    	this.path = path;
133       
134    	try
135    	{
136 	   	if( path != null && open )
137 	   	{
138 		   	if( path.toLowerCase().startsWith( "http" ))
139 		   	{
140 		   		try
141 		 			{
142 		   			remote = true;
143 		 				loadProject( new URL( path ));
144 		 			}
145 		 			catch( MalformedURLException e )
146 		 			{
147 		 				SoapUI.logError( e );
148 		 			}
149 		   	}
150 				else
151 				{
152 					File file = new File( path );
153 					if( file.exists())
154 					{
155 					   try
156 						{
157 							loadProject( file.toURI().toURL());
158 							lastModified = file.lastModified();
159 						}
160 						catch( MalformedURLException e )
161 						{
162 			 				SoapUI.logError( e );
163 						}
164 					}
165 					else if( !create )
166 					{
167 						disabled = true;
168 					}
169 				}
170 		   }
171    	}
172    	catch( SoapUIException e )
173 		{
174    		SoapUI.logError( e );
175 			disabled = true;
176 		}
177    	finally
178    	{
179       	closedIcon = UISupport.createImageIcon( "/closedProject.gif" );
180       	remoteIcon = UISupport.createImageIcon( "/remoteProject.gif" );
181       	disabledIcon = UISupport.createImageIcon( "/disabledProject.gif" );
182       	
183       	this.open = open && !disabled;
184       	
185       	if( projectDocument == null )
186 	   	{
187 	   		projectDocument = SoapuiProjectDocumentConfig.Factory.newInstance();
188 			   setConfig( projectDocument.addNewSoapuiProject() );
189 			   if( tempName != null || path != null )
190 			   	getConfig().setName( StringUtils.isNullOrEmpty( tempName ) ? getNameFromPath() : tempName );
191 			   
192 				setPropertiesConfig( getConfig().addNewProperties() );
193 				wssContainer = new DefaultWssContainer( this, getConfig().addNewWssContainer());
194 	   	}
195       	
196       	endpointStrategy.init( this );
197       	setProjectRoot(path);
198       	
199       	for( ProjectListener listener : SoapUI.getListenerRegistry().getListeners( ProjectListener.class ) )
200    		{
201    			addProjectListener( listener );
202    		}
203    	}
204    }
205    
206 	public boolean isRemote()
207 	{
208 		return remote;
209 	}
210 
211 	private void loadProject( URL file ) throws SoapUIException
212 	{
213 		try
214 		{
215 			UISupport.setHourglassCursor();
216 			
217 			UrlWsdlLoader loader = new UrlWsdlLoader( file.toString() );
218 			loader.setUseWorker( false );
219 			projectDocument = SoapuiProjectDocumentConfig.Factory.parse( loader.load() );
220 
221 			setConfig( projectDocument.getSoapuiProject() );
222 			
223 			// removed cached definitions if caching is disabled
224 			if( !getSettings().getBoolean( WsdlSettings.CACHE_WSDLS ))
225 			{
226 				removeDefinitionCaches( projectDocument );
227 			}
228 			
229 			log.info( "Loaded project from [" + file.toString() + "]" );
230 			 
231 			List<InterfaceConfig> interfaceConfigs = getConfig().getInterfaceList();
232 			for (InterfaceConfig config : interfaceConfigs)
233 			{
234 			   interfaces.add( new WsdlInterface( this, config ));
235 			}
236 
237 			List<TestSuiteConfig> testSuiteConfigs = getConfig().getTestSuiteList();
238 			for( TestSuiteConfig config : testSuiteConfigs )
239 			{
240 			   testSuites.add( new WsdlTestSuite( this, config ));
241 			}
242 			
243 			List<MockServiceConfig> mockServiceConfigs = getConfig().getMockServiceList();
244 			for( MockServiceConfig config : mockServiceConfigs )
245 			{
246 			   mockServices.add( new WsdlMockService( this, config ));
247 			}
248 			
249 			if( !getConfig().isSetWssContainer())
250 				getConfig().addNewWssContainer();
251 			
252 			wssContainer = new DefaultWssContainer( this, getConfig().getWssContainer());
253 			
254 			endpointStrategy.init( this );
255 			
256 			if( !getConfig().isSetProperties() )
257 				getConfig().addNewProperties();
258 			
259 			setPropertiesConfig( getConfig().getProperties() );
260 			
261 			afterLoad( this );
262 		}
263 		catch (Exception e)
264 		{
265 			e.printStackTrace();
266 			throw new SoapUIException( "Failed to load project from file [" + file.toString() + "]", e );
267 		}
268 		finally
269 		{
270 			UISupport.resetCursor();
271 		}
272 	}
273 	
274 	@Override
275 	public void afterLoad() throws Exception
276 	{
277 		runAfterLoadScript();
278 	}
279 
280 	private void setProjectRoot(String path)
281 	{
282 		if( path != null && projectDocument != null )
283       {
284       	int ix = path.lastIndexOf( File.separatorChar );
285       	if( ix > 0 )
286       		getSettings().setString( ProjectSettings.PROJECT_ROOT, path.substring( 0, ix ) );
287       }
288 	}
289 	
290 	@Override
291 	public ImageIcon getIcon()
292 	{
293 		if( isDisabled())
294 			return disabledIcon;
295 		else if( !isOpen() )
296 			return closedIcon;
297 		else if( isRemote() )
298 			return remoteIcon;
299 		else
300 			return super.getIcon();
301 	}
302 	
303 	private String getNameFromPath()
304 	{
305 		int ix = path.lastIndexOf( isRemote() ? '/' : File.separatorChar );
306 		String name = ix == -1 ? path : path.substring( ix+1 );
307 		return name;
308 	}
309 	
310 	@Override
311 	public String getDescription()
312 	{
313 		if( isOpen() )
314 			return super.getDescription();
315 		
316 		String name = getName();
317 		
318 		if( isDisabled() )
319 			name += " - disabled";
320 		else
321 			name += " - closed";
322 		
323 		return name;
324 	}
325 
326    public WorkspaceImpl getWorkspace()
327    {
328       return workspace;
329    }
330 
331 	public WsdlInterface getInterfaceAt(int index)
332    {
333       return interfaces.get( index );
334    }
335 
336    public WsdlInterface getInterfaceByName(String interfaceName)
337 	{
338 		return (WsdlInterface) getWsdlModelItemByName( interfaces, interfaceName );
339 	}
340 
341    public WsdlInterface getInterfaceByBindingName( QName bindingName )
342    {
343    	for( int c = 0; c < getInterfaceCount(); c++ )
344    	{
345    		if( getInterfaceAt( c ).getBindingName().equals( bindingName ))
346    			return getInterfaceAt( c );
347    	}
348    	
349    	return null;
350    }
351    
352 	public int getInterfaceCount()
353    {
354       return interfaces.size();
355    }
356 
357    public String getPath()
358 	{
359 		return path;
360 	}
361 
362 	public boolean save() throws IOException 
363    {
364 		if( !isOpen() || isDisabled() || isRemote() )
365 			return true;
366 		
367       if( path == null || isRemote())
368       {
369       	path = getName() + "-soapui-project.xml";
370       	File file = null;
371          
372          while( file == null || (file.exists() && !UISupport.confirm( "File [" + file.getName() + "] exists, overwrite?", "Overwrite File?" )))
373          {
374          	file = UISupport.getFileDialogs().saveAs(this, "Save project " + getName(), ".xml",
375       					"XML Files (*.xml)", new File( path ));
376             if( file == null ) return false;
377          }
378 
379          path = file.getAbsolutePath();
380       }
381       
382       File projectFile = new File( path );
383       
384       while( projectFile.exists() && !projectFile.canWrite() )
385       {
386       	if( UISupport.confirm( "Project file [" + path + "] can not be written to, save to new file?", "Save Project" ))
387       	{
388       		projectFile = UISupport.getFileDialogs().saveAs(this, "Save project " + getName(),".xml",
389       					"XML Files (*.xml)", projectFile );
390       		
391             if( projectFile == null ) return false;
392 
393             path = projectFile.getAbsolutePath();
394       	}
395       	else return false;
396       }
397       
398       // check modified 
399 		if( projectFile.exists() && lastModified != 0 && lastModified < projectFile.lastModified() )
400 		{
401 			if( !UISupport.confirm( 
402 						"Project file for [" + getName() + "] has been modified externally, overwrite?", 
403 						"Save Project" ))
404 				return false;
405 		}
406       
407    	long size = 0;
408    	
409    	if( projectFile.exists() && getSettings().getBoolean( UISettings.CREATE_BACKUP ))
410    	{
411    		createBackup( projectFile );
412    	}
413    	
414    	beforeSave();
415    	
416    	XmlOptions options = new XmlOptions();
417    	if( SoapUI.getSettings().getBoolean( WsdlSettings.PRETTY_PRINT_PROJECT_FILES ))
418    		options.setSavePrettyPrint();
419    	
420    	// check for caching
421    	if( !getSettings().getBoolean( WsdlSettings.CACHE_WSDLS ))
422    	{
423    		// no caching -> create copy and remove definition cachings
424    		SoapuiProjectDocumentConfig config = (SoapuiProjectDocumentConfig) projectDocument.copy();
425    		removeDefinitionCaches(config);
426    		
427    		config.getSoapuiProject().setSoapuiVersion( SoapUI.SOAPUI_VERSION );
428    		config.save( projectFile, options );
429    	}
430    	else
431    	{
432       	try
433 			{
434       		// save to temporary buffer to avoid corruption of file
435 				projectDocument.getSoapuiProject().setSoapuiVersion( SoapUI.SOAPUI_VERSION );
436 				ByteArrayOutputStream writer = new ByteArrayOutputStream( 8192 );
437 				projectDocument.save( writer, options );
438 				FileOutputStream out = new FileOutputStream( projectFile );
439 				writer.writeTo( out );
440 				out.close();
441 				size = writer.size();
442 			}
443 			catch (Throwable t)
444 			{
445 				SoapUI.logError( t );
446 				UISupport.showErrorMessage( "Failed to save project [" + getName() + "]: " + t.toString() );
447 				return false;
448 			}
449    	}
450    	
451    	lastModified = projectFile.lastModified();
452 		log.info( "Saved project [" + getName() + "] to [" + projectFile.getAbsolutePath() + " - " +
453 				size + " bytes" );
454 		setProjectRoot(path);
455 		return true;
456 }
457 
458 	@Override
459    public void beforeSave()
460 	{
461 		try
462 		{
463 			runBeforeSaveScript();
464 		}
465 		catch( Exception e )
466 		{
467 			SoapUI.logError( e );
468 		}
469 		
470 		// notify
471    	for( WsdlInterface iface : interfaces )
472    		iface.beforeSave();
473    	
474    	for( WsdlTestSuite testSuite : testSuites )
475    		testSuite.beforeSave();
476    	
477    	for( WsdlMockService mockService : mockServices )
478    		mockService.beforeSave();
479    	
480   		endpointStrategy.onSave();
481 	}
482 
483 	private void createBackup(File projectFile) throws IOException
484 	{
485 		String backupFolderName = getSettings().getString( UISettings.BACKUP_FOLDER, "" );
486 		
487 		File backupFolder = new File( backupFolderName );
488 		if( !backupFolder.isAbsolute() )
489 		{
490 			backupFolder = new File( projectFile.getParentFile(), backupFolderName );
491 		}
492 		
493 		if( !backupFolder.exists() )
494 			backupFolder.mkdirs();
495 		
496 		File backupFile = new File( backupFolder, projectFile.getName() + ".backup" );
497 		log.info( "Backing up [" + projectFile + "] to [" + backupFile + "]" );
498 		
499 		Tools.copyFile( projectFile, backupFile, true );
500 	}
501 
502 	private void removeDefinitionCaches(SoapuiProjectDocumentConfig config)
503 	{
504 		for( InterfaceConfig ifaceConfig : config.getSoapuiProject().getInterfaceList() )
505 		{
506 			if( ifaceConfig.isSetDefinitionCache() )
507 			{
508 				log.info( "Removing definition cache from interface [" + ifaceConfig.getName() + "]" );
509 				ifaceConfig.unsetDefinitionCache();
510 			}
511 		}
512 	}
513 	
514 	public WsdlInterface [] importWsdl( String url, boolean createRequests ) throws SoapUIException
515 	{
516 		return importWsdl( url, createRequests, null, null );
517 	}
518    
519 	public WsdlInterface [] importWsdl( String url, boolean createRequests, WsdlLoader wsdlLoader ) throws SoapUIException
520 	{
521 		return importWsdl( url, createRequests, null, wsdlLoader );
522 	}
523 	
524    public WsdlInterface [] importWsdl( String url, boolean createRequests, QName bindingName, WsdlLoader wsdlLoader ) throws SoapUIException
525    {
526    	if( projectDocument == null )
527    		return null;
528    	
529    	WsdlInterface[] result;
530    	
531       try
532       {
533          result = WsdlImporter.getInstance().importWsdl( this, url, bindingName, wsdlLoader );
534       }
535       catch (Exception e)
536       {
537          log.error( "Error importing wsdl: " + e );
538          SoapUI.logError( e );
539          throw new SoapUIException( "Error importing wsdl", e );
540       }
541       
542       try
543       {      
544 			if( createRequests && result != null )
545          {
546          	for (WsdlInterface iface : result)
547 				{
548          		for( int c = 0; c < iface.getOperationCount(); c++ )
549          		{
550          			WsdlOperation operation = iface.getOperationAt( c );
551          			WsdlRequest request = operation.addNewRequest( "Request 1");
552                   try
553                   {
554                      String requestContent = operation.createRequest( true );
555 							request.setRequestContent( requestContent);
556                   }
557                   catch (Exception e)
558                   {
559                      SoapUI.logError( e );
560                   }
561          		}
562 				}
563          }
564       }
565       catch (Exception e)
566       {
567       	log.error( "Error creating requests: " + e.getMessage() );
568          throw new SoapUIException( "Error creating requests", e );
569       }
570       
571       return result;
572    }
573    
574    public WsdlInterface addNewInterface( String name )
575    {
576       WsdlInterface iface = new WsdlInterface( this, getConfig().addNewInterface());
577       iface.setName( name );
578       interfaces.add( iface );
579       fireInterfaceAdded( iface );
580 
581       return iface;
582    }
583    
584    public void addProjectListener(ProjectListener listener)
585    {
586       projectListeners.add( listener );
587    }
588    
589    public void removeProjectListener(ProjectListener listener)
590    {
591       projectListeners.remove( listener );
592    }
593    
594    public void fireInterfaceAdded( WsdlInterface iface )
595    {
596       ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
597       
598       for (int c = 0; c < a.length; c++ )
599       {
600          a[c].interfaceAdded( iface );
601       }
602    }
603    
604    public void fireInterfaceRemoved( WsdlInterface iface )
605    {
606       ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
607       
608       for (int c = 0; c < a.length; c++ )
609       {
610          a[c].interfaceRemoved( iface );
611       }
612    }
613    
614    public void fireInterfaceUpdated( WsdlInterface iface )
615    {
616       ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
617       
618       for (int c = 0; c < a.length; c++ )
619       {
620          a[c].interfaceUpdated( iface );
621       }
622    }
623    
624    public void fireTestSuiteAdded( WsdlTestSuite testSuite )
625    {
626       ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
627       
628       for (int c = 0; c < a.length; c++ )
629       {
630          a[c].testSuiteAdded( testSuite );
631       }
632    }
633    
634    public void fireTestSuiteRemoved( WsdlTestSuite testSuite )
635    {
636       ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
637       
638       for (int c = 0; c < a.length; c++ )
639       {
640          a[c].testSuiteRemoved( testSuite );
641       }
642    } 
643    
644    public void fireMockServiceAdded( WsdlMockService mockService )
645    {
646       ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
647       
648       for (int c = 0; c < a.length; c++ )
649       {
650          a[c].mockServiceAdded( mockService );
651       }
652    }
653    
654    public void fireMockServiceRemoved( WsdlMockService mockService )
655    {
656       ProjectListener[] a = projectListeners.toArray( new ProjectListener[projectListeners.size()] );
657       
658       for (int c = 0; c < a.length; c++ )
659       {
660          a[c].mockServiceRemoved( mockService );
661       }
662    }
663    
664    public void removeInterface(WsdlInterface iface )
665    {
666       int ix = interfaces.indexOf( iface );
667       interfaces.remove( ix );
668       try
669       {
670       	fireInterfaceRemoved( iface );
671       }
672       finally
673       {
674       	iface.release();
675       	getConfig().removeInterface( ix );
676       }
677    }
678    
679    public void removeTestSuite(WsdlTestSuite testSuite )
680    {
681       int ix = testSuites.indexOf( testSuite );
682       testSuites.remove( ix );
683       
684       try
685       {
686       	fireTestSuiteRemoved( testSuite );
687       }
688       finally
689       {
690       	testSuite.release();
691       	getConfig().removeTestSuite( ix );
692       }
693    }
694 
695    public boolean isDisabled()
696    {
697    	return disabled;
698    }
699    
700    public int getTestSuiteCount()
701    {
702       return testSuites.size();
703    }
704 
705    public WsdlTestSuite getTestSuiteAt(int index)
706    {
707       return testSuites.get( index );
708    }
709 
710    public WsdlTestSuite getTestSuiteByName(String testSuiteName)
711 	{
712 		return  ( WsdlTestSuite ) getWsdlModelItemByName( testSuites, testSuiteName );
713 	}
714 
715    public WsdlTestSuite addNewTestSuite(String name)
716    {
717       WsdlTestSuite testSuite = new WsdlTestSuite( this, getConfig().addNewTestSuite());
718       testSuite.setName( name );
719       testSuites.add( testSuite );
720       fireTestSuiteAdded( testSuite );
721 
722       return testSuite;
723    }
724 
725 	public boolean isCacheDefinitions()
726 	{
727 		return getSettings().getBoolean( WsdlSettings.CACHE_WSDLS );
728 	}
729 	
730 	public void setCacheDefinitions( boolean cacheDefinitions )
731 	{
732 		getSettings().setBoolean( WsdlSettings.CACHE_WSDLS, cacheDefinitions );
733 	}
734 
735 	public boolean saveTo(String fileName) throws IOException
736 	{
737 		if( !isOpen() || isDisabled() )
738 			return false;
739 		
740 		String oldPath = path;
741 		path = fileName;
742 		boolean result = save();
743 		if( !result )
744 			path = oldPath;
745 		else
746 			remote = false;
747 		
748 		setProjectRoot(path);
749 		
750 		return result;
751 	}
752 
753 	@Override
754    public void release()
755 	{
756 		super.release();
757 		
758 		if( isOpen() )
759 		{
760 			endpointStrategy.release();
761 			
762 			for( WsdlTestSuite testSuite : testSuites )
763 				testSuite.release();
764 	
765 			for( WsdlInterface iface : interfaces )
766 				iface.release();
767 			
768 			for( WsdlMockService mockService : mockServices )
769 				mockService.release();
770 		}
771 		
772 		projectListeners.clear();
773 		
774 		if( afterLoadScriptEngine != null )
775 			afterLoadScriptEngine.release();
776 		
777 		if( beforeSaveScriptEngine != null )
778 			beforeSaveScriptEngine.release();
779 	}
780 
781 	public WsdlMockService addNewMockService( String name )
782 	{
783 		WsdlMockService mockService = new WsdlMockService( this, getConfig().addNewMockService());
784       mockService.setName( name );
785       mockServices.add( mockService );
786       fireMockServiceAdded( mockService );
787 
788       return mockService;
789 	}
790 
791 	public WsdlMockService getMockServiceAt( int index )
792 	{
793 		return mockServices.get( index );
794 	}
795 
796 	public WsdlMockService getMockServiceByName( String mockServiceName )
797 	{
798 		return (WsdlMockService) getWsdlModelItemByName( mockServices, mockServiceName );
799 	}
800 
801 	public int getMockServiceCount()
802 	{
803 		return mockServices.size();
804 	}
805 
806 	public void removeMockService(WsdlMockService mockService )
807    {
808       int ix = mockServices.indexOf( mockService );
809       mockServices.remove( ix );
810       
811       try
812       {
813       	fireMockServiceRemoved( mockService );
814       }
815       finally
816       {
817       	mockService.release();
818       	getConfig().removeMockService( ix );
819       }
820    }
821 
822 	public List<TestSuite> getTestSuiteList()
823 	{
824 		return new ArrayList<TestSuite>( testSuites );
825 	}
826 
827 	public List<MockService> getMockServiceList()
828 	{
829 		return new ArrayList<MockService>( mockServices );
830 	}
831 
832 	public List<Interface> getInterfaceList()
833 	{
834 		return new ArrayList<Interface>( interfaces );
835 	}
836 	
837 	public Map<String, Interface> getInterfaces()
838 	{
839 		Map<String, Interface> result = new HashMap<String, Interface>();
840 		for( Interface iface : interfaces )
841 			result.put( iface.getName(), iface );
842 
843 		return result;
844 	}
845 	
846 	public Map<String, TestSuite> getTestSuites()
847 	{
848 		Map<String, TestSuite> result = new HashMap<String, TestSuite>();
849 		for( TestSuite iface : testSuites )
850 			result.put( iface.getName(), iface );
851 
852 		return result;
853 	}
854 	
855 	public Map<String, MockService> getMockServices()
856 	{
857 		Map<String, MockService> result = new HashMap<String, MockService>();
858 		for( MockService mockService : mockServices )
859 			result.put( mockService.getName(), mockService );
860 
861 		return result;
862 	}
863 
864 	public void reload() throws SoapUIException
865 	{
866 		reload( path );
867 	}
868 	
869 	public void reload( String path ) throws SoapUIException
870 	{
871 		this.path = path;
872 		getWorkspace().reloadProject( this );
873 	}
874 
875    public boolean hasNature(String natureId)
876    {
877       Settings projectSettings = getSettings();
878       String projectNature = projectSettings.getString( ProjectSettings.PROJECT_NATURE, null );
879       return natureId.equals(projectNature);
880    }
881 
882 	public WsdlInterface importInterface( WsdlInterface iface, boolean importEndpoints, boolean createCopy )
883 	{
884 		iface.beforeSave();
885 		InterfaceConfig ifaceConfig = ( InterfaceConfig ) getConfig().addNewInterface().set( iface.getConfig().copy());
886 		if( ifaceConfig.isSetId() && createCopy )
887 			ifaceConfig.unsetId();
888 		
889 		WsdlInterface imported = new WsdlInterface( this, ifaceConfig );
890       interfaces.add( imported );
891       
892       if( iface.getProject() != this && importEndpoints )
893       {
894       	endpointStrategy.importEndpoints( iface );
895       }
896       
897       fireInterfaceAdded( imported );
898 
899       return imported;
900 	}
901 
902 	public WsdlTestSuite importTestSuite( WsdlTestSuite testSuite, String name, boolean createCopy )
903 	{
904 		testSuite.beforeSave();
905 		TestSuiteConfig testSuiteConfig = ( TestSuiteConfig ) getConfig().addNewTestSuite().set( testSuite.getConfig().copy() );
906 		testSuiteConfig.setName( name );
907 		if( testSuiteConfig.isSetId() && createCopy )
908 			testSuiteConfig.unsetId();
909 		
910 		testSuite = new WsdlTestSuite( this, testSuiteConfig );
911       testSuites.add( testSuite );
912       fireTestSuiteAdded( testSuite );
913 
914 		return testSuite;
915 	}
916 
917 	public WsdlMockService importMockService( WsdlMockService mockService, String name, boolean createCopy )
918 	{
919 		mockService.beforeSave();
920 		MockServiceConfig mockServiceConfig = ( MockServiceConfig ) getConfig().addNewMockService().set( mockService.getConfig().copy() );
921 		mockServiceConfig.setName( name );
922 		if( mockServiceConfig.isSetId() && createCopy )
923 			mockServiceConfig.unsetId();
924 		mockService = new WsdlMockService( this, mockServiceConfig);
925       mockServices.add( mockService );
926       fireMockServiceAdded( mockService );
927 
928       return mockService;
929 	}
930 
931 	public EndpointStrategy getEndpointStrategy()
932 	{
933 		return endpointStrategy;
934 	}
935 
936 	public boolean isOpen()
937 	{
938 		return open;
939 	}
940    
941    public List<? extends ModelItem> getChildren()
942    {
943       ArrayList<ModelItem> list = new ArrayList<ModelItem>();
944       list.addAll(getInterfaceList());
945       list.addAll(getTestSuiteList());
946       list.addAll(getMockServiceList());
947       return list;
948    }
949    
950    public void setAfterLoadScript( String script )
951 	{
952 		String oldScript = getAfterLoadScript();
953 
954 		if( !getConfig().isSetAfterLoadScript() )
955 			getConfig().addNewAfterLoadScript();
956 
957 		getConfig().getAfterLoadScript().setStringValue( script );
958 		if( afterLoadScriptEngine != null )
959 			afterLoadScriptEngine.setScript( script );
960 
961 		notifyPropertyChanged( AFTER_LOAD_SCRIPT_PROPERTY, oldScript, script );
962 	}
963 
964 	public String getAfterLoadScript()
965 	{
966 		return getConfig().isSetAfterLoadScript() ? getConfig().getAfterLoadScript().getStringValue() : null;
967 	}
968 
969 	public void setBeforeSaveScript( String script )
970 	{
971 		String oldScript = getBeforeSaveScript();
972 
973 		if( !getConfig().isSetBeforeSaveScript() )
974 			getConfig().addNewBeforeSaveScript();
975 
976 		getConfig().getBeforeSaveScript().setStringValue( script );
977 		if( beforeSaveScriptEngine != null )
978 			beforeSaveScriptEngine.setScript( script );
979 
980 		notifyPropertyChanged( BEFORE_SAVE_SCRIPT_PROPERTY, oldScript, script );
981 	}
982 
983 	public String getBeforeSaveScript()
984 	{
985 		return getConfig().isSetBeforeSaveScript() ? getConfig().getBeforeSaveScript().getStringValue() : null;
986 	}
987 	
988 	public Object runAfterLoadScript() throws Exception
989 	{
990 		String script = getAfterLoadScript();
991 		if( StringUtils.isNullOrEmpty( script ))
992 			return null;
993 		
994 		if( afterLoadScriptEngine == null )
995 		{
996 			afterLoadScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
997 			afterLoadScriptEngine.setScript( script );
998 		}
999 		
1000 		afterLoadScriptEngine.setVariable( "context", context );
1001 		afterLoadScriptEngine.setVariable( "project", this );
1002 		afterLoadScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
1003 		return afterLoadScriptEngine.run();
1004 	}
1005 
1006 	public Object runBeforeSaveScript() throws Exception
1007 	{
1008 		String script = getBeforeSaveScript();
1009 		if( StringUtils.isNullOrEmpty( script ))
1010 			return null;
1011 		
1012 		if( beforeSaveScriptEngine == null )
1013 		{
1014 			beforeSaveScriptEngine = SoapUIScriptEngineRegistry.create( SoapUIScriptEngineRegistry.GROOVY_ID, this );
1015 			beforeSaveScriptEngine.setScript( script );
1016 		}
1017 		
1018 		beforeSaveScriptEngine.setVariable( "context", context );
1019 		beforeSaveScriptEngine.setVariable( "project", this );
1020 		beforeSaveScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
1021 		return beforeSaveScriptEngine.run();
1022 	}
1023 
1024 	public PropertyExpansionContext getContext()
1025 	{
1026 		return context;
1027 	}
1028 
1029 	public DefaultWssContainer getWssContainer()
1030 	{
1031 		return wssContainer;
1032 	}
1033 }