1
2
3
4
5
6
7
8
9
10
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
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
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 ( WsdlProject ) 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
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
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
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 }