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