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;
14  
15  import java.io.File;
16  import java.io.IOException;
17  import java.util.ArrayList;
18  import java.util.HashSet;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.Set;
22  
23  import javax.swing.ImageIcon;
24  
25  import org.apache.log4j.Logger;
26  import org.apache.xmlbeans.XmlException;
27  import org.apache.xmlbeans.XmlOptions;
28  
29  import com.eviware.soapui.SoapUI;
30  import com.eviware.soapui.config.SoapuiWorkspaceDocumentConfig;
31  import com.eviware.soapui.config.WorkspaceProjectConfig;
32  import com.eviware.soapui.impl.settings.XmlBeansSettingsImpl;
33  import com.eviware.soapui.impl.wsdl.WsdlProject;
34  import com.eviware.soapui.model.ModelItem;
35  import com.eviware.soapui.model.project.Project;
36  import com.eviware.soapui.model.settings.Settings;
37  import com.eviware.soapui.model.support.AbstractModelItem;
38  import com.eviware.soapui.model.workspace.Workspace;
39  import com.eviware.soapui.model.workspace.WorkspaceListener;
40  import com.eviware.soapui.support.SoapUIException;
41  import com.eviware.soapui.support.UISupport;
42  
43  /***
44   * Default Workspace implementation
45   * 
46   * @author Ole.Matzura
47   */
48  
49  public class WorkspaceImpl extends AbstractModelItem implements Workspace
50  {
51  	private final static Logger log = Logger.getLogger( WorkspaceImpl.class );
52  	private List<Project> projectList = new ArrayList<Project>();
53  	private SoapuiWorkspaceDocumentConfig workspaceConfig;
54  	private String path = null;
55  	private Set<WorkspaceListener> listeners = new HashSet<WorkspaceListener>();
56  	private ImageIcon workspaceIcon;
57  	private XmlBeansSettingsImpl settings;
58  
59  	public WorkspaceImpl( String path ) throws XmlException, IOException
60  	{
61  		File file = new File( path );
62  		this.path = file.getAbsolutePath();
63  		loadWorkspace( file );
64  		workspaceIcon = UISupport.createImageIcon( "/workspace.gif" );
65  	}
66  
67  	public void changeWorkspace( File file ) throws SoapUIException
68  	{
69  		// check first if valid workspace file
70  		if( file.exists() )
71  		{
72  			try
73  			{
74  				SoapuiWorkspaceDocumentConfig.Factory.parse( file );
75  			}
76  			catch( Exception e )
77  			{
78  				throw new SoapUIException( "Failed to load workspace: " + e.toString() );
79  			}
80  		}
81  		
82  		while( projectList.size() > 0 )
83  		{
84  			Project project = projectList.remove( 0 );
85  			try
86  			{
87  				fireProjectRemoved( project );
88  			}
89  			finally
90  			{
91  				project.release();
92  			}
93  		}
94  		
95  		try
96  		{
97  			String oldName = getName();
98  		
99  			loadWorkspace( file );
100 			this.path = file.getAbsolutePath();
101 			
102 			for( Project project : projectList )
103 			{
104 				fireProjectAdded( project );
105 			}
106 			
107 			notifyPropertyChanged( ModelItem.NAME_PROPERTY, oldName, getName() );
108 		}
109 		catch(Exception e )
110 		{
111 			SoapUI.logError( e );
112 		}
113 	}
114 	
115 	private void loadWorkspace( File file ) throws XmlException, IOException
116 	{
117 		if( file.exists() )
118 		{
119 			log.info( "Loading workspace from [" + file.getAbsolutePath() + "]" );
120 			workspaceConfig = SoapuiWorkspaceDocumentConfig.Factory.parse( file );
121 			if( workspaceConfig.getSoapuiWorkspace().getSettings() == null )
122 				workspaceConfig.getSoapuiWorkspace().addNewSettings();
123 
124 			settings = new XmlBeansSettingsImpl( this, SoapUI.getSettings(), workspaceConfig
125 						.getSoapuiWorkspace().getSettings() );
126 
127 			List<WorkspaceProjectConfig> projects = workspaceConfig.getSoapuiWorkspace()
128 						.getProjectList();
129 			for( int i = 0; i < projects.size(); i++ )
130 			{
131 				WorkspaceProjectConfig wsc = projects.get( i );
132 				String str = wsc.getStringValue();
133 
134 				if( new File( str ).exists() )
135 				{
136 					try
137 					{
138 						WsdlProject project = new WsdlProject( str, this );
139 						projectList.add( project );
140 					}
141 					catch( Exception e )
142 					{
143 						UISupport.showErrorMessage( "Failed to load project [" + str
144 									+ "]\nfrom workspace; " + e.getMessage() );
145 
146 						SoapUI.logError( e );
147 					}
148 				}
149 				else
150 				{
151 					UISupport.showErrorMessage( "project [" + str
152 								+ "]\nnot found, disabling in workspace" );
153 					
154 					try
155 					{
156 						WsdlProject project = new WsdlProject( str, this, false );
157 						projectList.add( project );
158 					}
159 					catch( Exception e )
160 					{
161 						SoapUI.logError( e );
162 					}
163 				}
164 			}
165 		}
166 		else
167 		{
168 			workspaceConfig = SoapuiWorkspaceDocumentConfig.Factory.newInstance();
169 			workspaceConfig.addNewSoapuiWorkspace().setName( "Projects" );
170 			workspaceConfig.getSoapuiWorkspace().addNewSettings();
171 
172 			settings = new XmlBeansSettingsImpl( this, SoapUI.getSettings(), workspaceConfig
173 						.getSoapuiWorkspace().getSettings() );
174 		}
175 	}
176 
177 	public void setPath( String path )
178 	{
179 		this.path = path;
180 	}
181 
182 	public Project[] getProjects()
183 	{
184 		return projectList.toArray( new Project[projectList.size()] );
185 	}
186 
187 	public void setName( String name )
188 	{
189 		String oldName = getName();
190 		
191 		workspaceConfig.getSoapuiWorkspace().setName( name );
192 		notifyPropertyChanged( ModelItem.NAME_PROPERTY, oldName, name );
193 	}
194 	
195 	public void setDescription( String description )
196 	{
197 		String oldDescription = getDescription();
198 		
199 		workspaceConfig.getSoapuiWorkspace().setDescription( description );
200 		notifyPropertyChanged( ModelItem.DESCRIPTION_PROPERTY, oldDescription, description );
201 	}
202 
203 	public String getName()
204 	{
205 		return workspaceConfig.getSoapuiWorkspace().isSetName() ? workspaceConfig.getSoapuiWorkspace().getName() : "Projects";
206 	}
207 
208 	public Project getProjectAt( int index )
209 	{
210 		return projectList.get( index );
211 	}
212 
213 	public Project getProjectByName( String projectName )
214 	{
215 		for( Project project : projectList )
216 		{
217 			if( project.getName().equals( projectName ) )
218 				return project;
219 		}
220 
221 		return null;
222 	}
223 
224 	public int getProjectCount()
225 	{
226 		return projectList.size();
227 	}
228 
229 	public void onClose()
230 	{
231 		save( false );
232 	}
233 
234 	public void save( boolean workspaceOnly )
235 	{
236 		try
237 		{
238 			List<WorkspaceProjectConfig> projects = new ArrayList<WorkspaceProjectConfig>();
239 
240 			// save projects first
241 			for( int c = 0; c < getProjectCount(); c++ )
242 			{
243 				WsdlProject project = ( WsdlProject ) getProjectAt( c );
244 
245 				if( !workspaceOnly )
246 				{
247 					if( SoapUI.getTestMonitor().hasRunningTests( project ))
248 					{
249 						log.warn( "Project [" + project.getName() + "] has running tests.. skipping save" );
250 					}
251 					else
252 					{
253 						project.save();
254 					}
255 				}
256 
257 				String path = project.getPath();
258 				if( path != null )
259 				{
260 					WorkspaceProjectConfig wpc = WorkspaceProjectConfig.Factory.newInstance();
261 					wpc.setStringValue( path );
262 					projects.add( wpc );
263 				}
264 			}
265 
266 			if( path == null )
267 			{
268 				File file = UISupport.getFileDialogs().saveAs( this, "Save workspace", ".xml",
269 							"XML Files (*.xml)", null );
270 				if( file == null )
271 					return;
272 
273 				path = file.getAbsolutePath();
274 			}
275 
276 			workspaceConfig.getSoapuiWorkspace().setProjectArray(
277 						projects.toArray( new WorkspaceProjectConfig[projects.size()] ) );
278 			workspaceConfig.getSoapuiWorkspace().setSoapuiVersion( SoapUI.SOAPUI_VERSION );
279 
280 			File workspaceFile = new File( path );
281 			workspaceConfig.save( workspaceFile, new XmlOptions().setSavePrettyPrint() );
282 
283 			log.info( "Saved workspace to [" + workspaceFile.getAbsolutePath() + "]" );
284 		}
285 		catch( IOException e )
286 		{
287 			log.error( "Failed to save workspace: " + e.getMessage(), e );
288 		}
289 	}
290 
291 	public void addWorkspaceListener( WorkspaceListener listener )
292 	{
293 		listeners.add( listener );
294 	}
295 
296 	public void removeWorkspaceListener( WorkspaceListener listener )
297 	{
298 		listeners.remove( listener );
299 	}
300 
301 	public Project importProject( String fileName ) throws SoapUIException
302 	{
303 		File projectFile = new File( fileName );
304 
305 		WsdlProject project = new WsdlProject( projectFile.getAbsolutePath(), this );
306 		projectList.add( project );
307 
308 		fireProjectAdded( project );
309 
310 		save( true );
311 
312 		return project;
313 	}
314 
315 	public WsdlProject createProject( String name ) throws SoapUIException
316 	{
317 		File projectFile = new File( createProjectFileName( name ) );
318 		File file = UISupport.getFileDialogs().saveAs( this, "Create Project", ".xml",
319 					"XML Files (*.xml)", projectFile );
320 		if( file == null )
321 			return null;
322 
323 		return ( WsdlProject ) createProject( name, file );
324 	}
325 
326 	public Project createProject( String name, File file ) throws SoapUIException
327 	{
328 		File projectFile = file;
329 		while( projectFile.exists() )
330 		{
331 			Boolean result = Boolean.FALSE;
332 			while( !result.booleanValue() )
333 			{
334 				result = UISupport.confirmOrCancel( "Project File exists, overwrite?", "Overwrite Project?" );
335 				if( result == null )
336 					return null;
337 				if( result.booleanValue() )
338 				{
339 					projectFile.delete();
340 				}
341 				else
342 				{
343 					projectFile = UISupport.getFileDialogs().saveAs( this, "Create Project", ".xml",
344 								"XML Files (*.xml)", projectFile );
345 					if( projectFile == null )
346 						return null;
347 					else
348 						break;
349 				}
350 			}
351 		}
352 
353 		WsdlProject project = new WsdlProject( projectFile.getAbsolutePath(), this );
354 
355 		project.setName( name );
356 		projectList.add( project );
357 
358 		fireProjectAdded( project );
359 
360 		try
361 		{
362 			project.save();
363 		}
364 		catch( IOException e )
365 		{
366 			log.error( "Failed to save project: " + e.getMessage(), e );
367 		}
368 		save( true );
369 
370 		return project;
371 	}
372 
373 	private void fireProjectAdded( Project project )
374 	{
375 		for( Iterator<WorkspaceListener> iter = listeners.iterator(); iter.hasNext(); )
376 		{
377 			WorkspaceListener listener = iter.next();
378 			listener.projectAdded( project );
379 		}
380 	}
381 
382 	private String createProjectFileName( String name )
383 	{
384 		StringBuffer result = new StringBuffer();
385 		result.append( name );
386 		result.append( "-soapui-project.xml" );
387 		return result.toString();
388 	}
389 
390 	public void removeProject( Project project )
391 	{
392 		int ix = projectList.indexOf( project );
393 		if( ix == -1 )
394 			throw new RuntimeException( "Project [" + project.getName()
395 						+ "] not available in workspace for removal" );
396 
397 		projectList.remove( ix );
398 
399 		try
400 		{
401 			fireProjectRemoved( project );
402 		}
403 		finally
404 		{
405 			project.release();
406 			workspaceConfig.getSoapuiWorkspace().removeProject( ix );
407 		}
408 	}
409 	
410 	public void reloadProject( WsdlProject project ) throws SoapUIException
411 	{
412 		int ix = projectList.indexOf( project );
413 		if( ix == -1 )
414 			throw new RuntimeException( "Project [" + project.getName()
415 						+ "] not available in workspace for removal" );
416 
417 		projectList.remove( ix );
418 		fireProjectRemoved( project );
419 		
420 		project.release();
421 		project = new WsdlProject( project.getPath(), this );
422 		
423 		projectList.add( ix, project );
424 
425 		fireProjectAdded( project );
426 
427 		workspaceConfig.getSoapuiWorkspace().getProjectArray( ix ).setStringValue( project.getPath() );
428 		save( true );
429 	}
430 
431 	private void fireProjectRemoved( Project project )
432 	{
433 		WorkspaceListener[] listenerArray = listeners
434 					.toArray( new WorkspaceListener[listeners.size()] );
435 		for( int c = 0; c < listenerArray.length; c++ )
436 		{
437 			listenerArray[c].projectRemoved( project );
438 		}
439 	}
440 
441 	public ImageIcon getIcon()
442 	{
443 		return workspaceIcon;
444 	}
445 
446 	public Settings getSettings()
447 	{
448 		return settings;
449 	}
450 
451 	public int getIndexOfProject( Project project )
452 	{
453 		return projectList.indexOf( project );
454 	}
455 
456 	public String getPath()
457 	{
458 		return path;
459 	}
460 
461 	public void release()
462 	{
463 		settings.release();
464 
465 		for( Project project : projectList )
466 			project.release();
467 	}
468 
469 	public List<? extends ModelItem> getProjectList()
470 	{
471 		return projectList;
472 	}
473 
474 	public String getDescription()
475 	{
476 		return workspaceConfig.getSoapuiWorkspace().getDescription();
477 	}
478 
479 }