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