View Javadoc

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