/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.impl.wsdl.teststeps;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import javax.swing.ImageIcon;
import com.eviware.soapui.config.PropertiesStepConfig;
import com.eviware.soapui.config.TestStepConfig;
import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
import com.eviware.soapui.impl.wsdl.support.ExternalDependency;
import com.eviware.soapui.impl.wsdl.support.PathPropertyExternalDependency;
import com.eviware.soapui.impl.wsdl.support.XmlBeansPropertiesTestPropertyHolder;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
import com.eviware.soapui.model.testsuite.TestCaseRunContext;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.model.testsuite.TestPropertyListener;
import com.eviware.soapui.model.testsuite.TestStepResult;
import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.resolver.ResolveContext;
import com.eviware.soapui.support.types.StringList;
/**
* TestStep that holds an arbitrary number of custom properties
*
* @author ole.matzura
*/
public class WsdlPropertiesTestStep extends WsdlTestStep implements MutableTestPropertyHolder
{
private PropertiesStepConfig propertiesStepConfig;
private ImageIcon okIcon;
private ImageIcon failedIcon;
private XmlBeansPropertiesTestPropertyHolder propertyHolderSupport;
private BeanPathPropertySupport sourceProperty;
private BeanPathPropertySupport targetProperty;
public static final String SOURCE_PROPERTY = WsdlPropertiesTestStep.class.getName() + "@source";
public static final String TARGET_PROPERTY = WsdlPropertiesTestStep.class.getName() + "@target";
public WsdlPropertiesTestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
{
super( testCase, config, true, forLoadTest );
if( !forLoadTest )
{
okIcon = UISupport.createImageIcon( "/properties_step.gif" );
failedIcon = UISupport.createImageIcon( "/properties_step_failed.gif" );
setIcon( okIcon );
}
if( config.getConfig() == null )
{
propertiesStepConfig = ( PropertiesStepConfig )config.addNewConfig().changeType( PropertiesStepConfig.type );
propertiesStepConfig.addNewProperties();
propertiesStepConfig.setCreateMissingOnLoad( true );
}
else
{
propertiesStepConfig = ( PropertiesStepConfig )config.getConfig().changeType( PropertiesStepConfig.type );
if( !propertiesStepConfig.isSetProperties() )
{
propertiesStepConfig.addNewProperties();
}
if( !propertiesStepConfig.isSetSaveFirst() )
propertiesStepConfig.setSaveFirst( true );
}
propertyHolderSupport = new XmlBeansPropertiesTestPropertyHolder( this, propertiesStepConfig.getProperties() );
sourceProperty = new BeanPathPropertySupport( this, propertiesStepConfig, "source" );
targetProperty = new BeanPathPropertySupport( this, propertiesStepConfig, "target" );
}
public TestStepResult run( TestCaseRunner testRunner, TestCaseRunContext testRunContext )
{
WsdlTestStepResult result = new WsdlTestStepResult( this );
if( okIcon != null )
setIcon( okIcon );
result.setStatus( TestStepStatus.OK );
result.startTimer();
if( isSaveFirst() )
saveDuringRun( result, testRunContext );
String source = sourceProperty.expand( testRunContext );
if( StringUtils.hasContent( source ) )
{
try
{
int cnt = loadProperties( source, isCreateMissingOnLoad() );
result.setStatus( TestStepStatus.OK );
result.addMessage( "Loaded " + cnt + " properties from [" + source + "]" );
}
catch( IOException e )
{
result.stopTimer();
result.addMessage( "Failed to load properties from [" + source + "]" );
result.setStatus( TestStepStatus.FAILED );
result.setError( e );
if( failedIcon != null )
setIcon( failedIcon );
}
}
if( !isSaveFirst() )
saveDuringRun( result, testRunContext );
result.stopTimer();
return result;
}
private boolean saveDuringRun( WsdlTestStepResult result, TestCaseRunContext context )
{
String target = targetProperty.expand( context );
if( StringUtils.hasContent( target ) )
{
try
{
int cnt = saveProperties( target );
result.setStatus( TestStepStatus.OK );
result.addMessage( "Saved " + cnt + " properties to [" + target + "]" );
}
catch( IOException e )
{
result.stopTimer();
result.addMessage( "Failed to save properties to [" + target + "]" );
result.setStatus( TestStepStatus.FAILED );
result.setError( e );
if( failedIcon != null )
setIcon( failedIcon );
return false;
}
}
return true;
}
private int saveProperties( String target ) throws IOException
{
return propertyHolderSupport.saveTo( System.getProperty( target, target ) );
}
private int loadProperties( String source, boolean createMissing ) throws IOException
{
// override methods so propertynames are returned in readorder
java.util.Properties props = new java.util.Properties()
{
public StringList names = new StringList();
@Override
public synchronized Object put( Object key, Object value )
{
names.add( key.toString() );
return super.put( key, value );
}
@Override
public Enumeration<?> propertyNames()
{
return Collections.enumeration( names );
}
};
InputStream in = getPropertiesInputStream( source );
props.load( in );
in.close();
int cnt = 0;
Enumeration<?> names = props.propertyNames();
while( names.hasMoreElements() )
{
String name = names.nextElement().toString();
TestProperty property = getProperty( name );
if( property != null )
{
property.setValue( props.get( name ).toString() );
cnt++ ;
}
else if( createMissing )
{
addProperty( name ).setValue( props.get( name ).toString() );
cnt++ ;
}
}
return cnt;
}
private InputStream getPropertiesInputStream( String source ) throws IOException
{
String fileProperty = System.getProperty( source );
if( fileProperty != null )
source = fileProperty;
URL url;
try
{
url = new URL( source );
}
catch( MalformedURLException e )
{
url = new URL( "file:" + source );
}
return url.openStream();
}
public TestProperty getTestStepPropertyAt( int index )
{
return propertyHolderSupport.getPropertyAt( index );
}
public int getStepPropertyCount()
{
return propertyHolderSupport.getPropertyCount();
}
public String getSource()
{
return sourceProperty.get();
}
public void setSource( String source )
{
sourceProperty.set( source, true );
}
public String getTarget()
{
return targetProperty.get();
}
public String getLabel()
{
String str = super.getName() + " (" + getPropertyCount() + ")";
if( isDisabled() )
str += " (disabled)";
return str;
}
public void setTarget( String target )
{
targetProperty.set( target, true );
}
public void resetConfigOnMove( TestStepConfig config )
{
super.resetConfigOnMove( config );
propertiesStepConfig = ( PropertiesStepConfig )config.getConfig().changeType( PropertiesStepConfig.type );
propertyHolderSupport.resetPropertiesConfig( propertiesStepConfig.getProperties() );
sourceProperty.setConfig( propertiesStepConfig );
targetProperty.setConfig( propertiesStepConfig );
}
public int loadProperties( boolean createMissing ) throws IOException
{
return loadProperties( sourceProperty.expand(), createMissing );
}
public int saveProperties() throws IOException
{
String target = PropertyExpander.expandProperties( this, targetProperty.expand() );
return saveProperties( target );
}
public boolean isCreateMissingOnLoad()
{
return propertiesStepConfig.getCreateMissingOnLoad();
}
public void setCreateMissingOnLoad( boolean b )
{
propertiesStepConfig.setCreateMissingOnLoad( b );
}
public boolean isSaveFirst()
{
return propertiesStepConfig.getSaveFirst();
}
public void setSaveFirst( boolean b )
{
propertiesStepConfig.setSaveFirst( b );
}
public boolean isDiscardValuesOnSave()
{
return propertiesStepConfig.getDiscardValuesOnSave();
}
public void setDiscardValuesOnSave( boolean b )
{
propertiesStepConfig.setDiscardValuesOnSave( b );
}
public void setPropertyValue( String name, String value )
{
if( isCreateMissingOnLoad() && getProperty( name ) == null )
addProperty( name );
propertyHolderSupport.setPropertyValue( name, value );
}
@Override
public void beforeSave()
{
super.beforeSave();
if( isDiscardValuesOnSave() )
{
clearPropertyValues();
}
}
public void clearPropertyValues()
{
for( TestProperty property : propertyHolderSupport.getProperties().values() )
property.setValue( null );
}
public boolean renameProperty( String name, String newName )
{
return PropertyExpansionUtils.renameProperty( propertyHolderSupport.getProperty( name ), newName, getTestCase() ) != null;
}
public TestProperty addProperty( String name )
{
String oldLabel = getLabel();
TestProperty property = propertyHolderSupport.addProperty( name );
notifyPropertyChanged( WsdlTestStep.LABEL_PROPERTY, oldLabel, getLabel() );
return property;
}
public void addTestPropertyListener( TestPropertyListener listener )
{
propertyHolderSupport.addTestPropertyListener( listener );
}
public Map<String, TestProperty> getProperties()
{
return propertyHolderSupport.getProperties();
}
public TestProperty getProperty( String name )
{
return propertyHolderSupport.getProperty( name );
}
public TestProperty getPropertyAt( int index )
{
return propertyHolderSupport.getPropertyAt( index );
}
public List<TestProperty> getPropertyList()
{
return propertyHolderSupport.getPropertyList();
}
public int getPropertyCount()
{
return propertyHolderSupport.getPropertyCount();
}
public String[] getPropertyNames()
{
return propertyHolderSupport.getPropertyNames();
}
public String getPropertyValue( String name )
{
return propertyHolderSupport.getPropertyValue( name );
}
public TestProperty removeProperty( String propertyName )
{
String oldLabel = getLabel();
TestProperty result = propertyHolderSupport.removeProperty( propertyName );
notifyPropertyChanged( WsdlTestStep.LABEL_PROPERTY, oldLabel, getLabel() );
return result;
}
public void removeTestPropertyListener( TestPropertyListener listener )
{
propertyHolderSupport.removeTestPropertyListener( listener );
}
public boolean hasProperty( String name )
{
return propertyHolderSupport.hasProperty( name );
}
public void addExternalDependency( List<ExternalDependency> dependencies )
{
super.addExternalDependencies( dependencies );
dependencies.add( new PathPropertyExternalDependency( targetProperty ) );
dependencies.add( new PathPropertyExternalDependency( sourceProperty ) );
}
@Override
public void resolve( ResolveContext<?> context )
{
super.resolve( context );
targetProperty.resolveFile( context, "Missing target property file", "properties",
"Properties Files (*.properties)", true );
sourceProperty.resolveFile( context, "Missing source property file", "properties",
"Properties Files (*.properties)", true );
}
public void moveProperty( String propertyName, int targetIndex )
{
propertyHolderSupport.moveProperty( propertyName, targetIndex );
}
public String getSource( boolean expand )
{
return expand ? sourceProperty.expand() : getSource();
}
public String getTarget( boolean expand )
{
return expand ? targetProperty.expand() : getTarget();
}
}