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