public function setAttribute(Project $project, $element, $attributeName, &$value)
    {

        // we want to check whether the value we are setting looks like
        // a slot-listener variable:  %{task.current_file}
        //
        // slot-listener variables are not like properties, in that they cannot be mixed with
        // other text values.  The reason for this disparity is that properties are only
        // set when first constructing objects from XML, whereas slot-listeners are always dynamic.
        //
        // This is made possible by PHP5 (objects automatically passed by reference) and PHP's loose
        // typing.

        if (StringHelper::isSlotVar($value)) {
            $as = "setlistening" . strtolower($attributeName);

            if (!isset($this->slotListeners[$as])) {
                $msg = $this->getElementName(
                    $project,
                    $element
                ) . " doesn't support a slot-listening '$attributeName' attribute.";
                throw new BuildException($msg);
            }

            $method = $this->slotListeners[$as];

            $key = StringHelper::slotVar($value);
            $value = Register::getSlot(
                $key
            ); // returns a RegisterSlot object which will hold current value of that register (accessible using getValue())
        } else {
            // Traditional value options

            $as = "set" . strtolower($attributeName);

            if (!isset($this->attributeSetters[$as])) {
                $msg = $this->getElementName($project, $element) . " doesn't support the '$attributeName' attribute.";
                throw new BuildException($msg);
            }

            $method = $this->attributeSetters[$as];

            if ($as == "setrefid") {
                $value = new Reference($project, $value);
            } else {
                // value is a string representation of a boolean type,
                // convert it to primitive
                if (StringHelper::isBoolean($value)) {
                    $value = StringHelper::booleanValue($value);
                }

                // does method expect a PhingFile object? if so, then
                // pass a project-relative file.
                $params = $method->getParameters();

                $classname = null;

                if (($hint = $params[0]->getClass()) !== null) {
                    $classname = $hint->getName();
                }

                // there should only be one param; we'll just assume ....
                if ($classname !== null) {
                    switch (strtolower($classname)) {
                        case "phingfile":
                            $value = $project->resolveFile($value);
                            break;
                        case "path":
                            $value = new Path($project, $value);
                            break;
                        case "reference":
                            $value = new Reference($project, $value);
                            break;
                        // any other object params we want to support should go here ...
                    }
                } // if hint !== null
            } // if not setrefid
        } // if is slot-listener

        try {
            $project->log(
                "    -calling setter " . $method->getDeclaringClass()->getName() . "::" . $method->getName() . "()",
                Project::MSG_DEBUG
            );
            $method->invoke($element, $value);
        } catch (Exception $exc) {
            throw new BuildException($exc->getMessage(), $exc);
        }
    }