/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.rest.support; import com.eviware.soapui.SoapUI; import com.eviware.soapui.config.RestParameterConfig; import com.eviware.soapui.config.RestParametersConfig; import com.eviware.soapui.impl.rest.RestMethod; import com.eviware.soapui.impl.rest.RestResource; import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader; import com.eviware.soapui.model.ModelItem; import com.eviware.soapui.model.propertyexpansion.PropertyExpansion; import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils; import com.eviware.soapui.model.testsuite.TestProperty; import com.eviware.soapui.model.testsuite.TestPropertyListener; import com.eviware.soapui.support.StringUtils; import org.apache.xmlbeans.SchemaType; import org.apache.xmlbeans.XmlBeans; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlString; import javax.xml.namespace.QName; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import static com.eviware.soapui.impl.rest.actions.support.NewRestResourceActionBase.ParamLocation; public class XmlBeansRestParamsTestPropertyHolder implements RestParamsPropertyHolder { public static final String PROPERTY_STYLE = "style"; public static final String PARAM_LOCATION = "paramLocation"; private RestParametersConfig config; private List<RestParamProperty> properties = new ArrayList<RestParamProperty>(); private Map<String, RestParamProperty> propertyMap = new HashMap<String, RestParamProperty>(); private Set<TestPropertyListener> listeners = new HashSet<TestPropertyListener>(); private final ModelItem modelItem; private ParamLocation defaultParamLocation; private Properties overrideProperties; private String propertiesLabel = "Test Properties"; public XmlBeansRestParamsTestPropertyHolder(ModelItem modelItem, RestParametersConfig config) { this(modelItem, config, getParamLocation(modelItem)); } public XmlBeansRestParamsTestPropertyHolder(ModelItem modelItem, RestParametersConfig config, ParamLocation defaultParamLocation) { this.modelItem = modelItem; this.config = config; this.defaultParamLocation = defaultParamLocation; for (RestParameterConfig propertyConfig : config.getParameterList()) { addProperty(propertyConfig, false); } removeProeprtiesWithEmptyName(config); //Backward compatibility. Parameter with empty name was allowed in 4.6.2 } private void removeProeprtiesWithEmptyName(RestParametersConfig config) { Iterator<RestParamProperty> propertyIterator = properties.iterator(); //since we are deleting while iterating while (propertyIterator.hasNext()) { RestParamProperty property = propertyIterator.next(); String propertyName = property.getName(); if (!StringUtils.hasContent(propertyName)) { int index = properties.indexOf(property); propertyMap.remove(propertyName.toUpperCase()); propertyIterator.remove(); firePropertyRemoved(propertyName); config.removeParameter(index); } } } protected XmlBeansRestParamProperty addProperty(RestParameterConfig propertyConfig, boolean notify) { XmlBeansRestParamProperty propertiesStepProperty = new XmlBeansRestParamProperty(propertyConfig, defaultParamLocation); properties.add(propertiesStepProperty); propertyMap.put(propertiesStepProperty.getName().toUpperCase(), propertiesStepProperty); if (notify) { firePropertyAdded(propertiesStepProperty.getName()); } return propertiesStepProperty; } private static ParamLocation getParamLocation(ModelItem modelItem1) { if (modelItem1 == null || modelItem1 instanceof RestResource) { return ParamLocation.RESOURCE; } else if (modelItem1 instanceof RestMethod) { return ParamLocation.METHOD; } return null; } private void firePropertyAdded(String name) { TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyAdded(name); } } private void firePropertyRemoved(String name) { TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyRemoved(name); } } private void firePropertyMoved(String name, int oldIndex, int newIndex) { TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyMoved(name, oldIndex, newIndex); } } private void firePropertyRenamed(String oldName, String newName) { TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyRenamed(oldName, newName); } } private void firePropertyValueChanged(String name, String oldValue, String newValue) { TestPropertyListener[] listenersArray = listeners.toArray(new TestPropertyListener[listeners.size()]); for (TestPropertyListener listener : listenersArray) { listener.propertyValueChanged(name, oldValue, newValue); } } public RestParamProperty addProperty(String name) { if (hasProperty(name)) { return getProperty(name); } RestParameterConfig propertyConfig = config.addNewParameter(); propertyConfig.setName(name); return addProperty(propertyConfig, true); } public void addTestPropertyListener(TestPropertyListener listener) { listeners.add(listener); } /* * (non-Javadoc) * * @see * com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder#getProperty * (java.lang.String) */ public RestParamProperty getProperty(String name) { return propertyMap.get(name.toUpperCase()); } public String[] getPropertyNames() { String[] result = new String[properties.size()]; for (int c = 0; c < properties.size(); c++) { result[c] = properties.get(c).getName(); } return result; } public String getPropertyValue(String name) { TestProperty property = getProperty(name); return property == null ? null : property.getValue(); } public RestParamProperty removeProperty(String propertyName) { RestParamProperty property = getProperty(propertyName); if (property != null) { int ix = properties.indexOf(property); propertyMap.remove(propertyName.toUpperCase()); properties.remove(ix); firePropertyRemoved(propertyName); config.removeParameter(ix); return property; } return null; } public void removeTestPropertyListener(TestPropertyListener listener) { listeners.remove(listener); } public void setPropertyValue(String name, String value) { RestParamProperty property = getProperty(name); if (property != null) { property.setValue(value); } else { addProperty(name).setValue(value); } } /* * (non-Javadoc) * * @see * com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder#resetValues * () */ public void resetValues() { for (RestParamProperty property : properties) { ((XmlBeansRestParamProperty) property).reset(); } } public void resetPropertiesConfig(RestParametersConfig config) { this.config = config; for (int c = 0; c < config.sizeOfParameterArray(); c++) { ((XmlBeansRestParamProperty) properties.get(c)).setConfig(config.getParameterArray(c)); } } public boolean renameProperty(String name, String newName) { if (getProperty(newName) != null) { return false; } RestParamProperty property = getProperty(name); if (property == null) { return false; } property.setName(newName); firePropertyRenamed(name, newName); return true; } /* * (non-Javadoc) * * @see * com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder#getPropertyIndex * (java.lang.String) */ public int getPropertyIndex(String name) { for (int c = 0; c < properties.size(); c++) { if (properties.get(c).getName().equals(name)) { return c; } } return -1; } public class XmlBeansRestParamProperty implements RestParamProperty { private RestParameterConfig propertyConfig; private PropertyChangeSupport propertySupport; private ParamLocation paramLocation; public XmlBeansRestParamProperty(RestParameterConfig propertyConfig, ParamLocation location) { this.propertyConfig = propertyConfig; this.paramLocation = location; propertySupport = new PropertyChangeSupport(this); } /* * (non-Javadoc) * * @seecom.eviware.soapui.impl.rest.support.RestParamProperty# * addPropertyChangeListener(java.beans.PropertyChangeListener) */ public void addPropertyChangeListener(PropertyChangeListener listener) { propertySupport.addPropertyChangeListener(listener); } /* * (non-Javadoc) * * @seecom.eviware.soapui.impl.rest.support.RestParamProperty# * addPropertyChangeListener(java.lang.String, * java.beans.PropertyChangeListener) */ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertySupport.addPropertyChangeListener(propertyName, listener); } /* * (non-Javadoc) * * @seecom.eviware.soapui.impl.rest.support.RestParamProperty# * removePropertyChangeListener(java.beans.PropertyChangeListener) */ public void removePropertyChangeListener(PropertyChangeListener listener) { propertySupport.removePropertyChangeListener(listener); } /* * (non-Javadoc) * * @seecom.eviware.soapui.impl.rest.support.RestParamProperty# * removePropertyChangeListener(java.lang.String, * java.beans.PropertyChangeListener) */ public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertySupport.removePropertyChangeListener(propertyName, listener); } public void setConfig(RestParameterConfig restParameterConfig) { this.propertyConfig = restParameterConfig; } public String getName() { return propertyConfig.getName(); } public void setName(String name) { String oldName = getName(); propertyConfig.setName(name); propertyMap.remove(oldName.toUpperCase()); propertyMap.put(name.toUpperCase(), this); firePropertyRenamed(oldName, name); } public String getDescription() { return propertyConfig.getDescription(); } public void setDescription(String description) { String old = getDescription(); propertyConfig.setDescription(description); propertySupport.firePropertyChange("description", old, description); } public ParamLocation getParamLocation() { return this.paramLocation; } public void setParamLocation(ParamLocation paramLocation) { if (this.paramLocation == paramLocation) { return; } ParamLocation old = this.paramLocation; this.paramLocation = paramLocation; propertySupport.firePropertyChange(PARAM_LOCATION, old, this.paramLocation); } public ParameterStyle getStyle() { if (propertyConfig.xgetStyle() == null) { propertyConfig.setStyle(RestParameterConfig.Style.QUERY); } return ParameterStyle.valueOf(propertyConfig.getStyle().toString()); } public void setStyle(ParameterStyle style) { ParameterStyle old = getStyle(); propertyConfig.setStyle(RestParameterConfig.Style.Enum.forString(style.name())); propertySupport.firePropertyChange(PROPERTY_STYLE, old, style); } public String getValue() { if (overrideProperties != null && overrideProperties.containsKey(getName())) { return overrideProperties.getProperty(getName()); } return propertyConfig.getValue() == null ? "" : propertyConfig.getValue(); } public void setValue(String value) { String oldValue = getValue(); propertyConfig.setValue(value); if (overrideProperties != null && overrideProperties.containsKey(getName())) { overrideProperties.remove(getName()); if (overrideProperties.isEmpty()) { overrideProperties = null; } } firePropertyValueChanged(getName(), oldValue, value); } public boolean isReadOnly() { return false; } public ModelItem getModelItem() { return modelItem; } public String getDefaultValue() { return propertyConfig.isSetDefault() ? propertyConfig.getDefault() : ""; } public String[] getOptions() { return propertyConfig.getOptionList().toArray(new String[propertyConfig.sizeOfOptionArray()]); } public boolean getRequired() { return propertyConfig.getRequired(); } /* * (non-Javadoc) * * @see * com.eviware.soapui.impl.rest.support.RestParamProperty#isDisableUrlEncoding * () */ public boolean isDisableUrlEncoding() { return propertyConfig.getDisableUrlEncoding(); } /* * (non-Javadoc) * * @seecom.eviware.soapui.impl.rest.support.RestParamProperty# * setDisableUrlEncoding(boolean) */ public void setDisableUrlEncoding(boolean encode) { boolean old = isDisableUrlEncoding(); if (old == encode) { return; } propertyConfig.setDisableUrlEncoding(encode); propertySupport.firePropertyChange("disableUrlEncoding", old, encode); } public QName getType() { return propertyConfig.isSetType() ? propertyConfig.getType() : XmlString.type.getName(); } public void setOptions(String[] arg0) { String[] old = getOptions(); propertyConfig.setOptionArray(arg0); propertySupport.firePropertyChange("options", old, arg0); } public void setRequired(boolean arg0) { boolean old = getRequired(); if (old == arg0) { return; } propertyConfig.setRequired(arg0); propertySupport.firePropertyChange("required", old, arg0); } public void setType(QName arg0) { QName old = getType(); if (old.equals(arg0)) { return; } propertyConfig.setType(arg0); propertySupport.firePropertyChange("type", old, arg0); } public void setDefaultValue(String default1) { String old = default1; propertyConfig.setDefault(default1); propertySupport.firePropertyChange("defaultValue", old, default1); } public RestParameterConfig getConfig() { return propertyConfig; } @Override public boolean equals(Object obj) { if (obj instanceof XmlBeansRestParamProperty) { return propertyConfig.toString().equals(((XmlBeansRestParamProperty) obj).propertyConfig.toString()); } return super.equals(obj); } public void reset() { setValue(getDefaultValue()); } @Override public String getPath() { return propertyConfig.getPath(); } @Override public void setPath(String path) { String old = getPath(); propertyConfig.setPath(path); propertySupport.firePropertyChange("path", old, path); } @Override public boolean isRequestPart() { return false; } @Override public SchemaType getSchemaType() { return XmlBeans.getBuiltinTypeSystem().findType(getType()); } } /* * (non-Javadoc) * * @see * com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder#saveTo(java * .util.Properties) */ public void saveTo(Properties props) { for (RestParamProperty p : properties) { String name = p.getName(); String value = p.getValue(); if (value == null) { value = ""; } props.setProperty(name, value); } } public int getPropertyCount() { return properties.size(); } /* * (non-Javadoc) * * @see * com.eviware.soapui.impl.rest.support.RestParamsPropertyHolder#getPropertyAt * (int) */ public RestParamProperty getPropertyAt(int index) { return properties.get(index); } public List<TestProperty> getPropertyList() { List<TestProperty> result = new ArrayList<TestProperty>(); for (TestProperty property : properties) { result.add(property); } return result; } public Map<String, TestProperty> getProperties() { Map<String, TestProperty> result = new HashMap<String, TestProperty>(); for (RestParamProperty property : propertyMap.values()) { result.put(property.getName(), property); } return result; } public boolean hasProperty(String name) { return propertyMap.containsKey(name.toUpperCase()); } public int addPropertiesFromFile(String propFile) { if (!StringUtils.hasContent(propFile)) { return 0; } try { InputStream input = null; File file = new File(propFile); if (file.exists()) { input = new FileInputStream(file); } else if (propFile.toLowerCase().startsWith("http://") || propFile.toLowerCase().startsWith("https://")) { UrlWsdlLoader loader = new UrlWsdlLoader(propFile, getModelItem()); loader.setUseWorker(false); input = loader.load(); } if (input != null) { if (overrideProperties == null) { overrideProperties = new Properties(); } int sz = overrideProperties.size(); overrideProperties.load(input); for (Object key : overrideProperties.keySet()) { String name = key.toString(); if (!hasProperty(name)) { addProperty(name); } } return overrideProperties.size() - sz; } } catch (Exception e) { SoapUI.logError(e); } return 0; } public ModelItem getModelItem() { return modelItem; } /* * (non-Javadoc) * * @seecom.eviware.soapui.impl.rest.support.RestParamsPropertyHolder# * getPropertyExpansions() */ public PropertyExpansion[] getPropertyExpansions() { List<PropertyExpansion> result = new ArrayList<PropertyExpansion>(); for (RestParamProperty prop : properties) { result.addAll(PropertyExpansionUtils.extractPropertyExpansions(getModelItem(), prop, "value")); } return result.toArray(new PropertyExpansion[result.size()]); } public void moveProperty(String propertyName, int targetIndex) { RestParamProperty property = getProperty(propertyName); int ix = properties.indexOf(property); if (ix == targetIndex) { return; } if (targetIndex < 0) { targetIndex = 0; } String value = property.getValue(); String defaultValue = property.getDefaultValue(); String style = property.getStyle().name(); String[] options = property.getOptions(); boolean required = property.getRequired(); QName type = property.getType(); String description = property.getDescription(); boolean disableUrlEncoding = property.isDisableUrlEncoding(); config.removeParameter(ix); RestParameterConfig propertyConfig; if (targetIndex < properties.size()) { properties.add(targetIndex, properties.remove(ix)); propertyConfig = config.insertNewParameter(targetIndex); } else { properties.add(properties.remove(ix)); propertyConfig = config.addNewParameter(); } propertyConfig.setName(propertyName); propertyConfig.setValue(value); propertyConfig.setDefault(defaultValue); propertyConfig.setStyle(RestParameterConfig.Style.Enum.forString(style)); propertyConfig.setOptionArray(options); propertyConfig.setRequired(required); propertyConfig.setType(type); propertyConfig.setDescription(description); propertyConfig.setDisableUrlEncoding(disableUrlEncoding); resetPropertiesConfig(config); if (targetIndex > properties.size()) { targetIndex = properties.size(); } firePropertyMoved(propertyName, ix, targetIndex); } public void clear() { while (size() > 0) { removeProperty(getPropertyAt(0).getName()); } } public boolean containsKey(Object key) { return hasProperty((String) key); } public boolean containsValue(Object value) { return propertyMap.containsValue(value); } public Set<java.util.Map.Entry<String, TestProperty>> entrySet() { HashSet<java.util.Map.Entry<String, TestProperty>> result = new HashSet<Entry<String, TestProperty>>(); for (TestProperty p : propertyMap.values()) { // This does not compile on JDK 1.5: // result.add( new java.util.HashMap.SimpleEntry<String, // TestProperty>(p.getName(), p)); result.add(new HashMapEntry<String, TestProperty>(p.getName(), p)); } return result; } private static class HashMapEntry<K, V> implements java.util.Map.Entry<K, V> { private K key; private V value; public HashMapEntry(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { throw new UnsupportedOperationException(); } } public RestParamProperty get(Object key) { return getProperty((String) key); } public boolean isEmpty() { return propertyMap.isEmpty(); } public Set<String> keySet() { return new LinkedHashSet<String>(Arrays.asList(getPropertyNames())); } public TestProperty put(String key, TestProperty value) { TestProperty result = addProperty(key); result.setValue(value.getValue()); return result; } public void putAll(Map<? extends String, ? extends TestProperty> m) { for (TestProperty p : m.values()) { addProperty(p.getName()).setValue(p.getValue()); } } public TestProperty remove(Object key) { return removeProperty((String) key); } public int size() { return propertyMap.size(); } public Collection<TestProperty> values() { ArrayList<TestProperty> result = new ArrayList<TestProperty>(); result.addAll(properties); return result; } public String getPropertiesLabel() { return propertiesLabel; } public void setPropertiesLabel(String propertiesLabel) { this.propertiesLabel = propertiesLabel; } public XmlObject getConfig() { return config; } public void addParameters(RestParamsPropertyHolder params) { for (int c = 0; c < params.getPropertyCount(); c++) { RestParamProperty property = params.getPropertyAt(c); if (!hasProperty(property.getName())) { addParameter(property); } } } public void addParameter(RestParamProperty property) { RestParamProperty prop = addProperty(property.getName()); prop.setStyle(property.getStyle()); prop.setValue(property.getValue()); prop.setType(property.getType()); prop.setDefaultValue(property.getDefaultValue()); prop.setDescription(property.getDescription()); prop.setOptions(property.getOptions()); prop.setPath(property.getPath()); prop.setRequired(property.getRequired()); } @Override public void setParameterLocation(RestParamProperty parameter, ParamLocation newLocation) { // defensive programming, since parameter may be a disconnected XmlObject getProperty(parameter.getName()).setParamLocation(newLocation); } public void release() { } public RestParamProperty addProperty(XmlBeansRestParamProperty prop) { RestParameterConfig propertyConfig = (RestParameterConfig) config.addNewParameter().set(prop.getConfig()); return addProperty(propertyConfig, true); } }