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.config.WorkspaceProjectConfig.Status;
33  import com.eviware.soapui.config.WorkspaceProjectConfig.Type;
34  import com.eviware.soapui.impl.settings.XmlBeansSettingsImpl;
35  import com.eviware.soapui.impl.wsdl.WsdlProject;
36  import com.eviware.soapui.model.ModelItem;
37  import com.eviware.soapui.model.project.Project;
38  import com.eviware.soapui.model.settings.Settings;
39  import com.eviware.soapui.model.support.AbstractModelItem;
40  import com.eviware.soapui.model.workspace.Workspace;
41  import com.eviware.soapui.model.workspace.WorkspaceListener;
42  import com.eviware.soapui.settings.UISettings;
43  import com.eviware.soapui.support.SoapUIException;
44  import com.eviware.soapui.support.UISupport;
45  
46  /***
47   * Default Workspace implementation
48   * 
49   * @author Ole.Matzura
50   */
51  
52  public class WorkspaceImpl extends AbstractModelItem implements Workspace
53  {
54  	private final static Logger log = Logger.getLogger( WorkspaceImpl.class );
55  	private List<Project> projectList = new ArrayList<Project>();
56  	private SoapuiWorkspaceDocumentConfig workspaceConfig;
57  	private String path = null;
58  	private Set<WorkspaceListener> listeners = new HashSet<WorkspaceListener>();
59  	private ImageIcon workspaceIcon;
60  	private XmlBeansSettingsImpl settings;
61  
62  	public WorkspaceImpl( String path ) throws XmlException, IOException
63  	{
64  		File file = new File( path );
65  		this.path = file.getAbsolutePath();
66  		loadWorkspace( file );
67  		workspaceIcon = UISupport.createImageIcon( "/workspace.gif" );
68  	}
69  
70  	public void switchWorkspace( File file ) throws SoapUIException
71  	{
72  		// check first if valid workspace file
73  		if( file.exists() )
74  		{
75  			try
76  			{
77  				SoapuiWorkspaceDocumentConfig.Factory.parse( file );
78  			}
79  			catch( Exception e )
80  			{
81  				throw new SoapUIException( "Failed to load workspace: " + e.toString() );
82  			}
83  		}
84  		
85  		fireWorkspaceSwitching();
86  		
87  		while( projectList.size() > 0 )
88  		{
89  			Project project = projectList.remove( 0 );
90  			try
91  			{
92  				fireProjectRemoved( project );
93  			}
94  			finally
95  			{
96  				project.release();
97  			}
98  		}
99  		
100 		try
101 		{
102 			String oldName = getName();
103 		
104 			loadWorkspace( file );
105 			this.path = file.getAbsolutePath();
106 			
107 			for( Project project : projectList )
108 			{
109 				fireProjectAdded( project );
110 			}
111 			
112 			notifyPropertyChanged( ModelItem.NAME_PROPERTY, oldName, getName() );
113 		}
114 		catch(Exception e )
115 		{
116 			SoapUI.logError( e );
117 		}
118 		
119 		fireWorkspaceSwitched();
120 	}
121 	
122 	private void loadWorkspace( File file ) throws XmlException, IOException
123 	{
124 		if( file.exists() )
125 		{
126 			log.info( "Loading workspace from [" + file.getAbsolutePath() + "]" );
127 			workspaceConfig = SoapuiWorkspaceDocumentConfig.Factory.parse( file );
128 			if( workspaceConfig.getSoapuiWorkspace().getSettings() == null )
129 				workspaceConfig.getSoapuiWorkspace().addNewSettings();
130 
131 			settings = new XmlBeansSettingsImpl( this, SoapUI.getSettings(), workspaceConfig
132 						.getSoapuiWorkspace().getSettings() );
133 
134 			boolean closeOnStartup = getSettings().getBoolean( UISettings.CLOSE_PROJECTS );
135 			List<WorkspaceProjectConfig> projects = workspaceConfig.getSoapuiWorkspace().getProjectList();
136 			for( int i = 0; i < projects.size(); i++ )
137 			{
138 				WorkspaceProjectConfig wsc = projects.get( i );
139 				String str = wsc.getStringValue();
140 
141 				try
142 				{
143 					WsdlProject project = new WsdlProject( str, this, false, !closeOnStartup &&
144 								wsc.getStatus() != Status.CLOSED && wsc.getType() != Type.REMOTE, wsc.getName() );
145 					
146 					projectList.add( project );
147 				}
148 				catch( Exception e )
149 				{
150 					UISupport.showErrorMessage( "Failed to load project [" + str
151 								+ "]\nin workspace; " + e.getMessage() );
152 
153 					SoapUI.logError( e );
154 				}
155 			}
156 		}
157 		else
158 		{
159 			workspaceConfig = SoapuiWorkspaceDocumentConfig.Factory.newInstance();
160 			workspaceConfig.addNewSoapuiWorkspace().setName( "Projects" );
161 			workspaceConfig.getSoapuiWorkspace().addNewSettings();
162 
163 			settings = new XmlBeansSettingsImpl( this, SoapUI.getSettings(), workspaceConfig
164 						.getSoapuiWorkspace().getSettings() );
165 		}
166 	}
167 
168 	public void setPath( String path )
169 	{
170 		this.path = path;
171 	}
172 
173 	public Project[] getProjects()
174 	{
175 		return projectList.toArray( new Project[projectList.size()] );
176 	}
177 
178 	public void setName( String name )
179 	{
180 		String oldName = getName();
181 		
182 		workspaceConfig.getSoapuiWorkspace().setName( name );
183 		notifyPropertyChanged( ModelItem.NAME_PROPERTY, oldName, name );
184 	}
185 	
186 	public void setDescription( String description )
187 	{
188 		String oldDescription = getDescription();
189 		
190 		workspaceConfig.getSoapuiWorkspace().setDescription( description );
191 		notifyPropertyChanged( ModelItem.DESCRIPTION_PROPERTY, oldDescription, description );
192 	}
193 
194 	public String getName()
195 	{
196 		return workspaceConfig.getSoapuiWorkspace().isSetName() ? workspaceConfig.getSoapuiWorkspace().getName() : "Projects";
197 	}
198 
199 	public Project getProjectAt( int index )
200 	{
201 		return projectList.get( index );
202 	}
203 
204 	public Project getProjectByName( String projectName )
205 	{
206 		for( Project project : projectList )
207 		{
208 			if( project.getName().equals( projectName ) )
209 				return project;
210 		}
211 
212 		return null;
213 	}
214 
215 	public int getProjectCount()
216 	{
217 		return projectList.size();
218 	}
219 
220 	public void onClose()
221 	{
222 		save( false );
223 	}
224 
225 	public void save( boolean workspaceOnly )
226 	{
227 		save( workspaceOnly, false );
228 	}
229 	
230 	public void save( boolean workspaceOnly, boolean skipProjectsWithRunningTests )
231 	{
232 		try
233 		{
234 			List<WorkspaceProjectConfig> projects = new ArrayList<WorkspaceProjectConfig>();
235 
236 			// save projects first
237 			for( int c = 0; c < getProjectCount(); c++ )
238 			{
239 				WsdlProject project = ( WsdlProject ) getProjectAt( c );
240 
241 				if( !workspaceOnly  )
242 				{
243 					if( skipProjectsWithRunningTests && SoapUI.getTestMonitor().hasRunningTests( project ))
244 					{
245 						log.warn( "Project [" + project.getName() + "] has running tests.. skipping save" );
246 					}
247 					else
248 					{
249 						String path = project.getPath();
250 						if( path == null )
251 						{
252 							if( UISupport.confirm( "Project [" + project.getName() + "] has not been saved, save now?", "Save Project" ))
253 							{
254 								project.save();
255 							}
256 						}
257 						else
258 						{
259 							project.save();
260 						}
261 					}
262 				}
263 
264 				String path = project.getPath();
265 				if( path != null )
266 				{
267 					WorkspaceProjectConfig wpc = WorkspaceProjectConfig.Factory.newInstance();
268 					wpc.setStringValue( path );
269 					if( project.isRemote() )
270 						wpc.setType( Type.REMOTE );
271 					
272 					if( !project.isOpen() )
273 						wpc.setStatus( Status.CLOSED );
274 					
275 					wpc.setName( project.getName() );
276 					projects.add( wpc );
277 				}
278 			}
279 
280 			if( path == null )
281 			{
282 				File file = UISupport.getFileDialogs().saveAs( this, "Save workspace", ".xml",
283 							"XML Files (*.xml)", null );
284 				if( file == null )
285 					return;
286 
287 				path = file.getAbsolutePath();
288 			}
289 
290 			workspaceConfig.getSoapuiWorkspace().setProjectArray(
291 						projects.toArray( new WorkspaceProjectConfig[projects.size()] ) );
292 			workspaceConfig.getSoapuiWorkspace().setSoapuiVersion( SoapUI.SOAPUI_VERSION );
293 
294 			File workspaceFile = new File( path );
295 			workspaceConfig.save( workspaceFile, new XmlOptions().setSavePrettyPrint() );
296 
297 			log.info( "Saved workspace to [" + workspaceFile.getAbsolutePath() + "]" );
298 		}
299 		catch( IOException e )
300 		{
301 			log.error( "Failed to save workspace: " + e.getMessage(), e );
302 		}
303 	}
304 
305 	public void addWorkspaceListener( WorkspaceListener listener )
306 	{
307 		listeners.add( listener );
308 	}
309 
310 	public void removeWorkspaceListener( WorkspaceListener listener )
311 	{
312 		listeners.remove( listener );
313 	}
314 
315 	public Project importProject( String fileName ) throws SoapUIException
316 	{
317 		File projectFile = new File( fileName );
318 
319 		WsdlProject project = new WsdlProject( projectFile.getAbsolutePath(), this );
320 		projectList.add( project );
321 		fireProjectAdded( project );
322 
323 		save( true );
324 
325 		return project;
326 	}
327 
328 	
329 	public WsdlProject createProject( String name ) throws SoapUIException
330 	{
331 		File projectFile = new File( createProjectFileName( name ) );
332 		File file = UISupport.getFileDialogs().saveAs( this, "Create Project", ".xml",
333 					"XML Files (*.xml)", projectFile );
334 		if( file == null )
335 			return null;
336 
337 		return createProject( name, file );
338 	}
339 
340 	public WsdlProject createProject( String name, File file ) throws SoapUIException
341 	{
342 		File projectFile = file;
343 		while( projectFile != null && projectFile.exists() )
344 		{
345 			Boolean result = Boolean.FALSE;
346 			while( !result.booleanValue() )
347 			{
348 				result = UISupport.confirmOrCancel( "Project File exists, overwrite?", "Overwrite Project?" );
349 				if( result == null )
350 					return null;
351 				if( result.booleanValue() )
352 				{
353 					projectFile.delete();
354 				}
355 				else
356 				{
357 					projectFile = UISupport.getFileDialogs().saveAs( this, "Create Project", ".xml",
358 								"XML Files (*.xml)", projectFile );
359 					if( projectFile == null )
360 						return null;
361 					else
362 						break;
363 				}
364 			}
365 		}
366 
367 		WsdlProject project = new WsdlProject( projectFile == null ? null : projectFile.getAbsolutePath(), this );
368 
369 		project.setName( name );
370 		projectList.add( project );
371 
372 		fireProjectAdded( project );
373 
374 		try
375 		{
376 			if( projectFile != null )
377 				project.save();
378 		}
379 		catch( IOException e )
380 		{
381 			log.error( "Failed to save project: " + e.getMessage(), e );
382 		}
383 //		save( true );
384 
385 		return project;
386 	}
387 
388 	private void fireProjectAdded( Project project )
389 	{
390 		for( Iterator<WorkspaceListener> iter = listeners.iterator(); iter.hasNext(); )
391 		{
392 			WorkspaceListener listener = iter.next();
393 			listener.projectAdded( project );
394 		}
395 	}
396 	
397 	private void fireWorkspaceSwitching()
398 	{
399 		for( Iterator<WorkspaceListener> iter = listeners.iterator(); iter.hasNext(); )
400 		{
401 			WorkspaceListener listener = iter.next();
402 			listener.workspaceSwitching( this );
403 		}
404 	}
405 	
406 	private void fireWorkspaceSwitched()
407 	{
408 		for( Iterator<WorkspaceListener> iter = listeners.iterator(); iter.hasNext(); )
409 		{
410 			WorkspaceListener listener = iter.next();
411 			listener.workspaceSwitched( this );
412 		}
413 	}
414 
415 	private String createProjectFileName( String name )
416 	{
417 		return name + "-soapui-project.xml";
418 	}
419 
420 	public void removeProject( Project project )
421 	{
422 		int ix = projectList.indexOf( project );
423 		if( ix == -1 )
424 			throw new RuntimeException( "Project [" + project.getName()
425 						+ "] not available in workspace for removal" );
426 
427 		projectList.remove( ix );
428 
429 		try
430 		{
431 			fireProjectRemoved( project );
432 		}
433 		finally
434 		{
435 			project.release();
436 //			workspaceConfig.getSoapuiWorkspace().removeProject( ix );
437 		}
438 	}
439 	
440 	public Project reloadProject( Project project ) throws SoapUIException
441 	{
442 		int ix = projectList.indexOf( project );
443 		if( ix == -1 )
444 			throw new RuntimeException( "Project [" + project.getName()
445 						+ "] not available in workspace for reload" );
446 
447 		projectList.remove( ix );
448 		fireProjectRemoved( project );
449 		
450 		String tempName = project.getName();
451 		project.release();
452 		project = new WsdlProject( project.getPath(), this, false, true, tempName );
453 		
454 		projectList.add( ix, project );
455 
456 		fireProjectAdded( project );
457 
458 //		workspaceConfig.getSoapuiWorkspace().getProjectArray( ix ).setStringValue( project.getPath() );
459 		
460 		return project;
461 	}
462 
463 	private void fireProjectRemoved( Project project )
464 	{
465 		WorkspaceListener[] listenerArray = listeners
466 					.toArray( new WorkspaceListener[listeners.size()] );
467 		for( int c = 0; c < listenerArray.length; c++ )
468 		{
469 			listenerArray[c].projectRemoved( project );
470 		}
471 	}
472 
473 	public ImageIcon getIcon()
474 	{
475 		return workspaceIcon;
476 	}
477 
478 	public Settings getSettings()
479 	{
480 		return settings;
481 	}
482 
483 	public int getIndexOfProject( Project project )
484 	{
485 		return projectList.indexOf( project );
486 	}
487 
488 	public String getPath()
489 	{
490 		return path;
491 	}
492 
493 	public void release()
494 	{
495 		settings.release();
496 
497 		for( Project project : projectList )
498 			project.release();
499 	}
500 
501 	public List<? extends Project> getProjectList()
502 	{
503 		return projectList;
504 	}
505 
506 	public String getDescription()
507 	{
508 		return workspaceConfig.getSoapuiWorkspace().getDescription();
509 	}
510 
511 	public WsdlProject importRemoteProject( String url ) throws SoapUIException
512 	{
513 		WsdlProject project = new WsdlProject( url, this, false );
514 		projectList.add( project );
515 		fireProjectAdded( project );
516 
517 		save( true );
518 
519 		return project;
520 	}
521 
522 	public void closeProject( Project project )
523 	{
524 		int ix = projectList.indexOf( project );
525 		if( ix == -1 )
526 			throw new RuntimeException( "Project [" + project.getName()
527 						+ "] not available in workspace for close" );
528 
529 		projectList.remove( ix );
530 		fireProjectRemoved( project );
531 		
532 		String name = project.getName();
533 		project.release();
534 		
535 		try
536 		{
537 			project = new WsdlProject( project.getPath(), this, false, false, name );
538 			projectList.add( ix, project );
539 			fireProjectAdded( project );
540 		}
541 		catch( Exception e )
542 		{
543 			UISupport.showErrorMessage( "Failed to close project [" + name
544 						+ "]\nin workspace; " + e.getMessage() );
545 
546 			SoapUI.logError( e );
547 		}
548 	}
549 
550 	public List<Project> getOpenProjectList()
551 	{
552 		List<Project> availableProjects = new ArrayList<Project>(); 
553 		
554 		for( Project project : projectList )
555 			if( project.isOpen() )
556 				availableProjects.add( project );
557 		
558 		return availableProjects;
559 	}
560 
561 	public Project openProject( Project project ) throws SoapUIException
562 	{
563 		return reloadProject( project );
564 	}
565 	
566 	public String getId()
567 	{
568 		return String.valueOf( hashCode() );
569 	}
570    
571    public List<? extends ModelItem> getChildren()
572    {
573       return getProjectList();
574    }
575 
576 	public ModelItem getParent()
577 	{
578 		return null;
579 	}
580 }