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.util.ArrayList;
20  import java.util.HashSet;
21  import java.util.List;
22  import java.util.Set;
23  
24  import javax.swing.ImageIcon;
25  import javax.xml.namespace.QName;
26  
27  import org.apache.log4j.Logger;
28  import org.apache.xmlbeans.XmlException;
29  import org.apache.xmlbeans.XmlOptions;
30  
31  import com.eviware.soapui.SoapUI;
32  import com.eviware.soapui.config.InterfaceConfig;
33  import com.eviware.soapui.config.MockServiceConfig;
34  import com.eviware.soapui.config.ProjectConfig;
35  import com.eviware.soapui.config.SoapuiProjectDocumentConfig;
36  import com.eviware.soapui.config.TestSuiteConfig;
37  import com.eviware.soapui.impl.WorkspaceImpl;
38  import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
39  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlImporter;
40  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlLoader;
41  import com.eviware.soapui.model.iface.Interface;
42  import com.eviware.soapui.model.mock.MockService;
43  import com.eviware.soapui.model.project.Project;
44  import com.eviware.soapui.model.project.ProjectListener;
45  import com.eviware.soapui.model.settings.Settings;
46  import com.eviware.soapui.model.testsuite.TestSuite;
47  import com.eviware.soapui.settings.ProjectSettings;
48  import com.eviware.soapui.settings.UISettings;
49  import com.eviware.soapui.settings.WsdlSettings;
50  import com.eviware.soapui.support.SoapUIException;
51  import com.eviware.soapui.support.Tools;
52  import com.eviware.soapui.support.UISupport;
53  
54  /***
55   * WSDL project implementation
56   * 
57   * @author Ole.Matzura
58   */
59  
60  public class WsdlProject extends AbstractWsdlModelItem<ProjectConfig> implements Project
61  {
62     private WorkspaceImpl workspace;
63     private String path;
64     private List<WsdlInterface> interfaces = new ArrayList<WsdlInterface>();
65     private List<WsdlTestSuite> testSuites = new ArrayList<WsdlTestSuite>();
66     private List<WsdlMockService> mockServices = new ArrayList<WsdlMockService>();
67     private Set<ProjectListener> listeners = new HashSet<ProjectListener>();
68     private SoapuiProjectDocumentConfig projectDocument;
69  	private ImageIcon disabledIcon;
70  	private long lastModified;
71     
72     private final static Logger log = Logger.getLogger( WsdlProject.class );
73  
74     public WsdlProject() throws XmlException, IOException
75     {
76     	this( (WorkspaceImpl)null );
77     }
78  
79     public WsdlProject( String path ) throws XmlException, IOException, SoapUIException
80     {
81     	this( path, null );
82     }
83     
84     public WsdlProject( WorkspaceImpl workspace ) throws XmlException, IOException 
85     {
86     	super( null, workspace, "/project.gif" );
87        this.workspace = workspace;
88     	projectDocument = SoapuiProjectDocumentConfig.Factory.newInstance();
89     	
90     	setConfig( projectDocument.addNewSoapuiProject() );
91     }
92  
93     public WsdlProject(String path, WorkspaceImpl workspace ) throws SoapUIException
94     {
95     	this( path, workspace, true );
96     }
97     
98     public WsdlProject(String path, WorkspaceImpl workspace, boolean create ) throws SoapUIException
99     {
100    	super( null, workspace, "/project.gif" );
101    	
102       this.workspace = workspace;
103    	this.path = path;
104       File file = new File(path);
105       
106       if( file.exists())
107       {
108          loadProject( file );
109       }
110       else if( create )
111       {
112          projectDocument = SoapuiProjectDocumentConfig.Factory.newInstance();
113          setConfig( projectDocument.addNewSoapuiProject() );
114       }
115       else
116       {
117       	disabledIcon = UISupport.createImageIcon( "/disabledProject.gif" );
118       }
119       
120       setProjectRoot(path);
121    }
122 
123 	private void loadProject( File file ) throws SoapUIException
124 	{
125 		try
126 		{
127 			lastModified = file.lastModified();
128 			projectDocument = SoapuiProjectDocumentConfig.Factory.parse( file );
129 		}
130 		catch (Exception e)
131 		{
132 			throw new SoapUIException( "Failed to create project from file [" + file.getName() + "]", e );
133 		}
134 		
135 		setConfig( projectDocument.getSoapuiProject() );
136 		
137 		// removed cached definitions if caching is disabled
138 		if( !getSettings().getBoolean( WsdlSettings.CACHE_WSDLS ))
139 		{
140 			removeDefinitionCaches( projectDocument );
141 		}
142 		
143 		log.info( "Loaded project from [" + file.getAbsolutePath() + "]" );
144 		 
145 		List<InterfaceConfig> interfaceConfigs = getConfig().getInterfaceList();
146 		for (InterfaceConfig config : interfaceConfigs)
147 		{
148 		   interfaces.add( new WsdlInterface( this, config ));
149 		}
150 
151 		List<TestSuiteConfig> testSuiteConfigs = getConfig().getTestSuiteList();
152 		for( TestSuiteConfig config : testSuiteConfigs )
153 		{
154 		   testSuites.add( new WsdlTestSuite( this, config ));
155 		}
156 		
157 		List<MockServiceConfig> mockServiceConfigs = getConfig().getMockServiceList();
158 		for( MockServiceConfig config : mockServiceConfigs )
159 		{
160 		   mockServices.add( new WsdlMockService( this, config ));
161 		}
162 	}
163 
164 	private void setProjectRoot(String path)
165 	{
166 		if( path != null && projectDocument != null )
167       {
168       	int ix = path.lastIndexOf( File.separatorChar );
169       	if( ix > 0 )
170       		getSettings().setString( ProjectSettings.PROJECT_ROOT, path.substring( 0, ix ) );
171       }
172 	}
173 	
174 	@Override
175 	public ImageIcon getIcon()
176 	{
177 		if( projectDocument != null )
178 			return super.getIcon();
179 		else
180 			return disabledIcon;
181 	}
182 	
183 	@Override
184 	public String getName()
185 	{
186 		if( projectDocument != null )
187 			return super.getName();
188 		else
189 		{
190 			int ix = path.lastIndexOf( File.separatorChar );
191 			String name = ix == -1 ? path : path.substring( ix+1 );
192 			return name + " (disabled)";
193 		}
194 	}
195 	
196 	@Override
197 	public String getDescription()
198 	{
199 		return projectDocument == null ? getName() : super.getDescription();
200 	}
201 
202    public WorkspaceImpl getWorkspace()
203    {
204       return workspace;
205    }
206 
207 	public WsdlInterface getInterfaceAt(int index)
208    {
209       return interfaces.get( index );
210    }
211 
212    public WsdlInterface getInterfaceByName(String interfaceName)
213 	{
214 		return (WsdlInterface) getWsdlModelItemByName( interfaces, interfaceName );
215 	}
216 
217    public WsdlInterface getInterfaceByBindingName( QName bindingName )
218    {
219    	for( int c = 0; c < getInterfaceCount(); c++ )
220    	{
221    		if( getInterfaceAt( c ).getBindingName().equals( bindingName ))
222    			return getInterfaceAt( c );
223    	}
224    	
225    	return null;
226    }
227    
228 	public int getInterfaceCount()
229    {
230       return interfaces.size();
231    }
232 
233    public String getPath()
234 	{
235 		return path;
236 	}
237 
238 	public boolean save() throws IOException 
239    {
240 		if( projectDocument == null )
241 			return true;
242 		
243       if( path == null )
244       {
245          File file = UISupport.getFileDialogs().saveAs(this, "Save project " + getName());
246          if( file == null ) return false;
247 
248          path = file.getAbsolutePath();
249       }
250       
251       File projectFile = new File( path );
252       
253       while( projectFile.exists() && !projectFile.canWrite() )
254       {
255       	if( UISupport.confirm( "Project file [" + path + "] can not be written to, save to new file?", "Save Project" ))
256       	{
257       		projectFile = UISupport.getFileDialogs().saveAs(this, "Save project " + getName());
258             if( projectFile == null ) return false;
259 
260             path = projectFile.getAbsolutePath();
261       	}
262       	else return false;
263       }
264       
265       
266       // check modified 
267 		if( projectFile.exists() && lastModified != 0 && lastModified < projectFile.lastModified() )
268 		{
269 			if( !UISupport.confirm( 
270 						"Project file for [" + getName() + "] has been modified externally, overwrite?", 
271 						"Save Project" ))
272 				return false;
273 		}
274       
275    	long size = 0;
276    	
277    	if( projectFile.exists() && getSettings().getBoolean( UISettings.CREATE_BACKUP ))
278    	{
279    		createBackup( projectFile );
280    	}
281    	
282    	onSave();
283    	
284    	XmlOptions options = new XmlOptions();
285    	if( SoapUI.getSettings().getBoolean( WsdlSettings.PRETTY_PRINT_PROJECT_FILES ))
286    		options.setSavePrettyPrint();
287    	
288    	// check for caching
289    	if( !getSettings().getBoolean( WsdlSettings.CACHE_WSDLS ))
290    	{
291    		// no caching -> create copy and remove definition cachings
292    		SoapuiProjectDocumentConfig config = (SoapuiProjectDocumentConfig) projectDocument.copy();
293    		removeDefinitionCaches(config);
294    		
295    		config.getSoapuiProject().setSoapuiVersion( SoapUI.SOAPUI_VERSION );
296    		config.save( projectFile, options );
297    	}
298    	else
299    	{
300       	try
301 			{
302       		// save to temporary buffer to avoid corruption of file
303 				projectDocument.getSoapuiProject().setSoapuiVersion( SoapUI.SOAPUI_VERSION );
304 				ByteArrayOutputStream writer = new ByteArrayOutputStream( 8192 );
305 				projectDocument.save( writer, options );
306 				FileOutputStream out = new FileOutputStream( projectFile );
307 				writer.writeTo( out );
308 				out.close();
309 				size = writer.size();
310 			}
311 			catch (Throwable t)
312 			{
313 				SoapUI.logError( t );
314 				UISupport.showErrorMessage( "Failed to save project [" + getName() + "]: " + t.toString() );
315 				return false;
316 			}
317    	}
318    	
319    	lastModified = projectFile.lastModified();
320 		log.info( "Saved project [" + getName() + "] to [" + projectFile.getAbsolutePath() + " - " +
321 				size + " bytes" );
322 		setProjectRoot(path);
323 		return true;
324 }
325 
326 	public void onSave()
327 	{
328 		// notify
329    	for( WsdlInterface iface : interfaces )
330    		iface.onSave();
331    	
332    	for( WsdlTestSuite testSuite : testSuites )
333    		testSuite.onSave();
334    	
335    	for( WsdlMockService mockService : mockServices )
336    		mockService.onSave();
337 	}
338 
339 	private void createBackup(File projectFile) throws IOException
340 	{
341 		String backupFolderName = getSettings().getString( UISettings.BACKUP_FOLDER, "" );
342 		
343 		File backupFolder = new File( backupFolderName );
344 		if( !backupFolder.isAbsolute() )
345 		{
346 			backupFolder = new File( projectFile.getParentFile(), backupFolderName );
347 		}
348 		
349 		if( !backupFolder.exists() )
350 			backupFolder.mkdirs();
351 		
352 		File backupFile = new File( backupFolder, projectFile.getName() + ".backup" );
353 		log.info( "Backing up [" + projectFile + "] to [" + backupFile + "]" );
354 		
355 		Tools.copyFile( projectFile, backupFile, true );
356 	}
357 
358 	private void removeDefinitionCaches(SoapuiProjectDocumentConfig config)
359 	{
360 		for( InterfaceConfig ifaceConfig : config.getSoapuiProject().getInterfaceList() )
361 		{
362 			if( ifaceConfig.isSetDefinitionCache() )
363 			{
364 				log.info( "Removing definition cache from interface [" + ifaceConfig.getName() + "]" );
365 				ifaceConfig.unsetDefinitionCache();
366 			}
367 		}
368 	}
369 	
370 	public WsdlInterface [] importWsdl( String url, boolean createRequests ) throws SoapUIException
371 	{
372 		return importWsdl( url, createRequests, null, null );
373 	}
374    
375 	public WsdlInterface [] importWsdl( String url, boolean createRequests, WsdlLoader wsdlLoader ) throws SoapUIException
376 	{
377 		return importWsdl( url, createRequests, null, wsdlLoader );
378 	}
379 	
380    public WsdlInterface [] importWsdl( String url, boolean createRequests, QName bindingName, WsdlLoader wsdlLoader ) throws SoapUIException
381    {
382    	if( projectDocument == null )
383    		return null;
384    	
385    	WsdlInterface[] result;
386    	
387       try
388       {
389          result = WsdlImporter.getInstance().importWsdl( this, url, bindingName, wsdlLoader );
390       }
391       catch (Exception e)
392       {
393          log.error( "Error importing wsdl: " + e );
394          SoapUI.logError( e );
395          throw new SoapUIException( "Error importing wsdl", e );
396       }
397       
398       try
399       {      
400 			if( createRequests && result != null )
401          {
402          	for (WsdlInterface iface : result)
403 				{
404          		for( int c = 0; c < iface.getOperationCount(); c++ )
405          		{
406          			WsdlOperation operation = (WsdlOperation) iface.getOperationAt( c );
407          			WsdlRequest request = operation.addNewRequest( "Request 1");
408                   try
409                   {
410                      String requestContent = operation.createRequest( true );
411 							request.setRequestContent( requestContent);
412                   }
413                   catch (Exception e)
414                   {
415                      SoapUI.logError( e );
416                   }
417          		}
418 				}
419          }
420       }
421       catch (Exception e)
422       {
423       	log.error( "Error creating requests: " + e.getMessage() );
424          throw new SoapUIException( "Error creating requests", e );
425       }
426       
427       return result;
428    }
429    
430    public WsdlInterface addNewInterface( String name )
431    {
432       WsdlInterface iface = new WsdlInterface( this, getConfig().addNewInterface());
433       iface.setName( name );
434       interfaces.add( iface );
435       fireInterfaceAdded( iface );
436 
437       return iface;
438    }
439    
440    public void addProjectListener(ProjectListener listener)
441    {
442       listeners.add( listener );
443    }
444    
445    public void removeProjectListener(ProjectListener listener)
446    {
447       listeners.remove( listener );
448    }
449    
450    public void fireInterfaceAdded( WsdlInterface iface )
451    {
452       ProjectListener[] a = listeners.toArray( new ProjectListener[listeners.size()] );
453       
454       for (int c = 0; c < a.length; c++ )
455       {
456          a[c].interfaceAdded( iface );
457       }
458    }
459    
460    public void fireInterfaceRemoved( WsdlInterface iface )
461    {
462       ProjectListener[] a = listeners.toArray( new ProjectListener[listeners.size()] );
463       
464       for (int c = 0; c < a.length; c++ )
465       {
466          a[c].interfaceRemoved( iface );
467       }
468    }
469    
470    
471    public void fireTestSuiteAdded( WsdlTestSuite testSuite )
472    {
473       ProjectListener[] a = listeners.toArray( new ProjectListener[listeners.size()] );
474       
475       for (int c = 0; c < a.length; c++ )
476       {
477          a[c].testSuiteAdded( testSuite );
478       }
479    }
480    
481    public void fireTestSuiteRemoved( WsdlTestSuite testSuite )
482    {
483       ProjectListener[] a = listeners.toArray( new ProjectListener[listeners.size()] );
484       
485       for (int c = 0; c < a.length; c++ )
486       {
487          a[c].testSuiteRemoved( testSuite );
488       }
489    } 
490    
491    public void fireMockServiceAdded( WsdlMockService mockService )
492    {
493       ProjectListener[] a = listeners.toArray( new ProjectListener[listeners.size()] );
494       
495       for (int c = 0; c < a.length; c++ )
496       {
497          a[c].mockServiceAdded( mockService );
498       }
499    }
500    
501    public void fireMockServiceRemoved( WsdlMockService mockService )
502    {
503       ProjectListener[] a = listeners.toArray( new ProjectListener[listeners.size()] );
504       
505       for (int c = 0; c < a.length; c++ )
506       {
507          a[c].mockServiceRemoved( mockService );
508       }
509    }
510    
511    public void removeInterface(WsdlInterface iface )
512    {
513       int ix = interfaces.indexOf( iface );
514       interfaces.remove( ix );
515       try
516       {
517       	fireInterfaceRemoved( iface );
518       }
519       finally
520       {
521       	iface.release();
522       	getConfig().removeInterface( ix );
523       }
524    }
525    
526    public void removeTestSuite(WsdlTestSuite testSuite )
527    {
528       int ix = testSuites.indexOf( testSuite );
529       testSuites.remove( ix );
530       
531       try
532       {
533       	fireTestSuiteRemoved( testSuite );
534       }
535       finally
536       {
537       	testSuite.release();
538       	getConfig().removeTestSuite( ix );
539       }
540    }
541 
542    public boolean isDisabled()
543    {
544    	return projectDocument == null;
545    }
546    
547    public int getTestSuiteCount()
548    {
549       return testSuites.size();
550    }
551 
552    public WsdlTestSuite getTestSuiteAt(int index)
553    {
554       return testSuites.get( index );
555    }
556 
557    public WsdlTestSuite getTestSuiteByName(String testSuiteName)
558 	{
559 		return  ( WsdlTestSuite ) getWsdlModelItemByName( testSuites, testSuiteName );
560 	}
561 
562    public WsdlTestSuite addNewTestSuite(String name)
563    {
564       WsdlTestSuite testSuite = new WsdlTestSuite( this, getConfig().addNewTestSuite());
565       testSuite.setName( name );
566       testSuites.add( testSuite );
567       fireTestSuiteAdded( testSuite );
568 
569       return testSuite;
570    }
571 
572 	public WsdlTestSuite cloneTestSuite(WsdlTestSuite testSuite, String name)
573 	{
574 		testSuite.onSave();
575 		TestSuiteConfig testSuiteConfig = getConfig().addNewTestSuite();
576 		testSuiteConfig.set( testSuite.getConfig() );
577 		WsdlTestSuite newTestSuite = new WsdlTestSuite( this, testSuiteConfig );
578 		newTestSuite.setName( name );
579       testSuites.add( newTestSuite );
580       fireTestSuiteAdded( newTestSuite );
581 
582       return newTestSuite;
583 	}
584 	
585 	public boolean isCacheDefinitions()
586 	{
587 		return getSettings().getBoolean( WsdlSettings.CACHE_WSDLS );
588 	}
589 	
590 	public void setCacheDefinitions( boolean cacheDefinitions )
591 	{
592 		getSettings().setBoolean( WsdlSettings.CACHE_WSDLS, cacheDefinitions );
593 	}
594 
595 	public boolean saveTo(String fileName) throws IOException
596 	{
597 		String oldPath = path;
598 		path = fileName;
599 		boolean result = save();
600 		if( !result )
601 			path = oldPath;
602 		
603 		setProjectRoot(path);
604 		
605 		return result;
606 	}
607 
608 	public void release()
609 	{
610 		super.release();
611 		
612 		for( WsdlTestSuite testSuite : testSuites )
613 			testSuite.release();
614 
615 		for( WsdlInterface iface : interfaces )
616 			iface.release();
617 		
618 		for( WsdlMockService mockService : mockServices )
619 			mockService.release();
620 	}
621 
622 	public WsdlMockService cloneMockService( WsdlMockService mockService, String name )
623 	{
624 		mockService.onSave();
625 		MockServiceConfig testSuiteConfig = getConfig().addNewMockService();
626 		testSuiteConfig.set( mockService.getConfig() );
627 		WsdlMockService newMockService = new WsdlMockService( this, testSuiteConfig );
628 		newMockService.setName( name );
629       mockServices.add( newMockService );
630       fireMockServiceAdded( newMockService );
631 
632       return newMockService;
633 	}
634 	
635 	public WsdlMockService addNewMockService( String name )
636 	{
637 		WsdlMockService mockService = new WsdlMockService( this, getConfig().addNewMockService());
638       mockService.setName( name );
639       mockServices.add( mockService );
640       fireMockServiceAdded( mockService );
641 
642       return mockService;
643 	}
644 
645 	public WsdlMockService getMockServiceAt( int index )
646 	{
647 		return mockServices.get( index );
648 	}
649 
650 	public WsdlMockService getMockServiceByName( String mockServiceName )
651 	{
652 		return (WsdlMockService) getWsdlModelItemByName( mockServices, mockServiceName );
653 	}
654 
655 	public int getMockServiceCount()
656 	{
657 		return mockServices.size();
658 	}
659 
660 	public void removeMockService(WsdlMockService mockService )
661    {
662       int ix = mockServices.indexOf( mockService );
663       mockServices.remove( ix );
664       
665       try
666       {
667       	fireMockServiceRemoved( mockService );
668       }
669       finally
670       {
671       	mockService.release();
672       	getConfig().removeMockService( ix );
673       }
674    }
675 
676 	public List<TestSuite> getTestSuites()
677 	{
678 		return new ArrayList<TestSuite>( testSuites );
679 	}
680 
681 	public List<MockService> getMockServices()
682 	{
683 		return new ArrayList<MockService>( mockServices );
684 	}
685 
686 	public List<Interface> getInterfaces()
687 	{
688 		return new ArrayList<Interface>( interfaces );
689 	}
690 
691 	public void reload() throws SoapUIException
692 	{
693 		reload( new File( path ));
694 	}
695 	
696 	public void reload( File file ) throws SoapUIException
697 	{
698 		this.path = file.getAbsolutePath();
699 		getWorkspace().reloadProject( this );
700 	}
701 
702    public boolean hasNature(String natureId)
703    {
704       Settings projectSettings = getSettings();
705       String projectNature = projectSettings.getString( ProjectSettings.PROJECT_NATURE, null );
706       return natureId.equals(projectNature);
707    }
708 
709 	public WsdlInterface importInterface( WsdlInterface iface )
710 	{
711 		iface.onSave();
712 		InterfaceConfig ifaceConfig = ( InterfaceConfig ) getConfig().addNewInterface().set( iface.getConfig().copy());
713 		iface = new WsdlInterface( this, ifaceConfig );
714       interfaces.add( iface );
715       fireInterfaceAdded( iface );
716 
717       return iface;
718 	}
719 
720 	public WsdlTestSuite importTestSuite( WsdlTestSuite testSuite, String name )
721 	{
722 		testSuite.onSave();
723 		TestSuiteConfig testSuiteConfig = ( TestSuiteConfig ) getConfig().addNewTestSuite().set( testSuite.getConfig().copy() );
724 		testSuiteConfig.setName( name );
725 		testSuite = new WsdlTestSuite( this, testSuiteConfig );
726       testSuites.add( testSuite );
727       fireTestSuiteAdded( testSuite );
728 
729 		return testSuite;
730 	}
731 
732 	public WsdlMockService importMockService( WsdlMockService mockService, String name )
733 	{
734 		mockService.onSave();
735 		MockServiceConfig mockServiceConfig = ( MockServiceConfig ) getConfig().addNewMockService().set( mockService.getConfig().copy() );
736 		mockServiceConfig.setName( name );
737 		mockService = new WsdlMockService( this, mockServiceConfig);
738       mockServices.add( mockService );
739       fireMockServiceAdded( mockService );
740 
741       return mockService;
742 	}
743 }