/*
* 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.rest;
import java.beans.PropertyChangeEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.apache.xmlbeans.SchemaGlobalElement;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlString;
import com.eviware.soapui.config.AttachmentConfig;
import com.eviware.soapui.config.RestRequestConfig;
import com.eviware.soapui.config.StringToStringMapConfig;
import com.eviware.soapui.impl.rest.RestRepresentation.Type;
import com.eviware.soapui.impl.rest.support.RestParamProperty;
import com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder;
import com.eviware.soapui.impl.rest.support.RestRequestParamsPropertyHolder;
import com.eviware.soapui.impl.support.AbstractHttpRequest;
import com.eviware.soapui.impl.wsdl.HttpAttachmentPart;
import com.eviware.soapui.impl.wsdl.WsdlSubmit;
import com.eviware.soapui.impl.wsdl.submit.RequestTransportRegistry;
import com.eviware.soapui.impl.wsdl.submit.transports.http.HttpResponse;
import com.eviware.soapui.impl.wsdl.submit.transports.jms.JMSHeader;
import com.eviware.soapui.impl.wsdl.support.PathUtils;
import com.eviware.soapui.impl.wsdl.support.jms.header.JMSHeaderConfig;
import com.eviware.soapui.impl.wsdl.support.jms.property.JMSPropertiesConfig;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.iface.MessagePart;
import com.eviware.soapui.model.iface.MessagePart.ContentPart;
import com.eviware.soapui.model.iface.SubmitContext;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionsResult;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.model.testsuite.TestPropertyListener;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.types.StringList;
import com.eviware.soapui.support.types.StringToStringMap;
/**
* Request implementation holding a SOAP request
*
* @author Ole.Matzura
*/
public class RestRequest extends AbstractHttpRequest<RestRequestConfig> implements RestRequestInterface
{
private RestMethod method;
private RestRequestParamsPropertyHolder params;
private ParamUpdater paramUpdater;
public RestRequest( RestMethod method, RestRequestConfig requestConfig, boolean forLoadTest )
{
super( requestConfig, method.getOperation(), "/rest_request.gif", false );
this.method = method;
if( requestConfig.getParameters() == null )
requestConfig.addNewParameters();
StringToStringMap paramValues = StringToStringMap.fromXml( requestConfig.getParameters() );
params = new RestRequestParamsPropertyHolder( method.getOverlayParams(), this, paramValues );
paramUpdater = new ParamUpdater( paramValues );
params.addTestPropertyListener( paramUpdater );
if( method != null )
method.addPropertyChangeListener( this );
}
public ModelItem getParent()
{
return getRestMethod();
}
public RestMethod getRestMethod()
{
return method;
}
protected RequestIconAnimator<?> initIconAnimator()
{
return new RequestIconAnimator<AbstractHttpRequest<?>>( this, "/rest_request.gif", "/exec_rest_request", 4, "gif" );
}
public MessagePart[] getRequestParts()
{
List<MessagePart> result = new ArrayList<MessagePart>();
for( int c = 0; c < getPropertyCount(); c++ )
{
result.add( new ParameterMessagePart( getPropertyAt( c ) ) );
}
if( getMethod() == RestRequestInterface.RequestMethod.POST
|| getMethod() == RestRequestInterface.RequestMethod.PUT )
{
result.add( new RestContentPart() );
}
return result.toArray( new MessagePart[result.size()] );
}
public RestRepresentation[] getRepresentations()
{
return getRepresentations( null, null );
}
public RestRepresentation[] getRepresentations( RestRepresentation.Type type )
{
return getRepresentations( type, null );
}
public RestRepresentation[] getRepresentations( RestRepresentation.Type type, String mediaType )
{
return getRestMethod().getRepresentations( type, mediaType );
}
public MessagePart[] getResponseParts()
{
return new MessagePart[0];
}
public RestRequestInterface.RequestMethod getMethod()
{
return getRestMethod().getMethod();
}
public String getAccept()
{
String accept = getConfig().getAccept();
return accept == null ? "" : accept;
}
public void setAccept( String acceptEncoding )
{
String old = getAccept();
getConfig().setAccept( acceptEncoding );
notifyPropertyChanged( "accept", old, acceptEncoding );
}
public void setMediaType( String mediaType )
{
String old = getMediaType();
getConfig().setMediaType( mediaType );
notifyPropertyChanged( "mediaType", old, mediaType );
}
public String getMediaType()
{
if( getConfig().getMediaType() == null )
{
String mediaType = getRestMethod().getDefaultRequestMediaType();
getConfig().setMediaType( mediaType );
notifyPropertyChanged( "mediaType", null, mediaType );
}
return getConfig().getMediaType();
}
public void setMethod( RequestMethod method )
{
getRestMethod().setMethod( method );
}
public WsdlSubmit<RestRequest> submit( SubmitContext submitContext, boolean async ) throws SubmitException
{
String endpoint = PropertyExpander.expandProperties( submitContext, getEndpoint() );
if( StringUtils.isNullOrEmpty( endpoint ) )
{
try
{
endpoint = new URL( getPath() ).toString();
}
catch( MalformedURLException e )
{
}
}
if( StringUtils.isNullOrEmpty( endpoint ) )
{
UISupport.showErrorMessage( "Missing endpoint for request [" + getName() + "]" );
return null;
}
try
{
WsdlSubmit<RestRequest> submitter = new WsdlSubmit<RestRequest>( this, getSubmitListeners(),
RequestTransportRegistry.getTransport( endpoint, submitContext ) );
submitter.submitRequest( submitContext, async );
return submitter;
}
catch( Exception e )
{
throw new SubmitException( e.toString() );
}
}
public PropertyExpansion[] getPropertyExpansions()
{
PropertyExpansionsResult result = new PropertyExpansionsResult( this, this );
result.addAll( super.getPropertyExpansions() );
result.addAll( getRestMethod().getPropertyExpansions() );
result.addAll( params.getPropertyExpansions() );
addJMSHeaderExpansions( result, getJMSHeaderConfig(), this );
return result.toArray();
}
public void addJMSHeaderExpansions( PropertyExpansionsResult result, JMSHeaderConfig jmsHeaderConfig,
ModelItem modelItem )
{
result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig,
JMSHeader.JMSCORRELATIONID ) );
result.addAll( PropertyExpansionUtils
.extractPropertyExpansions( modelItem, jmsHeaderConfig, JMSHeader.JMSREPLYTO ) );
result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig, JMSHeader.JMSTYPE ) );
result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig,
JMSHeader.JMSPRIORITY ) );
result.addAll( PropertyExpansionUtils
.extractPropertyExpansions( modelItem, jmsHeaderConfig, JMSHeader.TIMETOLIVE ) );
result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig,
JMSHeader.DURABLE_SUBSCRIPTION_NAME ) );
result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig, JMSHeader.CLIENT_ID ) );
result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig,
JMSHeader.SEND_AS_BYTESMESSAGE ) );
result.addAll( PropertyExpansionUtils.extractPropertyExpansions( modelItem, jmsHeaderConfig,
JMSHeader.SOAP_ACTION_ADD ) );
}
public TestProperty addProperty( String name )
{
return params.addProperty( name );
}
public void moveProperty( String propertyName, int targetIndex )
{
params.moveProperty( propertyName, targetIndex );
}
public TestProperty removeProperty( String propertyName )
{
return params.removeProperty( propertyName );
}
public boolean renameProperty( String name, String newName )
{
return params.renameProperty( name, newName );
}
public void addTestPropertyListener( TestPropertyListener listener )
{
params.addTestPropertyListener( listener );
}
public ModelItem getModelItem()
{
return this;
}
@Override
public RestResource getOperation()
{
return ( RestResource )method.getOperation();
}
public Map<String, TestProperty> getProperties()
{
return params.getProperties();
}
public RestParamProperty getProperty( String name )
{
return params.getProperty( name );
}
public RestParamProperty getPropertyAt( int index )
{
return params.getPropertyAt( index );
}
public int getPropertyCount()
{
return params.getPropertyCount();
}
public String[] getPropertyNames()
{
return params.getPropertyNames();
}
public String getPropertyValue( String name )
{
return params.getPropertyValue( name );
}
public boolean hasProperty( String name )
{
return params.hasProperty( name );
}
public void removeTestPropertyListener( TestPropertyListener listener )
{
params.removeTestPropertyListener( listener );
}
public void setPropertyValue( String name, String value )
{
params.setPropertyValue( name, value );
}
public void resetPropertyValues()
{
params.clear();
for( String name : params.getPropertyNames() )
{
params.getProperty( name ).setValue( params.getProperty( name ).getDefaultValue() );
}
}
public void propertyChange( PropertyChangeEvent evt )
{
if( evt.getPropertyName().equals( "path" ) )
{
notifyPropertyChanged( "path", null, getPath() );
}
else if( evt.getPropertyName().equals( "method" ) )
{
notifyPropertyChanged( "method", evt.getOldValue(), evt.getNewValue() );
}
}
public String[] getResponseMediaTypes()
{
StringList result = new StringList();
for( RestRepresentation representation : getRepresentations( Type.RESPONSE, null ) )
{
if( !result.contains( representation.getMediaType() ) )
result.add( representation.getMediaType() );
}
return result.toStringArray();
}
public boolean isPostQueryString()
{
return hasRequestBody() && getConfig().getPostQueryString();
}
public void setPostQueryString( boolean b )
{
boolean old = isPostQueryString();
getConfig().setPostQueryString( b );
notifyPropertyChanged( "postQueryString", old, b );
if( !"multipart/form-data".equals( getMediaType() ) )
{
setMediaType( b ? "application/x-www-form-urlencoded" : getMediaType() );
}
}
public final static class ParameterMessagePart extends MessagePart.ParameterPart
{
private String name;
public ParameterMessagePart( TestProperty propertyAt )
{
this.name = propertyAt.getName();
}
@Override
public SchemaType getSchemaType()
{
return XmlString.type;
}
@Override
public SchemaGlobalElement getPartElement()
{
return null;
}
@Override
public QName getPartElementName()
{
return new QName( getName() );
}
public String getDescription()
{
return null;
}
public String getName()
{
return name;
}
}
public String getPropertiesLabel()
{
return "Request Params";
}
public RestParamsPropertyHolder getParams()
{
return params;
}
public HttpAttachmentPart getAttachmentPart( String partName )
{
return null;
}
public HttpAttachmentPart[] getDefinedAttachmentParts()
{
return new HttpAttachmentPart[0];
}
public class RestContentPart extends ContentPart implements MessagePart
{
@Override
public SchemaGlobalElement getPartElement()
{
return null;
}
@Override
public QName getPartElementName()
{
return null;
}
@Override
public SchemaType getSchemaType()
{
return null;
}
public String getDescription()
{
return null;
}
public String getName()
{
return null;
}
public String getMediaType()
{
return getConfig().getMediaType();
}
}
public boolean hasRequestBody()
{
return getRestMethod().hasRequestBody();
}
public RestResource getResource()
{
return getOperation();
}
public String getPath()
{
if( !StringUtils.isNullOrEmpty( getConfig().getFullPath() ) || getResource() == null )
return getConfig().getFullPath();
else
return getResource().getFullPath();
}
public void setPath( String fullPath )
{
String old = getPath();
if( getResource() != null && getResource().getFullPath().equals( fullPath ) )
getConfig().unsetFullPath();
else
getConfig().setFullPath( fullPath );
notifyPropertyChanged( "path", old, fullPath );
}
public String getResponseContentAsXml()
{
HttpResponse response = getResponse();
if( response == null )
return null;
return response.getContentAsXml();
}
@Override
public void release()
{
super.release();
if( method != null )
method.removePropertyChangeListener( this );
params.removeTestPropertyListener( paramUpdater );
params.release();
}
public void updateConfig( RestRequestConfig request )
{
setConfig( request );
updateParams();
List<AttachmentConfig> attachmentConfigs = getConfig().getAttachmentList();
for( int i = 0; i < attachmentConfigs.size(); i++ )
{
AttachmentConfig config = attachmentConfigs.get( i );
getAttachmentsList().get( i ).updateConfig( config );
}
if( jmsHeaderConfig != null )
{
jmsHeaderConfig.setJMSHeaderConfConfig( request.getJmsConfig() );
}
if( jmsPropertyConfig != null )
{
jmsPropertyConfig.setJmsPropertyConfConfig( request.getJmsPropertyConfig() );
}
}
protected void updateParams()
{
StringToStringMap paramValues = StringToStringMap.fromXml( getConfig().getParameters() );
params.reset( getRestMethod().getOverlayParams(), paramValues );
paramUpdater.setValues( paramValues );
}
public boolean hasEndpoint()
{
return super.hasEndpoint() || PathUtils.isHttpPath( getPath() );
}
private class ParamUpdater implements TestPropertyListener
{
private StringToStringMap values;
public ParamUpdater( StringToStringMap paramValues )
{
values = paramValues;
}
public void setValues( StringToStringMap paramValues )
{
values = paramValues;
}
private void sync()
{
try
{
getConfig().setParameters( StringToStringMapConfig.Factory.parse( values.toXml() ) );
}
catch( XmlException e )
{
e.printStackTrace();
}
}
public void propertyAdded( String name )
{
sync();
}
public void propertyMoved( String name, int oldIndex, int newIndex )
{
sync();
}
public void propertyRemoved( String name )
{
sync();
}
public void propertyRenamed( String oldName, String newName )
{
sync();
}
public void propertyValueChanged( String name, String oldValue, String newValue )
{
sync();
}
}
public List<TestProperty> getPropertyList()
{
return params.getPropertyList();
}
protected void setRestMethod( RestMethod restMethod )
{
if( this.method != null )
this.method.removePropertyChangeListener( this );
this.method = restMethod;
if( method != null )
method.addPropertyChangeListener( this );
updateParams();
}
private JMSHeaderConfig jmsHeaderConfig;
private JMSPropertiesConfig jmsPropertyConfig;
public JMSHeaderConfig getJMSHeaderConfig()
{
if( jmsHeaderConfig == null )
{
if( !getConfig().isSetJmsConfig() )
{
getConfig().addNewJmsConfig();
}
jmsHeaderConfig = new JMSHeaderConfig( getConfig().getJmsConfig(), this );
}
return jmsHeaderConfig;
}
public JMSPropertiesConfig getJMSPropertiesConfig()
{
if( jmsPropertyConfig == null )
{
if( !getConfig().isSetJmsPropertyConfig() )
{
getConfig().addNewJmsPropertyConfig();
}
jmsPropertyConfig = new JMSPropertiesConfig( getConfig().getJmsPropertyConfig(), this );
}
return jmsPropertyConfig;
}
@Override
public String getMultiValueDelimiter()
{
return getConfig().getMultiValueDelimiter();
}
public void setMultiValueDelimiter( String delimiter )
{
String old = getMultiValueDelimiter();
getConfig().setMultiValueDelimiter( delimiter );
notifyPropertyChanged( "multiValueDelimiter", old, delimiter );
}
}