View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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.wsdl;
14  
15  import java.beans.PropertyChangeEvent;
16  import java.beans.PropertyChangeListener;
17  import java.beans.PropertyChangeSupport;
18  import java.io.BufferedReader;
19  import java.io.BufferedWriter;
20  import java.io.File;
21  import java.io.FileNotFoundException;
22  import java.io.FileOutputStream;
23  import java.io.FileReader;
24  import java.io.FileWriter;
25  import java.io.IOException;
26  import java.net.MalformedURLException;
27  import java.net.URL;
28  import java.security.GeneralSecurityException;
29  import java.util.ArrayList;
30  import java.util.Arrays;
31  import java.util.HashMap;
32  import java.util.HashSet;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Set;
36  
37  import javax.swing.ImageIcon;
38  import javax.xml.namespace.QName;
39  
40  import org.apache.commons.ssl.OpenSSL;
41  import org.apache.log4j.Logger;
42  import org.apache.xmlbeans.XmlError;
43  import org.apache.xmlbeans.XmlException;
44  import org.apache.xmlbeans.XmlObject;
45  import org.apache.xmlbeans.XmlOptions;
46  
47  import com.eviware.soapui.SoapUI;
48  import com.eviware.soapui.config.InterfaceConfig;
49  import com.eviware.soapui.config.MockServiceConfig;
50  import com.eviware.soapui.config.MockServiceDocumentConfig;
51  import com.eviware.soapui.config.ProjectConfig;
52  import com.eviware.soapui.config.SoapuiProjectDocumentConfig;
53  import com.eviware.soapui.config.TestSuiteConfig;
54  import com.eviware.soapui.config.TestSuiteDocumentConfig;
55  import com.eviware.soapui.config.TestSuiteRunTypesConfig;
56  import com.eviware.soapui.config.TestSuiteRunTypesConfig.Enum;
57  import com.eviware.soapui.impl.WorkspaceImpl;
58  import com.eviware.soapui.impl.WsdlInterfaceFactory;
59  import com.eviware.soapui.impl.rest.support.RestRequestConverter.RestConversionException;
60  import com.eviware.soapui.impl.settings.XmlBeansSettingsImpl;
61  import com.eviware.soapui.impl.support.AbstractInterface;
62  import com.eviware.soapui.impl.wsdl.endpoint.DefaultEndpointStrategy;
63  import com.eviware.soapui.impl.wsdl.mock.WsdlMockService;
64  import com.eviware.soapui.impl.wsdl.support.PathUtils;
65  import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
66  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlLoader;
67  import com.eviware.soapui.impl.wsdl.support.wss.DefaultWssContainer;
68  import com.eviware.soapui.impl.wsdl.testcase.WsdlProjectRunner;
69  import com.eviware.soapui.model.ModelItem;
70  import com.eviware.soapui.model.iface.Interface;
71  import com.eviware.soapui.model.mock.MockService;
72  import com.eviware.soapui.model.project.EndpointStrategy;
73  import com.eviware.soapui.model.project.Project;
74  import com.eviware.soapui.model.project.ProjectListener;
75  import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
76  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
77  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
78  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
79  import com.eviware.soapui.model.settings.Settings;
80  import com.eviware.soapui.model.support.ModelSupport;
81  import com.eviware.soapui.model.testsuite.ProjectRunContext;
82  import com.eviware.soapui.model.testsuite.ProjectRunListener;
83  import com.eviware.soapui.model.testsuite.ProjectRunner;
84  import com.eviware.soapui.model.testsuite.TestRunnable;
85  import com.eviware.soapui.model.testsuite.TestSuite;
86  import com.eviware.soapui.model.testsuite.TestSuite.TestSuiteRunType;
87  import com.eviware.soapui.settings.ProjectSettings;
88  import com.eviware.soapui.settings.UISettings;
89  import com.eviware.soapui.settings.WsdlSettings;
90  import com.eviware.soapui.support.SoapUIException;
91  import com.eviware.soapui.support.StringUtils;
92  import com.eviware.soapui.support.Tools;
93  import com.eviware.soapui.support.UISupport;
94  import com.eviware.soapui.support.resolver.ResolveContext;
95  import com.eviware.soapui.support.resolver.ResolveDialog;
96  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
97  import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
98  import com.eviware.soapui.support.types.StringToObjectMap;
99  
100 /***
101  * WSDL project implementation
102  * 
103  * @author Ole.Matzura
104  */
105 
106 public class WsdlProject extends AbstractTestPropertyHolderWsdlModelItem<ProjectConfig> implements Project,
107 		PropertyExpansionContainer, PropertyChangeListener, TestRunnable
108 {
109 	public final static String AFTER_LOAD_SCRIPT_PROPERTY = WsdlProject.class.getName() + "@setupScript";
110 	public final static String BEFORE_SAVE_SCRIPT_PROPERTY = WsdlProject.class.getName() + "@tearDownScript";
111 	public final static String RESOURCE_ROOT_PROPERTY = WsdlProject.class.getName() + "@resourceRoot";
112 
113 	private WorkspaceImpl workspace;
114 	protected String path;
115 	protected List<AbstractInterface<?>> interfaces = new ArrayList<AbstractInterface<?>>();
116 	protected List<WsdlTestSuite> testSuites = new ArrayList<WsdlTestSuite>();
117 	protected List<WsdlMockService> mockServices = new ArrayList<WsdlMockService>();
118 	private Set<ProjectListener> projectListeners = new HashSet<ProjectListener>();
119 	protected SoapuiProjectDocumentConfig projectDocument;
120 	private ImageIcon disabledIcon;
121 	private ImageIcon closedIcon;
122 	private ImageIcon remoteIcon;
123 	private ImageIcon openEncyptedIcon;
124 	protected EndpointStrategy endpointStrategy = new DefaultEndpointStrategy();
125 	protected long lastModified;
126 	private boolean remote;
127 	private boolean open = true;
128 	private boolean disabled;
129 
130 	private SoapUIScriptEngine afterLoadScriptEngine;
131 	private SoapUIScriptEngine beforeSaveScriptEngine;
132 	private PropertyExpansionContext context = new DefaultPropertyExpansionContext(this);
133 	protected DefaultWssContainer wssContainer;
134 	private String projectPassword = null;
135 	private String hermesConfig;
136 
137 	/*
138 	 * 3 state flag: 1. 0 - project not encrypted 2. 1 - encrypted , good
139 	 * password, means that it could be successfully decrypted 3. -1 - encrypted,
140 	 * but with bad password or no password.
141 	 */
142 
143 	protected int encrypted;
144 	private ImageIcon closedEncyptedIcon;
145 	protected final PropertyChangeSupport pcs;
146 	private SoapUIScriptEngine afterRunScriptEngine;
147 	private SoapUIScriptEngine beforeRunScriptEngine;
148 	private Set<ProjectRunListener> runListeners = new HashSet<ProjectRunListener>();
149 
150 	protected final static Logger log = Logger.getLogger(WsdlProject.class);
151 
152 	public WsdlProject() throws XmlException, IOException, SoapUIException
153 	{
154 		this((WorkspaceImpl) null);
155 	}
156 
157 	public WsdlProject(String path) throws XmlException, IOException, SoapUIException
158 	{
159 		this(path, (WorkspaceImpl) null);
160 	}
161 
162 	public WsdlProject(String projectFile, String projectPassword)
163 	{
164 		this(projectFile, null, true, true, null, projectPassword);
165 	}
166 
167 	public WsdlProject(WorkspaceImpl workspace)
168 	{
169 		this(null, workspace, true);
170 	}
171 
172 	public WsdlProject(String path, WorkspaceImpl workspace)
173 	{
174 		this(path, workspace, true);
175 	}
176 
177 	public WsdlProject(String path, WorkspaceImpl workspace, boolean create)
178 	{
179 		this(path, workspace, create, true, null, null);
180 	}
181 
182 	public WsdlProject(String path, WorkspaceImpl workspace, boolean create, boolean open, String tempName,
183 			String projectPassword)
184 	{
185 		super(null, workspace, "/project.gif");
186 
187 		pcs = new PropertyChangeSupport(this);
188 
189 		this.workspace = workspace;
190 		this.path = path;
191 		this.projectPassword = projectPassword;
192 
193 		for (ProjectListener listener : SoapUI.getListenerRegistry().getListeners(ProjectListener.class))
194 		{
195 			addProjectListener(listener);
196 		}
197 
198 		for (ProjectRunListener listener : SoapUI.getListenerRegistry().getListeners(ProjectRunListener.class))
199 		{
200 			addProjectRunListener(listener);
201 		}
202 
203 		try
204 		{
205 			if (path != null && open)
206 			{
207 				File file = new File(path.trim());
208 				if (file.exists())
209 				{
210 					try
211 					{
212 						loadProject(new URL("file:" + file.getAbsolutePath()));
213 						lastModified = file.lastModified();
214 					}
215 					catch (MalformedURLException e)
216 					{
217 						SoapUI.logError(e);
218 						disabled = true;
219 					}
220 				}
221 				else
222 				{
223 					try
224 					{
225 						if (!PathUtils.isHttpPath(path))
226 							SoapUI.log.info("File [" + file.getAbsolutePath() + "] does not exist, trying URL instead");
227 
228 						remote = true;
229 						loadProject(new URL(path));
230 					}
231 					catch (MalformedURLException e)
232 					{
233 						SoapUI.logError(e);
234 						disabled = true;
235 					}
236 				}
237 			}
238 		}
239 		catch (SoapUIException e)
240 		{
241 			SoapUI.logError(e);
242 			disabled = true;
243 		}
244 		finally
245 		{
246 			closedIcon = UISupport.createImageIcon("/closedProject.gif");
247 			remoteIcon = UISupport.createImageIcon("/remoteProject.gif");
248 			disabledIcon = UISupport.createImageIcon("/disabledProject.gif");
249 			openEncyptedIcon = UISupport.createImageIcon("/openEncryptedProject.gif");
250 			closedEncyptedIcon = UISupport.createImageIcon("/closedEncryptedProject.gif");
251 
252 			this.open = open && !disabled && (this.encrypted != -1);
253 
254 			if (projectDocument == null)
255 			{
256 				projectDocument = SoapuiProjectDocumentConfig.Factory.newInstance();
257 				setConfig(projectDocument.addNewSoapuiProject());
258 				if (tempName != null || path != null)
259 					getConfig().setName(StringUtils.isNullOrEmpty(tempName) ? getNameFromPath() : tempName);
260 
261 				setPropertiesConfig(getConfig().addNewProperties());
262 				wssContainer = new DefaultWssContainer(this, getConfig().addNewWssContainer());
263 				// setResourceRoot("${projectDir}");
264 			}
265 
266 			if (getConfig() != null)
267 			{
268 				endpointStrategy.init(this);
269 			}
270 			if (getSettings() != null)
271 			{
272 				setProjectRoot(path);
273 			}
274 
275 			addPropertyChangeListener(this);
276 		}
277 	}
278 
279 	protected PropertyChangeSupport getPropertyChangeSupport()
280 	{
281 		return pcs;
282 	}
283 
284 	public boolean isRemote()
285 	{
286 		return remote;
287 	}
288 
289 	public void loadProject(URL file) throws SoapUIException
290 	{
291 		try
292 		{
293 			UISupport.setHourglassCursor();
294 
295 			UrlWsdlLoader loader = new UrlWsdlLoader(file.toString(), this);
296 			loader.setUseWorker(false);
297 			projectDocument = SoapuiProjectDocumentConfig.Factory.parse(loader.load());
298 
299 			// see if there is encoded data
300 			this.encrypted = checkForEncodedData(projectDocument.getSoapuiProject());
301 
302 			setConfig(projectDocument.getSoapuiProject());
303 
304 			// removed cached definitions if caching is disabled
305 			if (!getSettings().getBoolean(WsdlSettings.CACHE_WSDLS))
306 			{
307 				removeDefinitionCaches(projectDocument);
308 			}
309 
310 			log.info("Loaded project from [" + file.toString() + "]");
311 
312 			try
313 			{
314 				int majorVersion = Integer.parseInt(projectDocument.getSoapuiProject().getSoapuiVersion().split("//.")[0]);
315 				if (majorVersion > Integer.parseInt(SoapUI.SOAPUI_VERSION.split("//.")[0]))
316 					log.warn("Project '" + projectDocument.getSoapuiProject().getName() + "' is from a newer version ("
317 							+ projectDocument.getSoapuiProject().getSoapuiVersion() + ") of soapUI than this ("
318 							+ SoapUI.SOAPUI_VERSION + ") and parts of it may be incompatible or incorrect. "
319 							+ "Saving this project with this version of soapUI may cause it to function differently.");
320 			}
321 			catch (Exception e)
322 			{
323 			}
324 
325 			List<InterfaceConfig> interfaceConfigs = getConfig().getInterfaceList();
326 			for (InterfaceConfig config : interfaceConfigs)
327 			{
328 				AbstractInterface<?> iface = InterfaceFactoryRegistry.build(this, config);
329 				interfaces.add(iface);
330 			}
331 
332 			List<TestSuiteConfig> testSuiteConfigs = getConfig().getTestSuiteList();
333 			for (TestSuiteConfig config : testSuiteConfigs)
334 			{
335 				testSuites.add(buildTestSuite(config));
336 			}
337 
338 			List<MockServiceConfig> mockServiceConfigs = getConfig().getMockServiceList();
339 			for (MockServiceConfig config : mockServiceConfigs)
340 			{
341 				mockServices.add(new WsdlMockService(this, config));
342 			}
343 
344 			if (!getConfig().isSetWssContainer())
345 				getConfig().addNewWssContainer();
346 
347 			wssContainer = new DefaultWssContainer(this, getConfig().getWssContainer());
348 
349 			endpointStrategy.init(this);
350 
351 			if (!getConfig().isSetProperties())
352 				getConfig().addNewProperties();
353 
354 			if (!getConfig().isSetAbortOnError())
355 				getConfig().setAbortOnError(false);
356 
357 			// if( !getConfig().isSetFailOnErrors() )
358 			// getConfig().setFailOnErrors( true );
359 
360 			if (!getConfig().isSetRunType())
361 				getConfig().setRunType(TestSuiteRunTypesConfig.SEQUENTIAL);
362 
363 			setPropertiesConfig(getConfig().getProperties());
364 			afterLoad();
365 		}
366 		catch (Exception e)
367 		{
368 			if (e instanceof XmlException)
369 			{
370 				XmlException xe = (XmlException) e;
371 				XmlError error = xe.getError();
372 				if (error != null)
373 					System.err.println("Error at line " + error.getLine() + ", column " + error.getColumn());
374 			}
375 
376 			if (e instanceof RestConversionException)
377 			{
378 				log.error("Project file needs to be updated manually, please reload the project.");
379 				throw new SoapUIException("Failed to load project from file [" + file.toString() + "]", e);
380 			}
381 
382 			e.printStackTrace();
383 			throw new SoapUIException("Failed to load project from file [" + file.toString() + "]", e);
384 		}
385 		finally
386 		{
387 			UISupport.resetCursor();
388 		}
389 	}
390 
391 	protected WsdlTestSuite buildTestSuite(TestSuiteConfig config)
392 	{
393 		return new WsdlTestSuite(this, config);
394 	}
395 
396 	/***
397 	 * Decode encrypted data and restore user/pass
398 	 * 
399 	 * @param soapuiProject
400 	 * @return 0 - not encrypted, 1 - successfull decryption , -1 error while
401 	 *         decrypting, bad password, no password.
402 	 * @throws IOException
403 	 * @throws GeneralSecurityException
404 	 * @author robert nemet
405 	 */
406 	protected int checkForEncodedData(ProjectConfig soapuiProject) throws IOException, GeneralSecurityException
407 	{
408 
409 		byte[] encryptedContent = soapuiProject.getEncryptedContent();
410 		char[] password = null;
411 
412 		// no encrypted data then go back
413 		if (encryptedContent == null || encryptedContent.length == 0)
414 			return 0;
415 
416 		String projectPassword = null;
417 		if (workspace != null)
418 		{
419 			projectPassword = workspace.getProjectPassword(soapuiProject.getName());
420 		}
421 		else
422 		{
423 			projectPassword = this.projectPassword;
424 		}
425 		if (projectPassword == null)
426 		{
427 			password = UISupport.promptPassword("Enter Password:", soapuiProject.getName());
428 		}
429 		else
430 		{
431 			password = projectPassword.toCharArray();
432 		}
433 		byte[] data = null;
434 		// no pass go back.
435 		if (password == null)
436 		{
437 			return -1;
438 		}
439 
440 		try
441 		{
442 			data = OpenSSL.decrypt("des3", password, encryptedContent);
443 		}
444 		catch (Exception e)
445 		{
446 			e.printStackTrace();
447 			return -1;
448 		}
449 
450 		String decryptedData = new String(data, "UTF-8");
451 
452 		if (decryptedData != null)
453 		{
454 			if (decryptedData.length() > 0)
455 			{
456 				try
457 				{
458 					projectDocument.getSoapuiProject().set(XmlObject.Factory.parse(decryptedData));
459 				}
460 				catch (XmlException e)
461 				{
462 					UISupport.showErrorMessage("Wrong password. Project need to be reloaded.");
463 					getWorkspace().clearProjectPassword(soapuiProject.getName());
464 					return -1;
465 				}
466 			}
467 		}
468 		else
469 		{
470 			UISupport.showErrorMessage("Wrong project password");
471 			getWorkspace().clearProjectPassword(soapuiProject.getName());
472 			return -1;
473 		}
474 		projectDocument.getSoapuiProject().setEncryptedContent(null);
475 		return 1;
476 	}
477 
478 	@Override
479 	public void afterLoad()
480 	{
481 		super.afterLoad();
482 
483 		try
484 		{
485 			ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
486 
487 			for (int c = 0; c < a.length; c++)
488 			{
489 				a[c].afterLoad(this);
490 			}
491 
492 			runAfterLoadScript();
493 		}
494 		catch (Exception e)
495 		{
496 			SoapUI.logError(e);
497 		}
498 	}
499 
500 	protected void setProjectRoot(String path)
501 	{
502 		if (path != null && projectDocument != null)
503 		{
504 			int ix = path.lastIndexOf(File.separatorChar);
505 			if (ix > 0)
506 				getSettings().setString(ProjectSettings.PROJECT_ROOT, path.substring(0, ix));
507 		}
508 	}
509 
510 	public void setResourceRoot(String resourceRoot)
511 	{
512 		String old = getResourceRoot();
513 
514 		getConfig().setResourceRoot(resourceRoot);
515 		notifyPropertyChanged(RESOURCE_ROOT_PROPERTY, old, resourceRoot);
516 	}
517 
518 	public String getResourceRoot()
519 	{
520 		if (!getConfig().isSetResourceRoot())
521 			getConfig().setResourceRoot("");
522 
523 		return getConfig().getResourceRoot();
524 	}
525 
526 	@Override
527 	public ImageIcon getIcon()
528 	{
529 		if (isDisabled())
530 			return disabledIcon;
531 		else if (getEncrypted() != 0)
532 		{
533 			if (isOpen())
534 			{
535 				return openEncyptedIcon;
536 			}
537 			else
538 			{
539 				return closedEncyptedIcon;
540 			}
541 		}
542 		else if (!isOpen())
543 			return closedIcon;
544 		else if (isRemote())
545 			return remoteIcon;
546 		else
547 			return super.getIcon();
548 	}
549 
550 	private String getNameFromPath()
551 	{
552 		int ix = path.lastIndexOf(isRemote() ? '/' : File.separatorChar);
553 		String name = ix == -1 ? path : path.substring(ix + 1);
554 		return name;
555 	}
556 
557 	@Override
558 	public String getDescription()
559 	{
560 		if (isOpen())
561 			return super.getDescription();
562 
563 		String name = getName();
564 
565 		if (isDisabled())
566 			name += " - disabled [" + getPath() + "]";
567 		else
568 			name += " - closed [" + getPath() + "]";
569 
570 		return name;
571 	}
572 
573 	public WorkspaceImpl getWorkspace()
574 	{
575 		return workspace;
576 	}
577 
578 	public AbstractInterface<?> getInterfaceAt(int index)
579 	{
580 		return interfaces.get(index);
581 	}
582 
583 	public AbstractInterface<?> getInterfaceByName(String interfaceName)
584 	{
585 		return (AbstractInterface<?>) getWsdlModelItemByName(interfaces, interfaceName);
586 	}
587 
588 	public AbstractInterface<?> getInterfaceByTechnicalId(String technicalId)
589 	{
590 		for (int c = 0; c < getInterfaceCount(); c++)
591 		{
592 			if (getInterfaceAt(c).getTechnicalId().equals(technicalId))
593 				return getInterfaceAt(c);
594 		}
595 
596 		return null;
597 	}
598 
599 	public int getInterfaceCount()
600 	{
601 		return interfaces.size();
602 	}
603 
604 	public String getPath()
605 	{
606 		return path;
607 	}
608 
609 	public boolean save() throws IOException
610 	{
611 		return save(null);
612 	}
613 
614 	public boolean save(String folder) throws IOException
615 	{
616 		if (!isOpen() || isDisabled() || isRemote())
617 			return true;
618 
619 		if (path == null || isRemote())
620 		{
621 			path = StringUtils.createFileName2( getName(), '-' ) + "-soapui-project.xml";
622 			if (folder != null)
623 			{
624 				path = folder + File.separatorChar + path;
625 			}
626 
627 			File file = null;
628 
629 			while (file == null
630 					|| (file.exists() && !UISupport.confirm("File [" + file.getName() + "] exists, overwrite?",
631 							"Overwrite File?")))
632 			{
633 				file = UISupport.getFileDialogs().saveAs(this, "Save project " + getName(), ".xml", "XML Files (*.xml)",
634 						new File(path));
635 				if (file == null)
636 					return false;
637 			}
638 
639 			path = file.getAbsolutePath();
640 		}
641 
642 		File projectFile = new File(path);
643 
644 		while (projectFile.exists() && !projectFile.canWrite())
645 		{
646 			if (UISupport.confirm("Project file [" + path + "] can not be written to, save to new file?", "Save Project"))
647 			{
648 				projectFile = UISupport.getFileDialogs().saveAs(this, "Save project " + getName(), ".xml",
649 						"XML Files (*.xml)", projectFile);
650 
651 				if (projectFile == null)
652 					return false;
653 
654 				path = projectFile.getAbsolutePath();
655 			}
656 			else
657 				return false;
658 		}
659 
660 		// check modified
661 		if (projectFile.exists() && lastModified != 0 && lastModified < projectFile.lastModified())
662 		{
663 			if (!UISupport.confirm("Project file for [" + getName() + "] has been modified externally, overwrite?",
664 					"Save Project"))
665 				return false;
666 		}
667 
668 		if (projectFile.exists() && getSettings().getBoolean(UISettings.CREATE_BACKUP))
669 		{
670 			createBackup(projectFile);
671 		}
672 
673 		return saveIn(projectFile);
674 	}
675 
676 	public boolean saveBackup() throws IOException
677 	{
678 		File projectFile;
679 		if (path == null || isRemote())
680 		{
681 			projectFile = new File( StringUtils.createFileName2( getName(), '-' ) + "-soapui-project.xml" );
682 		}
683 		else
684 		{
685 			projectFile = new File(path);
686 		}
687 		File backupFile = getBackupFile(projectFile);
688 		return saveIn(backupFile);
689 	}
690 
691 	public boolean saveIn(File projectFile) throws IOException
692 	{
693 		long size = 0;
694 
695 		beforeSave();
696 		// work with copy beacuse we do not want to change working project while
697 		// working with it
698 		// if user choose save project, save all etc.
699 		SoapuiProjectDocumentConfig projectDocument = (SoapuiProjectDocumentConfig) this.projectDocument.copy();
700 
701 		// check for caching
702 		if (!getSettings().getBoolean(WsdlSettings.CACHE_WSDLS))
703 		{
704 			// no caching -> create copy and remove definition cachings
705 			removeDefinitionCaches(projectDocument);
706 		}
707 
708 		// remove project root
709 		XmlBeansSettingsImpl tempSettings = new XmlBeansSettingsImpl(this, null, projectDocument.getSoapuiProject()
710 				.getSettings());
711 		tempSettings.clearSetting(ProjectSettings.PROJECT_ROOT);
712 
713 		// check for encryption
714 		String passwordForEncryption = getSettings().getString(ProjectSettings.SHADOW_PASSWORD, null);
715 
716 		// if it has encryptedContend that means it is not decrypted corectly( bad
717 		// password, etc ), so do not encrypt it again.
718 		if (projectDocument.getSoapuiProject().getEncryptedContent() == null)
719 		{
720 			if (passwordForEncryption != null)
721 			{
722 				if (passwordForEncryption.length() > 1)
723 				{
724 					// we have password so do encryption
725 					try
726 					{
727 						String data = getConfig().xmlText();
728 						byte[] encrypted = OpenSSL.encrypt("des3", passwordForEncryption.toCharArray(), data.getBytes());
729 						projectDocument.getSoapuiProject().setEncryptedContent(encrypted);
730 						projectDocument.getSoapuiProject().setInterfaceArray(null);
731 						projectDocument.getSoapuiProject().setTestSuiteArray(null);
732 						projectDocument.getSoapuiProject().setMockServiceArray(null);
733 						projectDocument.getSoapuiProject().unsetWssContainer();
734 						projectDocument.getSoapuiProject().unsetSettings();
735 						projectDocument.getSoapuiProject().unsetProperties();
736 
737 					}
738 					catch (GeneralSecurityException e)
739 					{
740 						UISupport.showErrorMessage("Encryption Error");
741 					}
742 				}
743 				else
744 				{
745 					// no password no encryption.
746 					projectDocument.getSoapuiProject().setEncryptedContent(null);
747 				}
748 			}
749 		}
750 		// end of encryption.
751 
752 		XmlOptions options = new XmlOptions();
753 		if (SoapUI.getSettings().getBoolean(WsdlSettings.PRETTY_PRINT_PROJECT_FILES))
754 			options.setSavePrettyPrint();
755 
756 		projectDocument.getSoapuiProject().setSoapuiVersion(SoapUI.SOAPUI_VERSION);
757 
758 		try
759 		{
760 			File tempFile = File.createTempFile("project-temp-", ".xml", projectFile.getParentFile());
761 
762 			// save once to make sure it can be saved
763 			FileOutputStream tempOut = new FileOutputStream(tempFile);
764 			projectDocument.save(tempOut, options);
765 			tempOut.close();
766 
767 			if (getSettings().getBoolean(UISettings.LINEBREAK))
768 			{
769 				normalizeLineBreak(projectFile, tempFile);
770 			}
771 			else
772 			{
773 				// now save it for real
774 				FileOutputStream projectOut = new FileOutputStream(projectFile);
775 				projectDocument.save(projectOut, options);
776 				projectOut.close();
777 				// delete tempFile here so we have it as backup in case second save
778 				// fails
779 				if (!tempFile.delete())
780 				{
781 					SoapUI.getErrorLog().warn("Failed to delete temporary project file; " + tempFile.getAbsolutePath());
782 					tempFile.deleteOnExit();
783 				}
784 			}
785 			size = projectFile.length();
786 		}
787 		catch (Throwable t)
788 		{
789 			SoapUI.logError(t);
790 			UISupport.showErrorMessage("Failed to save project [" + getName() + "]: " + t.toString());
791 			return false;
792 		}
793 
794 		lastModified = projectFile.lastModified();
795 		log.info("Saved project [" + getName() + "] to [" + projectFile.getAbsolutePath() + " - " + size + " bytes");
796 		setProjectRoot(getPath());
797 		return true;
798 	}
799 
800 	private static void normalizeLineBreak(File target, File tmpFile)
801 	{
802 		try
803 		{
804 			FileReader fr = new FileReader(tmpFile);
805 			BufferedReader in = new BufferedReader(fr);
806 			FileWriter fw = new FileWriter(target);
807 			BufferedWriter out = new BufferedWriter(fw);
808 			String line = "";
809 			while ((line = in.readLine()) != null)
810 			{
811 				out.write(line);
812 				out.newLine();
813 				out.flush();
814 			}
815 			out.close();
816 			fw.close();
817 			in.close();
818 			fr.close();
819 		}
820 		catch (FileNotFoundException e)
821 		{
822 			// TODO Auto-generated catch block
823 			e.printStackTrace();
824 		}
825 		catch (IOException e)
826 		{
827 			// TODO Auto-generated catch block
828 			e.printStackTrace();
829 		}
830 
831 		if (!tmpFile.delete())
832 		{
833 			SoapUI.getErrorLog().warn("Failed to delete temporary file: " + tmpFile.getAbsolutePath());
834 			tmpFile.deleteOnExit();
835 		}
836 	}
837 
838 	public void beforeSave()
839 	{
840 		try
841 		{
842 			ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
843 
844 			for (int c = 0; c < a.length; c++)
845 			{
846 				a[c].beforeSave(this);
847 			}
848 
849 			runBeforeSaveScript();
850 		}
851 		catch (Exception e)
852 		{
853 			SoapUI.logError(e);
854 		}
855 
856 		// notify
857 		for (AbstractInterface<?> iface : interfaces)
858 			iface.beforeSave();
859 
860 		for (WsdlTestSuite testSuite : testSuites)
861 			testSuite.beforeSave();
862 
863 		for (WsdlMockService mockService : mockServices)
864 			mockService.beforeSave();
865 
866 		endpointStrategy.onSave();
867 	}
868 
869 	protected void createBackup(File projectFile) throws IOException
870 	{
871 		File backupFile = getBackupFile(projectFile);
872 		log.info("Backing up [" + projectFile + "] to [" + backupFile + "]");
873 		Tools.copyFile(projectFile, backupFile, true);
874 	}
875 
876 	protected File getBackupFile(File projectFile)
877 	{
878 		String backupFolderName = getSettings().getString(UISettings.BACKUP_FOLDER, "");
879 
880 		File backupFolder = new File(backupFolderName);
881 		if (!backupFolder.isAbsolute())
882 		{
883 			backupFolder = new File(projectFile.getParentFile(), backupFolderName);
884 		}
885 
886 		if (!backupFolder.exists())
887 			backupFolder.mkdirs();
888 
889 		File backupFile = new File(backupFolder, projectFile.getName() + ".backup");
890 		return backupFile;
891 	}
892 
893 	protected void removeDefinitionCaches(SoapuiProjectDocumentConfig config)
894 	{
895 		for (InterfaceConfig ifaceConfig : config.getSoapuiProject().getInterfaceList())
896 		{
897 			if (ifaceConfig.isSetDefinitionCache())
898 			{
899 				log.info("Removing definition cache from interface [" + ifaceConfig.getName() + "]");
900 				ifaceConfig.unsetDefinitionCache();
901 			}
902 		}
903 	}
904 
905 	public AbstractInterface<?> addNewInterface(String name, String type)
906 	{
907 		AbstractInterface<?> iface = (AbstractInterface<?>) InterfaceFactoryRegistry.createNew(this, type, name);
908 		if (iface != null)
909 		{
910 			iface.getConfig().setType(type);
911 
912 			interfaces.add(iface);
913 			fireInterfaceAdded(iface);
914 		}
915 
916 		return iface;
917 	}
918 
919 	public void addProjectListener(ProjectListener listener)
920 	{
921 		projectListeners.add(listener);
922 	}
923 
924 	public void removeProjectListener(ProjectListener listener)
925 	{
926 		projectListeners.remove(listener);
927 	}
928 
929 	public void fireInterfaceAdded(AbstractInterface<?> iface)
930 	{
931 		ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
932 
933 		for (int c = 0; c < a.length; c++)
934 		{
935 			a[c].interfaceAdded(iface);
936 		}
937 	}
938 
939 	public void fireInterfaceRemoved(AbstractInterface<?> iface)
940 	{
941 		ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
942 
943 		for (int c = 0; c < a.length; c++)
944 		{
945 			a[c].interfaceRemoved(iface);
946 		}
947 	}
948 
949 	public void fireInterfaceUpdated(AbstractInterface<?> iface)
950 	{
951 		ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
952 
953 		for (int c = 0; c < a.length; c++)
954 		{
955 			a[c].interfaceUpdated(iface);
956 		}
957 	}
958 
959 	public void fireTestSuiteAdded(WsdlTestSuite testSuite)
960 	{
961 		ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
962 
963 		for (int c = 0; c < a.length; c++)
964 		{
965 			a[c].testSuiteAdded(testSuite);
966 		}
967 	}
968 
969 	private void fireTestSuiteMoved(WsdlTestSuite testCase, int ix, int offset)
970 	{
971 		ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
972 
973 		for (int c = 0; c < a.length; c++)
974 		{
975 			a[c].testSuiteMoved(testCase, ix, offset);
976 		}
977 	}
978 
979 	public void fireTestSuiteRemoved(WsdlTestSuite testSuite)
980 	{
981 		ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
982 
983 		for (int c = 0; c < a.length; c++)
984 		{
985 			a[c].testSuiteRemoved(testSuite);
986 		}
987 	}
988 
989 	public void fireMockServiceAdded(WsdlMockService mockService)
990 	{
991 		ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
992 
993 		for (int c = 0; c < a.length; c++)
994 		{
995 			a[c].mockServiceAdded(mockService);
996 		}
997 	}
998 
999 	public void fireMockServiceRemoved(WsdlMockService mockService)
1000 	{
1001 		ProjectListener[] a = projectListeners.toArray(new ProjectListener[projectListeners.size()]);
1002 
1003 		for (int c = 0; c < a.length; c++)
1004 		{
1005 			a[c].mockServiceRemoved(mockService);
1006 		}
1007 	}
1008 
1009 	public void removeInterface(AbstractInterface<?> iface)
1010 	{
1011 		int ix = interfaces.indexOf(iface);
1012 		interfaces.remove(ix);
1013 		try
1014 		{
1015 			fireInterfaceRemoved(iface);
1016 		}
1017 		finally
1018 		{
1019 			iface.release();
1020 			getConfig().removeInterface(ix);
1021 		}
1022 	}
1023 
1024 	public void removeTestSuite(WsdlTestSuite testSuite)
1025 	{
1026 		int ix = testSuites.indexOf(testSuite);
1027 		testSuites.remove(ix);
1028 
1029 		try
1030 		{
1031 			fireTestSuiteRemoved(testSuite);
1032 		}
1033 		finally
1034 		{
1035 			testSuite.release();
1036 			getConfig().removeTestSuite(ix);
1037 		}
1038 	}
1039 
1040 	public boolean isDisabled()
1041 	{
1042 		return disabled;
1043 	}
1044 
1045 	public int getTestSuiteCount()
1046 	{
1047 		return testSuites.size();
1048 	}
1049 
1050 	public WsdlTestSuite getTestSuiteAt(int index)
1051 	{
1052 		return testSuites.get(index);
1053 	}
1054 
1055 	public WsdlTestSuite getTestSuiteByName(String testSuiteName)
1056 	{
1057 		return (WsdlTestSuite) getWsdlModelItemByName(testSuites, testSuiteName);
1058 	}
1059 
1060 	public WsdlTestSuite addNewTestSuite(String name)
1061 	{
1062 		WsdlTestSuite testSuite = buildTestSuite(getConfig().addNewTestSuite());
1063 		testSuite.setName(name);
1064 		testSuites.add(testSuite);
1065 		fireTestSuiteAdded(testSuite);
1066 
1067 		return testSuite;
1068 	}
1069 
1070 	public boolean isCacheDefinitions()
1071 	{
1072 		return getSettings().getBoolean(WsdlSettings.CACHE_WSDLS);
1073 	}
1074 
1075 	public void setCacheDefinitions(boolean cacheDefinitions)
1076 	{
1077 		getSettings().setBoolean(WsdlSettings.CACHE_WSDLS, cacheDefinitions);
1078 	}
1079 
1080 	public boolean saveAs(String fileName) throws IOException
1081 	{
1082 		if (!isOpen() || isDisabled())
1083 			return false;
1084 
1085 		String oldPath = path;
1086 		path = fileName;
1087 		boolean result = save();
1088 		if (!result)
1089 			path = oldPath;
1090 		else
1091 			remote = false;
1092 
1093 		setProjectRoot(path);
1094 
1095 		return result;
1096 	}
1097 
1098 	@Override
1099 	public void release()
1100 	{
1101 		super.release();
1102 
1103 		if (isOpen())
1104 		{
1105 			endpointStrategy.release();
1106 
1107 			for (WsdlTestSuite testSuite : testSuites)
1108 				testSuite.release();
1109 
1110 			for (WsdlMockService mockService : mockServices)
1111 				mockService.release();
1112 
1113 			for (AbstractInterface<?> iface : interfaces)
1114 				iface.release();
1115 
1116 			if (wssContainer != null)
1117 			{
1118 				wssContainer.release();
1119 				wssContainer = null;
1120 			}
1121 		}
1122 
1123 		projectListeners.clear();
1124 
1125 		if (afterLoadScriptEngine != null)
1126 			afterLoadScriptEngine.release();
1127 
1128 		if (beforeSaveScriptEngine != null)
1129 			beforeSaveScriptEngine.release();
1130 	}
1131 
1132 	public WsdlMockService addNewMockService(String name)
1133 	{
1134 		WsdlMockService mockService = new WsdlMockService(this, getConfig().addNewMockService());
1135 		mockService.setName(name);
1136 		mockServices.add(mockService);
1137 		fireMockServiceAdded(mockService);
1138 
1139 		return mockService;
1140 	}
1141 
1142 	public WsdlMockService getMockServiceAt(int index)
1143 	{
1144 		return mockServices.get(index);
1145 	}
1146 
1147 	public WsdlMockService getMockServiceByName(String mockServiceName)
1148 	{
1149 		return (WsdlMockService) getWsdlModelItemByName(mockServices, mockServiceName);
1150 	}
1151 
1152 	public int getMockServiceCount()
1153 	{
1154 		return mockServices.size();
1155 	}
1156 
1157 	public void removeMockService(WsdlMockService mockService)
1158 	{
1159 		int ix = mockServices.indexOf(mockService);
1160 		mockServices.remove(ix);
1161 
1162 		try
1163 		{
1164 			fireMockServiceRemoved(mockService);
1165 		}
1166 		finally
1167 		{
1168 			mockService.release();
1169 			getConfig().removeMockService(ix);
1170 		}
1171 	}
1172 
1173 	public List<TestSuite> getTestSuiteList()
1174 	{
1175 		return new ArrayList<TestSuite>(testSuites);
1176 	}
1177 
1178 	public List<MockService> getMockServiceList()
1179 	{
1180 		return new ArrayList<MockService>(mockServices);
1181 	}
1182 
1183 	public List<Interface> getInterfaceList()
1184 	{
1185 		return new ArrayList<Interface>(interfaces);
1186 	}
1187 
1188 	public Map<String, Interface> getInterfaces()
1189 	{
1190 		Map<String, Interface> result = new HashMap<String, Interface>();
1191 		for (Interface iface : interfaces)
1192 			result.put(iface.getName(), iface);
1193 
1194 		return result;
1195 	}
1196 
1197 	public Map<String, TestSuite> getTestSuites()
1198 	{
1199 		Map<String, TestSuite> result = new HashMap<String, TestSuite>();
1200 		for (TestSuite iface : testSuites)
1201 			result.put(iface.getName(), iface);
1202 
1203 		return result;
1204 	}
1205 
1206 	public Map<String, MockService> getMockServices()
1207 	{
1208 		Map<String, MockService> result = new HashMap<String, MockService>();
1209 		for (MockService mockService : mockServices)
1210 			result.put(mockService.getName(), mockService);
1211 
1212 		return result;
1213 	}
1214 
1215 	public void reload() throws SoapUIException
1216 	{
1217 		reload(path);
1218 	}
1219 
1220 	public void reload(String path) throws SoapUIException
1221 	{
1222 		this.path = path;
1223 		getWorkspace().reloadProject(this);
1224 	}
1225 
1226 	public boolean hasNature(String natureId)
1227 	{
1228 		Settings projectSettings = getSettings();
1229 		String projectNature = projectSettings.getString(ProjectSettings.PROJECT_NATURE, null);
1230 		return natureId.equals(projectNature);
1231 	}
1232 
1233 	public AbstractInterface<?> importInterface(AbstractInterface<?> iface, boolean importEndpoints, boolean createCopy)
1234 	{
1235 		iface.beforeSave();
1236 
1237 		InterfaceConfig ifaceConfig = (InterfaceConfig) iface.getConfig().copy();
1238 		ifaceConfig = (InterfaceConfig) getConfig().addNewInterface().set(ifaceConfig);
1239 
1240 		AbstractInterface<?> imported = InterfaceFactoryRegistry.build(this, ifaceConfig);
1241 		interfaces.add(imported);
1242 
1243 		if (iface.getProject() != this && importEndpoints)
1244 		{
1245 			endpointStrategy.importEndpoints(iface);
1246 		}
1247 
1248 		if (createCopy)
1249 			ModelSupport.unsetIds(imported);
1250 
1251 		imported.afterLoad();
1252 		fireInterfaceAdded(imported);
1253 
1254 		return imported;
1255 	}
1256 
1257 	public WsdlTestSuite importTestSuite(WsdlTestSuite testSuite, String name, int index, boolean createCopy,
1258 			String description)
1259 	{
1260 		testSuite.beforeSave();
1261 		TestSuiteConfig testSuiteConfig = index == -1 ? (TestSuiteConfig) getConfig().addNewTestSuite().set(
1262 				testSuite.getConfig().copy()) : (TestSuiteConfig) getConfig().insertNewTestSuite(index).set(
1263 				testSuite.getConfig().copy());
1264 
1265 		testSuiteConfig.setName(name);
1266 
1267 		testSuite = buildTestSuite(testSuiteConfig);
1268 		if (description != null)
1269 			testSuite.setDescription(description);
1270 
1271 		if (index == -1)
1272 			testSuites.add(testSuite);
1273 		else
1274 			testSuites.add(index, testSuite);
1275 
1276 		if (createCopy)
1277 			ModelSupport.unsetIds(testSuite);
1278 
1279 		testSuite.afterLoad();
1280 		fireTestSuiteAdded(testSuite);
1281 
1282 		resolveImportedTestSuite(testSuite);
1283 
1284 		return testSuite;
1285 	}
1286 
1287 	public WsdlMockService importMockService(WsdlMockService mockService, String name, boolean createCopy,
1288 			String description)
1289 	{
1290 		mockService.beforeSave();
1291 		MockServiceConfig mockServiceConfig = (MockServiceConfig) getConfig().addNewMockService().set(
1292 				mockService.getConfig().copy());
1293 		mockServiceConfig.setName(name);
1294 		if (mockServiceConfig.isSetId() && createCopy)
1295 			mockServiceConfig.unsetId();
1296 		mockService = new WsdlMockService(this, mockServiceConfig);
1297 		mockService.setDescription(description);
1298 		mockServices.add(mockService);
1299 		if (createCopy)
1300 			ModelSupport.unsetIds(mockService);
1301 
1302 		mockService.afterLoad();
1303 
1304 		fireMockServiceAdded(mockService);
1305 
1306 		return mockService;
1307 	}
1308 
1309 	public EndpointStrategy getEndpointStrategy()
1310 	{
1311 		return endpointStrategy;
1312 	}
1313 
1314 	public boolean isOpen()
1315 	{
1316 		return open;
1317 	}
1318 
1319 	public List<? extends ModelItem> getChildren()
1320 	{
1321 		ArrayList<ModelItem> list = new ArrayList<ModelItem>();
1322 		list.addAll(getInterfaceList());
1323 		list.addAll(getTestSuiteList());
1324 		list.addAll(getMockServiceList());
1325 		return list;
1326 	}
1327 
1328 	public void setAfterLoadScript(String script)
1329 	{
1330 		String oldScript = getAfterLoadScript();
1331 
1332 		if (!getConfig().isSetAfterLoadScript())
1333 			getConfig().addNewAfterLoadScript();
1334 
1335 		getConfig().getAfterLoadScript().setStringValue(script);
1336 		if (afterLoadScriptEngine != null)
1337 			afterLoadScriptEngine.setScript(script);
1338 
1339 		notifyPropertyChanged(AFTER_LOAD_SCRIPT_PROPERTY, oldScript, script);
1340 	}
1341 
1342 	public String getAfterLoadScript()
1343 	{
1344 		return getConfig().isSetAfterLoadScript() ? getConfig().getAfterLoadScript().getStringValue() : null;
1345 	}
1346 
1347 	public void setBeforeSaveScript(String script)
1348 	{
1349 		String oldScript = getBeforeSaveScript();
1350 
1351 		if (!getConfig().isSetBeforeSaveScript())
1352 			getConfig().addNewBeforeSaveScript();
1353 
1354 		getConfig().getBeforeSaveScript().setStringValue(script);
1355 		if (beforeSaveScriptEngine != null)
1356 			beforeSaveScriptEngine.setScript(script);
1357 
1358 		notifyPropertyChanged(BEFORE_SAVE_SCRIPT_PROPERTY, oldScript, script);
1359 	}
1360 
1361 	public String getBeforeSaveScript()
1362 	{
1363 		return getConfig().isSetBeforeSaveScript() ? getConfig().getBeforeSaveScript().getStringValue() : null;
1364 	}
1365 
1366 	public Object runAfterLoadScript() throws Exception
1367 	{
1368 		String script = getAfterLoadScript();
1369 		if (StringUtils.isNullOrEmpty(script))
1370 			return null;
1371 
1372 		if (afterLoadScriptEngine == null)
1373 		{
1374 			afterLoadScriptEngine = SoapUIScriptEngineRegistry.create(this);
1375 			afterLoadScriptEngine.setScript(script);
1376 		}
1377 
1378 		afterLoadScriptEngine.setVariable("context", context);
1379 		afterLoadScriptEngine.setVariable("project", this);
1380 		afterLoadScriptEngine.setVariable("log", SoapUI.ensureGroovyLog());
1381 		return afterLoadScriptEngine.run();
1382 	}
1383 
1384 	public Object runBeforeSaveScript() throws Exception
1385 	{
1386 		String script = getBeforeSaveScript();
1387 		if (StringUtils.isNullOrEmpty(script))
1388 			return null;
1389 
1390 		if (beforeSaveScriptEngine == null)
1391 		{
1392 			beforeSaveScriptEngine = SoapUIScriptEngineRegistry.create(this);
1393 			beforeSaveScriptEngine.setScript(script);
1394 		}
1395 
1396 		beforeSaveScriptEngine.setVariable("context", context);
1397 		beforeSaveScriptEngine.setVariable("project", this);
1398 		beforeSaveScriptEngine.setVariable("log", SoapUI.ensureGroovyLog());
1399 		return beforeSaveScriptEngine.run();
1400 	}
1401 
1402 	public PropertyExpansionContext getContext()
1403 	{
1404 		return context;
1405 	}
1406 
1407 	public DefaultWssContainer getWssContainer()
1408 	{
1409 		return wssContainer;
1410 	}
1411 
1412 	@Override
1413 	public void resolve(ResolveContext<?> context)
1414 	{
1415 		super.resolve(context);
1416 
1417 		wssContainer.resolve(context);
1418 	}
1419 
1420 	public PropertyExpansion[] getPropertyExpansions()
1421 	{
1422 		List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
1423 
1424 		result.addAll(Arrays.asList(wssContainer.getPropertyExpansions()));
1425 		// result.addAll(Arrays.asList(databaseConnectionContainer.
1426 		// getPropertyExpansions()));
1427 
1428 		return result.toArray(new PropertyExpansion[result.size()]);
1429 
1430 	}
1431 
1432 	public String getPropertiesLabel()
1433 	{
1434 		return "Custom Properties";
1435 	}
1436 
1437 	public String getShadowPassword()
1438 	{
1439 		projectPassword = getSettings() == null ? projectPassword : getSettings().getString(
1440 				ProjectSettings.SHADOW_PASSWORD, null);
1441 		return projectPassword;
1442 	}
1443 
1444 	public void setShadowPassword(String password)
1445 	{
1446 		String oldPassword = getSettings().getString(ProjectSettings.SHADOW_PASSWORD, null);
1447 		getSettings().setString(ProjectSettings.SHADOW_PASSWORD, password);
1448 		this.pcs.firePropertyChange("projectPassword", oldPassword, password);
1449 	}
1450 
1451 	public String getHermesConfig()
1452 	{
1453 		hermesConfig = getSettings() == null ? hermesConfig : resolveHermesConfig();
1454 		return hermesConfig;
1455 	}
1456 
1457 	private String resolveHermesConfig()
1458 	{
1459 		String hermesConfigProperty = getSettings().getString(ProjectSettings.HERMES_CONFIG, null);
1460 		if (hermesConfigProperty != null && !hermesConfigProperty.equals(""))
1461 		{
1462 			return hermesConfigProperty;
1463 		}
1464 		else if (System.getenv("HERMES_CONFIG") != null)
1465 		{
1466 			return System.getenv("HERMES_CONFIG");
1467 		}
1468 		else
1469 		{
1470 			return  "${#System#user.home}//.hermes";
1471 		}
1472 
1473 	}
1474 
1475 	public void setHermesConfig(String hermesConfigPath)
1476 	{
1477 		String oldHermesConfigPath = getSettings().getString(ProjectSettings.HERMES_CONFIG, null);
1478 		getSettings().setString(ProjectSettings.HERMES_CONFIG, hermesConfigPath);
1479 		this.pcs.firePropertyChange("hermesConfig", oldHermesConfigPath, hermesConfigPath);
1480 
1481 	}
1482 
1483 	public void inspect()
1484 	{
1485 
1486 		if (!isOpen())
1487 			return;
1488 
1489 		byte data[] = projectDocument.getSoapuiProject().getEncryptedContent();
1490 		if (data != null && data.length > 0)
1491 		{
1492 			try
1493 			{
1494 				reload();
1495 			}
1496 			catch (SoapUIException e)
1497 			{
1498 				e.printStackTrace();
1499 			}
1500 		}
1501 	}
1502 
1503 	public int getEncrypted()
1504 	{
1505 		return this.encrypted;
1506 	}
1507 
1508 	public int setEncrypted(int code)
1509 	{
1510 		return this.encrypted = code;
1511 	}
1512 
1513 	public void addPropertyChangeListener(PropertyChangeListener listener)
1514 	{
1515 		this.pcs.addPropertyChangeListener(listener);
1516 	}
1517 
1518 	public void propertyChange(PropertyChangeEvent evt)
1519 	{
1520 		if ("projectPassword".equals(evt.getPropertyName()))
1521 		{
1522 			if (encrypted == 0 & (evt.getOldValue() == null || ((String) evt.getOldValue()).length() == 0))
1523 			{
1524 				encrypted = 1;
1525 			}
1526 			if (encrypted == 1 & (evt.getNewValue() == null || ((String) evt.getNewValue()).length() == 0))
1527 			{
1528 				encrypted = 0;
1529 			}
1530 			SoapUI.getNavigator().repaint();
1531 		}
1532 
1533 	}
1534 
1535 	public SoapuiProjectDocumentConfig getProjectDocument()
1536 	{
1537 		return projectDocument;
1538 	}
1539 
1540 	public int getInterfaceCount(String type)
1541 	{
1542 		int result = 0;
1543 
1544 		for (AbstractInterface<?> iface : interfaces)
1545 		{
1546 			if (iface.getType().equals(type))
1547 				result++;
1548 		}
1549 
1550 		return result;
1551 	}
1552 
1553 	public List<AbstractInterface<?>> getInterfaces(String type)
1554 	{
1555 		ArrayList<AbstractInterface<?>> result = new ArrayList<AbstractInterface<?>>();
1556 
1557 		for (AbstractInterface<?> iface : interfaces)
1558 		{
1559 			if (iface.getType().equals(type))
1560 				result.add(iface);
1561 		}
1562 
1563 		return result;
1564 	}
1565 
1566 	public void importTestSuite(File file)
1567 	{
1568 		if (!file.exists())
1569 		{
1570 			UISupport.showErrorMessage("Error loading test case ");
1571 			return;
1572 		}
1573 
1574 		TestSuiteDocumentConfig newTestSuiteConfig = null;
1575 
1576 		try
1577 		{
1578 			newTestSuiteConfig = TestSuiteDocumentConfig.Factory.parse(file);
1579 		}
1580 		catch (Exception e)
1581 		{
1582 			SoapUI.logError(e);
1583 		}
1584 
1585 		if (newTestSuiteConfig == null)
1586 		{
1587 			UISupport.showErrorMessage("Not valild test case xml");
1588 		}
1589 		else
1590 		{
1591 			TestSuiteConfig config = (TestSuiteConfig) projectDocument.getSoapuiProject().addNewTestSuite().set(
1592 					newTestSuiteConfig.getTestSuite());
1593 			WsdlTestSuite testSuite = buildTestSuite(config);
1594 
1595 			ModelSupport.unsetIds(testSuite);
1596 			testSuite.afterLoad();
1597 
1598 			testSuites.add(testSuite);
1599 			fireTestSuiteAdded(testSuite);
1600 
1601 			resolveImportedTestSuite(testSuite);
1602 		}
1603 	}
1604 
1605 	private void resolveImportedTestSuite(WsdlTestSuite testSuite)
1606 	{
1607 		ResolveDialog resolver = new ResolveDialog("Validate TestSuite", "Checks TestSuite for inconsistencies", null);
1608 		resolver.setShowOkMessage(false);
1609 		resolver.resolve(testSuite);
1610 	}
1611 
1612 	/***
1613 	 * @see com.eviware.soapui.impl.WsdlInterfaceFactory.importWsdl
1614 	 * @deprecated
1615 	 */
1616 
1617 	public WsdlInterface[] importWsdl(String url, boolean createRequests) throws SoapUIException
1618 	{
1619 		return WsdlInterfaceFactory.importWsdl(this, url, createRequests);
1620 	}
1621 
1622 	/***
1623 	 * @see com.eviware.soapui.impl.WsdlInterfaceFactory.importWsdl
1624 	 * @deprecated see WsdlInterfaceFactory
1625 	 */
1626 
1627 	public WsdlInterface[] importWsdl(String url, boolean createRequests, WsdlLoader wsdlLoader) throws SoapUIException
1628 	{
1629 		return WsdlInterfaceFactory.importWsdl(this, url, createRequests, null, wsdlLoader);
1630 	}
1631 
1632 	/***
1633 	 * @see com.eviware.soapui.impl.WsdlInterfaceFactory.importWsdl
1634 	 * @deprecated see WsdlInterfaceFactory
1635 	 */
1636 
1637 	public WsdlInterface[] importWsdl(String url, boolean createRequests, QName bindingName, WsdlLoader wsdlLoader)
1638 			throws SoapUIException
1639 	{
1640 		return WsdlInterfaceFactory.importWsdl(this, url, createRequests, bindingName, wsdlLoader);
1641 	}
1642 
1643 	public void setDefaultScriptLanguage(String id)
1644 	{
1645 		getConfig().setDefaultScriptLanguage(id);
1646 	}
1647 
1648 	public String getDefaultScriptLanguage()
1649 	{
1650 		if (getConfig().isSetDefaultScriptLanguage())
1651 			return getConfig().getDefaultScriptLanguage();
1652 		else
1653 			return SoapUIScriptEngineRegistry.DEFAULT_SCRIPT_ENGINE_ID;
1654 	}
1655 
1656 	public int getIndexOfTestSuite(TestSuite testSuite)
1657 	{
1658 		return testSuites.indexOf(testSuite);
1659 	}
1660 
1661 	public String getBeforeRunScript()
1662 	{
1663 		return getConfig().isSetBeforeRunScript() ? getConfig().getBeforeRunScript().getStringValue() : null;
1664 	}
1665 
1666 	public void setBeforeRunScript(String script)
1667 	{
1668 		String oldScript = getBeforeRunScript();
1669 
1670 		if (!getConfig().isSetBeforeRunScript())
1671 			getConfig().addNewBeforeRunScript();
1672 
1673 		getConfig().getBeforeRunScript().setStringValue(script);
1674 		if (beforeRunScriptEngine != null)
1675 			beforeRunScriptEngine.setScript(script);
1676 
1677 		notifyPropertyChanged("beforeRunScript", oldScript, script);
1678 	}
1679 
1680 	public Object runBeforeRunScript(ProjectRunContext context, ProjectRunner runner) throws Exception
1681 	{
1682 		String script = getBeforeRunScript();
1683 		if (StringUtils.isNullOrEmpty(script))
1684 			return null;
1685 
1686 		if (beforeRunScriptEngine == null)
1687 		{
1688 			beforeRunScriptEngine = SoapUIScriptEngineRegistry.create(this);
1689 			beforeRunScriptEngine.setScript(script);
1690 		}
1691 
1692 		beforeRunScriptEngine.setVariable("runner", runner);
1693 		beforeRunScriptEngine.setVariable("context", context);
1694 		beforeRunScriptEngine.setVariable("project", this);
1695 		beforeRunScriptEngine.setVariable("log", SoapUI.ensureGroovyLog());
1696 		return beforeRunScriptEngine.run();
1697 	}
1698 
1699 	public String getAfterRunScript()
1700 	{
1701 		return getConfig().isSetAfterRunScript() ? getConfig().getAfterRunScript().getStringValue() : null;
1702 	}
1703 
1704 	public void setAfterRunScript(String script)
1705 	{
1706 		String oldScript = getAfterRunScript();
1707 
1708 		if (!getConfig().isSetAfterRunScript())
1709 			getConfig().addNewAfterRunScript();
1710 
1711 		getConfig().getAfterRunScript().setStringValue(script);
1712 		if (afterRunScriptEngine != null)
1713 			afterRunScriptEngine.setScript(script);
1714 
1715 		notifyPropertyChanged("afterRunScript", oldScript, script);
1716 	}
1717 
1718 	public Object runAfterRunScript(ProjectRunContext context, ProjectRunner runner) throws Exception
1719 	{
1720 		String script = getAfterRunScript();
1721 		if (StringUtils.isNullOrEmpty(script))
1722 			return null;
1723 
1724 		if (afterRunScriptEngine == null)
1725 		{
1726 			afterRunScriptEngine = SoapUIScriptEngineRegistry.create(this);
1727 			afterRunScriptEngine.setScript(script);
1728 		}
1729 
1730 		afterRunScriptEngine.setVariable("runner", runner);
1731 		afterRunScriptEngine.setVariable("context", context);
1732 		afterRunScriptEngine.setVariable("project", this);
1733 		afterRunScriptEngine.setVariable("log", SoapUI.ensureGroovyLog());
1734 		return afterRunScriptEngine.run();
1735 	}
1736 
1737 	public void addProjectRunListener(ProjectRunListener projectRunListener)
1738 	{
1739 		runListeners.add(projectRunListener);
1740 	}
1741 
1742 	public void removeProjectRunListener(ProjectRunListener projectRunListener)
1743 	{
1744 		runListeners.remove(projectRunListener);
1745 	}
1746 
1747 	public WsdlProjectRunner run(StringToObjectMap context, boolean async)
1748 	{
1749 		WsdlProjectRunner runner = new WsdlProjectRunner(this, context);
1750 		runner.start(async);
1751 		return runner;
1752 	}
1753 
1754 	public boolean isAbortOnError()
1755 	{
1756 		return getConfig().getAbortOnError();
1757 	}
1758 
1759 	// public boolean isFailOnErrors()
1760 	// {
1761 	// return getConfig().getFailOnErrors();
1762 	// }
1763 	//	
1764 	// public void setFailOnErrors( boolean arg0 )
1765 	// {
1766 	// getConfig().setFailOnErrors( arg0 );
1767 	// }
1768 
1769 	public void setAbortOnError(boolean arg0)
1770 	{
1771 		getConfig().setAbortOnError(arg0);
1772 	}
1773 
1774 	public long getTimeout()
1775 	{
1776 		return getConfig().getTimeout();
1777 	}
1778 
1779 	public void setTimeout(long timeout)
1780 	{
1781 		getConfig().setTimeout(timeout);
1782 	}
1783 
1784 	public ProjectRunListener[] getProjectRunListeners()
1785 	{
1786 		return runListeners.toArray(new ProjectRunListener[runListeners.size()]);
1787 	}
1788 
1789 	public TestSuiteRunType getRunType()
1790 	{
1791 		Enum runType = getConfig().getRunType();
1792 
1793 		if (TestSuiteRunTypesConfig.PARALLELL.equals(runType))
1794 			return TestSuiteRunType.PARALLEL;
1795 		else
1796 			return TestSuiteRunType.SEQUENTIAL;
1797 	}
1798 
1799 	public void setRunType(TestSuiteRunType runType)
1800 	{
1801 		TestSuiteRunType oldRunType = getRunType();
1802 
1803 		if (runType == TestSuiteRunType.PARALLEL && oldRunType != TestSuiteRunType.PARALLEL)
1804 		{
1805 			getConfig().setRunType(TestSuiteRunTypesConfig.PARALLELL);
1806 			notifyPropertyChanged("runType", oldRunType, runType);
1807 		}
1808 		else if (runType == TestSuiteRunType.SEQUENTIAL && oldRunType != TestSuiteRunType.SEQUENTIAL)
1809 		{
1810 			getConfig().setRunType(TestSuiteRunTypesConfig.SEQUENTIAL);
1811 			notifyPropertyChanged("runType", oldRunType, runType);
1812 		}
1813 	}
1814 
1815 	public WsdlTestSuite moveTestSuite(int ix, int offset)
1816 	{
1817 		WsdlTestSuite testSuite = testSuites.get(ix);
1818 
1819 		if (offset == 0)
1820 			return testSuite;
1821 
1822 		testSuites.remove(ix);
1823 		testSuites.add(ix + offset, testSuite);
1824 
1825 		TestSuiteConfig[] configs = new TestSuiteConfig[testSuites.size()];
1826 
1827 		for (int c = 0; c < testSuites.size(); c++)
1828 		{
1829 			if (offset > 0)
1830 			{
1831 				if (c < ix)
1832 					configs[c] = (TestSuiteConfig) getConfig().getTestSuiteArray(c).copy();
1833 				else if (c < (ix + offset))
1834 					configs[c] = (TestSuiteConfig) getConfig().getTestSuiteArray(c + 1).copy();
1835 				else if (c == ix + offset)
1836 					configs[c] = (TestSuiteConfig) getConfig().getTestSuiteArray(ix).copy();
1837 				else
1838 					configs[c] = (TestSuiteConfig) getConfig().getTestSuiteArray(c).copy();
1839 			}
1840 			else
1841 			{
1842 				if (c < ix + offset)
1843 					configs[c] = (TestSuiteConfig) getConfig().getTestSuiteArray(c).copy();
1844 				else if (c == ix + offset)
1845 					configs[c] = (TestSuiteConfig) getConfig().getTestSuiteArray(ix).copy();
1846 				else if (c <= ix)
1847 					configs[c] = (TestSuiteConfig) getConfig().getTestSuiteArray(c - 1).copy();
1848 				else
1849 					configs[c] = (TestSuiteConfig) getConfig().getTestSuiteArray(c).copy();
1850 			}
1851 		}
1852 
1853 		getConfig().setTestSuiteArray(configs);
1854 		for (int c = 0; c < configs.length; c++)
1855 		{
1856 			testSuites.get(c).resetConfigOnMove(getConfig().getTestSuiteArray(c));
1857 		}
1858 
1859 		fireTestSuiteMoved(testSuite, ix, offset);
1860 		return testSuite;
1861 
1862 	}
1863 
1864 	public void importMockService(File file)
1865 	{
1866 		if (!file.exists())
1867 		{
1868 			UISupport.showErrorMessage("Error loading test case ");
1869 			return;
1870 		}
1871 
1872 		MockServiceDocumentConfig newMockServiceConfig = null;
1873 
1874 		try
1875 		{
1876 			newMockServiceConfig = MockServiceDocumentConfig.Factory.parse(file);
1877 		}
1878 		catch (Exception e)
1879 		{
1880 			SoapUI.logError(e);
1881 		}
1882 
1883 		if (newMockServiceConfig == null)
1884 		{
1885 			UISupport.showErrorMessage("Not valid mock service xml");
1886 		}
1887 		else
1888 		{
1889 			MockServiceConfig config = (MockServiceConfig) projectDocument.getSoapuiProject().addNewMockService().set(
1890 					newMockServiceConfig.getMockService());
1891 			WsdlMockService mockService = new WsdlMockService(this, config);
1892 
1893 			ModelSupport.unsetIds(mockService);
1894 			mockService.afterLoad();
1895 
1896 			mockServices.add(mockService);
1897 			fireMockServiceAdded(mockService);
1898 
1899 			resolveImportedMockService(mockService);
1900 		}
1901 	}
1902 
1903 	private void resolveImportedMockService(WsdlMockService mockService)
1904 	{
1905 		ResolveDialog resolver = new ResolveDialog("Validate MockService", "Checks MockService for inconsistencies", null);
1906 		resolver.setShowOkMessage(false);
1907 		resolver.resolve(mockService);
1908 	}
1909 }