Package com.canoo.webtest.ant

Source Code of com.canoo.webtest.ant.WebtestPropertyHelper

package com.canoo.webtest.ant;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.PropertyHelper;

import com.canoo.webtest.engine.Context;
import com.canoo.webtest.extension.ScriptStep;

/**
* Helper class for working with Ant and WebTest dynamic properties.<p>
*
* This property helper is registered at the start of a WebTest and used by ant to evaluate
* properties when configuring tasks.<br/>
* It is able to evaluate traditional Ant properties like ${my.property} as well as
* WebTest dynamic properties like #{my.dynamic.property}.<br/>
* It will notify build listeners implementing {@link IPropertyExpansionListener} of the property expansion.
* @author Marc Guillemot
*/
public class WebtestPropertyHelper extends PropertyHelper
{
    private static final Logger LOG = Logger.getLogger(WebtestPropertyHelper.class);
  private final PropertyHelper fWrappedHelper;
  private Project fProject;
 
  /**
   * Wrapps the property helper defined for the project.
   * @param project the project containing the original helper to decorate
   */
  public WebtestPropertyHelper(final Project project)
  {
    fWrappedHelper = PropertyHelper.getPropertyHelper(project);
    setProject(project);
  }
 
  /**
   * Define a new property helper for the project
   * @param propertyHelper the new helper
   */
  protected static void definePropertyHelper(final Project project, final PropertyHelper propertyHelper) {
    // first remove reference to avoid Warning message
    project.getReferences().remove("ant.PropertyHelper");
    project.addReference("ant.PropertyHelper", propertyHelper);
  }


  /**
   * Configures the special WebTest property helper for the current project
   * @param project the project which property helper should be wrapped
   */
  public static void configureWebtestPropertyHelper(final Project project) {
    final WebtestPropertyHelper propertyHelper = new WebtestPropertyHelper(project);
    propertyHelper.setProject(project);
      definePropertyHelper(project, propertyHelper);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#copyInheritedProperties(org.apache.tools.ant.Project)
   */
  public void copyInheritedProperties(final Project other)
  {
    fWrappedHelper.copyInheritedProperties(other);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#copyUserProperties(org.apache.tools.ant.Project)
   */
  public void copyUserProperties(final Project other)
  {
    fWrappedHelper.copyUserProperties(other);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#getNext()
   */
  public PropertyHelper getNext()
  {
    return fWrappedHelper.getNext();
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#getProperties()
   */
  public Hashtable getProperties()
  {
    return fWrappedHelper.getProperties();
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#getProperty(java.lang.String, java.lang.String)
   */
  public Object getProperty(final String ns, final String name)
  {
    return fWrappedHelper.getProperty(ns, name);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#getPropertyHook(java.lang.String, java.lang.String, boolean)
   */
  public Object getPropertyHook(final String ns, final String name, final boolean user)
  {
    return fWrappedHelper.getPropertyHook(ns, name, user);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#getUserProperties()
   */
  public Hashtable getUserProperties()
  {
    return fWrappedHelper.getUserProperties();
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#getUserProperty(java.lang.String, java.lang.String)
   */
  public Object getUserProperty(final String ns, final String name)
  {
    return fWrappedHelper.getUserProperty(ns, name);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#parsePropertyString(java.lang.String, java.util.Vector, java.util.Vector)
   */
  public void parsePropertyString(final String value, final Vector fragments, final Vector propertyRefs) throws BuildException
  {
    fWrappedHelper.parsePropertyString(value, fragments, propertyRefs);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#setInheritedProperty(java.lang.String, java.lang.String, java.lang.Object)
   */
  public void setInheritedProperty(final String ns, final String name, final Object value)
  {
    fWrappedHelper.setInheritedProperty(ns, name, value);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#setNewProperty(java.lang.String, java.lang.String, java.lang.Object)
   */
  public void setNewProperty(final String ns, final String name, final Object value)
  {
    fWrappedHelper.setNewProperty(ns, name, value);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#setNext(org.apache.tools.ant.PropertyHelper)
   */
  public void setNext(final PropertyHelper next)
  {
    fWrappedHelper.setNext(next);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#setProject(org.apache.tools.ant.Project)
   */
  public void setProject(final Project p)
  {
    fProject = p;
    super.setProject(p);
    fWrappedHelper.setProject(p);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#setProperty(java.lang.String, java.lang.String, java.lang.Object, boolean)
   */
  public boolean setProperty(final String ns, final String name, final Object value, final boolean verbose)
  {
    return fWrappedHelper.setProperty(ns, name, value, verbose);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#setPropertyHook(java.lang.String, java.lang.String, java.lang.Object, boolean, boolean, boolean)
   */
  public boolean setPropertyHook(final String ns, final String name, final Object value, final boolean inherited, final boolean user, final boolean isNew)
  {
    return fWrappedHelper.setPropertyHook(ns, name, value, inherited, user, isNew);
  }

  /**
   * @see org.apache.tools.ant.PropertyHelper#setUserProperty(java.lang.String, java.lang.String, java.lang.Object)
   */
  public void setUserProperty(final String ns, final String name, final Object value)
  {
    fWrappedHelper.setUserProperty(ns, name, value);
  }

  /**
   * Handles ${my.property} as well as WebTest dynamic properties like #{my.dynamic.property}
   * @see org.apache.tools.ant.PropertyHelper#replaceProperties(java.lang.String, java.lang.String, java.util.Hashtable)
   */
  public String replaceProperties(final String ns, final String value, final Hashtable keys) throws BuildException
  {
    if (value == null)
      return null;
    final String str = replacePropertiesInternal(ns, value, keys);

    // the evaluated properties need to be written in the report
    // perhaps would it be better to notify the StepExecutionListener directly?
    // in a first time without hard coupling
    if (!str.equals(value))
    {
      LOG.debug("Notifying listeners of properties expansion: " + value + " -> " + str);
        for (final Iterator iter=fProject.getBuildListeners().iterator(); iter.hasNext();)
        {
          final BuildListener listener = (BuildListener) iter.next();
          if (listener instanceof IPropertyExpansionListener)
          {
            ((IPropertyExpansionListener) listener).propertiesExpanded(value, str);
          }
        }
     
    }
    return str;
  }

  private String replacePropertiesInternal(final String ns, final String value, final Hashtable keys) {
    final int length = value.length();
    if (length < 4)
      return value;
   
    int posStart = value.indexOf('{', 1);
    while (posStart != -1)
    {
      final char prec = value.charAt(posStart - 1);
      if (prec == '$' || prec == '#')
      {
        int posClosing = getMatchingClosing(value, posStart);
        if (posClosing != -1)
        {
          final String propertyContent = value.substring(posStart+1, posClosing);
          final String expandedContent = replacePropertiesInternal(ns, propertyContent, keys);
          final String replacement;
          if (prec == '#')
          {
            final String propValue = getDynamicPropertyValue(expandedContent);
            if (propValue == null)
            {
              replacement = "#{" + expandedContent + "}";
            }
            else
            {
              replacement = propValue;
            }
          }
          else // $
          {
            replacement = super.replaceProperties(ns, "${" + expandedContent + "}", keys);
          }
          return value.substring(0, posStart -1)
            + replacement + replacePropertiesInternal(ns, value.substring(posClosing+1), keys);
        }
      }
     
      posStart = value.indexOf('{', posStart+1);
    }
   
    return value;
  }

  /**
   * Gets the first unmatched "}" from the start position
   * @param value the string to look in
   * @param posStart the position of the opening { to match
   * @return -1 if none found
   */
  private int getMatchingClosing(final String value, int posStart) {
    final int length = value.length();
    int i = posStart + 1;
    int opened = 0;
    while (i < length)
    {
      final char c = value.charAt(i);
      if (c == '}')
      {
        if (opened == 0)
          return i;
        opened--;
      }
      else if (c == '{')
        opened++;
      ++i;
    }
    return -1;
  }

  private String getDynamicPropertyValue(final String propName) {
    if (propName.startsWith("script:"))
    {
        final Context context = WebtestTask.getThreadContext();
          if (context == null || context.getRunner() == null) {
              return null;
          }
      final String expr = StringUtils.substringAfter(propName, "script:");
      return ScriptStep.evalScriptExpression(context, expr, null);
    }
    else
      return (String) getDynamicProperties().get(propName);
  }

  /**
   * Gets the dynamic properties map for the current webtest
   * @return the map of properties
   */
  Map getDynamicProperties() {
    return WebtestTask.getThreadContext().getWebtest().getDynamicProperties();
  }

    /**
     * This method handles the replacement of dynamic properties in a given String.
     * It checks if any of the currently existing property names occur in the string.
     * If a match is detected, it is replaced by its value. If the value is
     * <code>null</code>, it is replaced by an empty string. The search looks for
     * textual matches of the property name using an ant-like notation, i.e.
     * in the form of "#{xxx}".
     *
     * @param properties the properties
     * @param text The string to expand
     * @deprecated Use @link Project#replaceProperties(msg)} instead
     */
    public static String expandDynamicProperties(final Map properties, final String text) {
      if (StringUtils.isEmpty(text)) {
            return text;
        }
        String result = text;
        for (final Iterator i = properties.entrySet().iterator(); i.hasNext();) {
            final Map.Entry currentProperty = (Map.Entry) i.next();
            final String propName = "#{" + currentProperty.getKey() + "}";

            for (int index = result.indexOf(propName); index >= 0;) {
                final String propValue = String.valueOf(currentProperty.getValue());
                final StringBuffer newResult = new StringBuffer(result.substring(0, index));
                newResult.append(propValue);
                newResult.append(result.substring(index + propName.length(), result.length()));
                result = newResult.toString();
                index = result.indexOf(propName, index + propValue.length());
            }
        }
        return result;
    }
}
TOP

Related Classes of com.canoo.webtest.ant.WebtestPropertyHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.