+
+
+
diff --git a/src/etc/checkstyle/checkstyle-config b/src/etc/checkstyle/checkstyle-config
index 877fb9077..160b098d3 100644
--- a/src/etc/checkstyle/checkstyle-config
+++ b/src/etc/checkstyle/checkstyle-config
@@ -96,8 +96,8 @@
-
-
+
+
diff --git a/src/main/org/apache/tools/ant/ComponentHelper.java b/src/main/org/apache/tools/ant/ComponentHelper.java
index c5823d1b8..44b7daa3c 100644
--- a/src/main/org/apache/tools/ant/ComponentHelper.java
+++ b/src/main/org/apache/tools/ant/ComponentHelper.java
@@ -316,6 +316,7 @@ public class ComponentHelper {
public void initDefaultDefinitions() {
initTasks();
initTypes();
+ new DefaultDefinitions(this).execute();
}
/**
diff --git a/src/main/org/apache/tools/ant/DefaultDefinitions.java b/src/main/org/apache/tools/ant/DefaultDefinitions.java
new file mode 100644
index 000000000..0de0e1a27
--- /dev/null
+++ b/src/main/org/apache/tools/ant/DefaultDefinitions.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant;
+
+/**
+ * Default definitions.
+ */
+public final class DefaultDefinitions {
+ private static final String IF_NAMESPACE = "ant:if";
+ private static final String UNLESS_NAMESPACE = "ant:unless";
+ private static final String OATA = "org.apache.tools.ant.";
+
+ private final ComponentHelper componentHelper;
+
+ /**
+ * Create a default definitions object.
+ * @param componentHelper the componenthelper to initialize.
+ */
+ public DefaultDefinitions(ComponentHelper componentHelper) {
+ this.componentHelper = componentHelper;
+ }
+
+ /**
+ * Register the defintions.
+ */
+ public void execute() {
+ attributeNamespaceDef(IF_NAMESPACE);
+ attributeNamespaceDef(UNLESS_NAMESPACE);
+
+ ifUnlessDef("true", "IfTrueAttribute");
+ ifUnlessDef("set", "IfSetAttribute");
+ ifUnlessDef("blank", "IfBlankAttribute");
+ }
+
+ private void attributeNamespaceDef(String ns) {
+ AntTypeDefinition def = new AntTypeDefinition();
+ def.setName(ProjectHelper.nsToComponentName(ns));
+ def.setClassName(OATA + "attribute.AttributeNamespace");
+ def.setClassLoader(getClass().getClassLoader());
+ def.setRestrict(true);
+ componentHelper.addDataTypeDefinition(def);
+ }
+
+ private void ifUnlessDef(String name, String base) {
+ String classname = OATA + "attribute." + base;
+ componentDef(IF_NAMESPACE, name, classname);
+ componentDef(UNLESS_NAMESPACE, name, classname + "$Unless");
+ }
+
+ private void componentDef(String ns, String name, String classname) {
+ AntTypeDefinition def = new AntTypeDefinition();
+ String n = ProjectHelper.genComponentName(ns, name);
+ def.setName(ProjectHelper.genComponentName(ns, name));
+ def.setClassName(classname);
+ def.setClassLoader(getClass().getClassLoader());
+ def.setRestrict(true);
+ componentHelper.addDataTypeDefinition(def);
+ }
+}
diff --git a/src/main/org/apache/tools/ant/MagicNames.java b/src/main/org/apache/tools/ant/MagicNames.java
index 9d021c848..2871269cd 100644
--- a/src/main/org/apache/tools/ant/MagicNames.java
+++ b/src/main/org/apache/tools/ant/MagicNames.java
@@ -276,5 +276,9 @@ public final class MagicNames {
* @since Ant 1.9.0
*/
public static final String ANT_VM_LAUNCHER_REF_ID = "ant.vmLauncher";
+ /** Name of the namespace "type" (note: cannot be used as an element)
+ * @since Ant 1.9.1
+ * */
+ public static final String ATTRIBUTE_NAMESPACE = "attribute namespace";
}
diff --git a/src/main/org/apache/tools/ant/ProjectHelper.java b/src/main/org/apache/tools/ant/ProjectHelper.java
index a3a88b889..b9df28cae 100644
--- a/src/main/org/apache/tools/ant/ProjectHelper.java
+++ b/src/main/org/apache/tools/ant/ProjectHelper.java
@@ -43,6 +43,11 @@ public class ProjectHelper {
/** The URI for antlib current definitions */
public static final String ANT_CURRENT_URI = "ant:current";
+ /** The URI for ant specific attributes
+ * @since Ant 1.9.1
+ * */
+ public static final String ANT_ATTRIBUTE_URI = "ant:attribute";
+
/** The URI for defined types/tasks - the format is antlib: */
public static final String ANTLIB_URI = "antlib:";
@@ -522,6 +527,16 @@ public class ProjectHelper {
return componentName.substring(index + 1);
}
+ /**
+ * Convert an attribute namespace to a "component name".
+ * @param ns the xml namespace uri.
+ * @return the converted value.
+ * @since Ant 1.9.1
+ */
+ public static String nsToComponentName(String ns) {
+ return "attribute namespace:" + ns;
+ }
+
/**
* Add location to build exception.
* @param ex the build exception, if the build exception
diff --git a/src/main/org/apache/tools/ant/RuntimeConfigurable.java b/src/main/org/apache/tools/ant/RuntimeConfigurable.java
index f8fb44b36..44e32edc2 100644
--- a/src/main/org/apache/tools/ant/RuntimeConfigurable.java
+++ b/src/main/org/apache/tools/ant/RuntimeConfigurable.java
@@ -27,6 +27,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
+import org.apache.tools.ant.attribute.EnableAttribute;
+
import org.apache.tools.ant.util.CollectionUtils;
import org.apache.tools.ant.taskdefs.MacroDef.Attribute;
import org.apache.tools.ant.taskdefs.MacroInstance;
@@ -64,6 +66,9 @@ public class RuntimeConfigurable implements Serializable {
*/
private transient AttributeList attributes;
+ // The following is set to true if any of the attributes are namespaced
+ private transient boolean namespacedAttribute = false;
+
/** Attribute names and values. While the XML spec doesn't require
* preserving the order ( AFAIK ), some ant tests do rely on the
* exact order.
@@ -113,6 +118,73 @@ public class RuntimeConfigurable implements Serializable {
proxyConfigured = false;
}
+ private static class EnableAttributeConsumer {
+ public void add(EnableAttribute b) {
+ // Ignore
+ }
+ }
+
+ /**
+ * Check if an UE is enabled.
+ * This looks tru the attributes and checks if there
+ * are any Ant attributes, and if so, the method calls the
+ * isEnabled() method on them.
+ * @param owner the UE that owns this RC.
+ * @return true if enabled, false if any of the ant attribures return
+ * false.
+ */
+ public boolean isEnabled(UnknownElement owner) {
+ if (!namespacedAttribute) {
+ return true;
+ }
+ ComponentHelper componentHelper = ComponentHelper
+ .getComponentHelper(owner.getProject());
+
+ IntrospectionHelper ih
+ = IntrospectionHelper.getHelper(
+ owner.getProject(), EnableAttributeConsumer.class);
+ for (int i = 0; i < attributeMap.keySet().size(); ++i) {
+ String name = (String) attributeMap.keySet().toArray()[i];
+ if (name.indexOf(':') == -1) {
+ continue;
+ }
+ String componentName = attrToComponent(name);
+ String ns = ProjectHelper.extractUriFromComponentName(componentName);
+ if (componentHelper.getRestrictedDefinitions(
+ ProjectHelper.nsToComponentName(ns)) == null) {
+ continue;
+ }
+
+ String value = (String) attributeMap.get(name);
+
+ EnableAttribute enable = null;
+ try {
+ enable = (EnableAttribute)
+ ih.createElement(
+ owner.getProject(), new EnableAttributeConsumer(),
+ componentName);
+ } catch (BuildException ex) {
+ throw new BuildException(
+ "Unsupported attribute " + componentName);
+ }
+ if (enable == null) {
+ continue;
+ }
+ value = owner.getProject().replaceProperties(value); // FixMe: need to make config
+ if (!enable.isEnabled(owner, value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private String attrToComponent(String a) {
+ // need to remove the prefix
+ int p1 = a.lastIndexOf(':');
+ int p2 = a.lastIndexOf(':', p1 - 1);
+ return a.substring(0, p2) + a.substring(p1);
+ }
+
/**
* Sets the creator of the element to be configured
* used to store the element in the parent.
@@ -177,6 +249,9 @@ public class RuntimeConfigurable implements Serializable {
* @param value the attribute's value.
*/
public synchronized void setAttribute(String name, String value) {
+ if (name.indexOf(':') != -1) {
+ namespacedAttribute = true;
+ }
setAttribute(name, (Object) value);
}
diff --git a/src/main/org/apache/tools/ant/UnknownElement.java b/src/main/org/apache/tools/ant/UnknownElement.java
index c3df2e29f..fd919ab66 100644
--- a/src/main/org/apache/tools/ant/UnknownElement.java
+++ b/src/main/org/apache/tools/ant/UnknownElement.java
@@ -170,6 +170,9 @@ public class UnknownElement extends Task {
*
*/
public void configure(Object realObject) {
+ if (realObject == null) {
+ return;
+ }
realThing = realObject;
getWrapper().setProxy(realThing);
@@ -281,10 +284,8 @@ public class UnknownElement extends Task {
*/
public void execute() {
if (realThing == null) {
- // plain impossible to get here, maybeConfigure should
- // have thrown an exception.
- throw new BuildException("Could not create task of type: "
- + elementName, getLocation());
+ // Got here if the runtimeconfigurable is not enabled.
+ return;
}
try {
if (realThing instanceof Task) {
@@ -346,6 +347,14 @@ public class UnknownElement extends Task {
RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
UnknownElement child = it.next();
try {
+ if (!childWrapper.isEnabled(child)) {
+ if (ih.supportsNestedElement(
+ parentUri, ProjectHelper.genComponentName(
+ child.getNamespace(), child.getTag()))) {
+ continue;
+ }
+ // fall tru and fail in handlechild (unsupported element)
+ }
if (!handleChild(
parentUri, ih, parent, child, childWrapper)) {
if (!(parent instanceof TaskContainer)) {
@@ -411,6 +420,9 @@ public class UnknownElement extends Task {
* @return the task or data type represented by the given unknown element.
*/
protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) {
+ if (!w.isEnabled(ue)) {
+ return null;
+ }
ComponentHelper helper = ComponentHelper.getComponentHelper(
getProject());
String name = ue.getComponentName();
diff --git a/src/main/org/apache/tools/ant/attribute/AttributeNamespace.java b/src/main/org/apache/tools/ant/attribute/AttributeNamespace.java
new file mode 100644
index 000000000..60cb62aca
--- /dev/null
+++ b/src/main/org/apache/tools/ant/attribute/AttributeNamespace.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.attribute;
+
+/**
+ * This class is used to indicate that the xml namespace (uri)
+ * can be used to look for namespace attributes.
+ */
+public final class AttributeNamespace {
+}
diff --git a/src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java b/src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java
new file mode 100644
index 000000000..df119bf73
--- /dev/null
+++ b/src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.attribute;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.tools.ant.ProjectComponent;
+import org.apache.tools.ant.RuntimeConfigurable;
+import org.apache.tools.ant.UnknownElement;
+
+
+/**
+ * An abstract class for if/unless attributes.
+ * This contains a boolean flag to specify whether this is an
+ * if or unless attribute.
+ */
+public abstract class BaseIfAttribute
+ extends ProjectComponent implements EnableAttribute {
+ private boolean positive = true;
+ /**
+ * Set the positive flag.
+ * @param positive the value to use.
+ */
+ protected void setPositive(boolean positive) {
+ this.positive = positive;
+ }
+
+ /**
+ * Get the positive flag.
+ * @return the flag.
+ */
+ protected boolean isPositive() {
+ return positive;
+ }
+
+ /**
+ * convert the result.
+ * @param val the result to convert
+ * @return val if positive or !val if not.
+ */
+ protected boolean convertResult(boolean val) {
+ return positive ? val : !val;
+ }
+
+ /**
+ * Get all the attributes in the ant-attribute:param
+ * namespace and place them in a map.
+ * @param el the element this attribute is in.
+ * @return a map of attributes.
+ */
+ protected Map getParams(UnknownElement el) {
+ Map ret = new HashMap();
+ RuntimeConfigurable rc = el.getWrapper();
+ Map attributes = rc.getAttributeMap(); // This does a copy!
+ for (Iterator i = attributes.entrySet().iterator(); i.hasNext();) {
+ Map.Entry entry = (Map.Entry) i.next();
+ String key = (String) entry.getKey();
+ String value = (String) entry.getValue();
+ if (key.startsWith("ant-attribute:param")) {
+ int pos = key.lastIndexOf(':');
+ ret.put(key.substring(pos + 1),
+ el.getProject().replaceProperties(value));
+ }
+ }
+ return ret;
+ }
+}
diff --git a/src/main/org/apache/tools/ant/attribute/EnableAttribute.java b/src/main/org/apache/tools/ant/attribute/EnableAttribute.java
new file mode 100644
index 000000000..d2f67fcb4
--- /dev/null
+++ b/src/main/org/apache/tools/ant/attribute/EnableAttribute.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.attribute;
+
+import org.apache.tools.ant.UnknownElement;
+
+/**
+ * This interface is used by ant attributes.
+ */
+public interface EnableAttribute {
+ /**
+ * is enabled.
+ * @param el the unknown element this attribute is in.
+ * @param value the value of the attribute.
+ * @return true if the attribute enables the element, false otherwise.
+ */
+ boolean isEnabled(UnknownElement el, String value);
+}
diff --git a/src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java b/src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java
new file mode 100644
index 000000000..d0ff19c5a
--- /dev/null
+++ b/src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.attribute;
+
+import org.apache.tools.ant.UnknownElement;
+
+/**
+ * Check if an attribute is blank or not.
+ */
+public class IfBlankAttribute extends BaseIfAttribute {
+ /** The unless version */
+ public static class Unless extends IfBlankAttribute {
+ { setPositive(false); }
+ }
+ /**
+ * check if the attribute value is blank or not
+ * {@inheritDoc}
+ */
+ public boolean isEnabled(UnknownElement el, String value) {
+ return convertResult((value == null || "".equals(value)));
+ }
+}
diff --git a/src/main/org/apache/tools/ant/attribute/IfSetAttribute.java b/src/main/org/apache/tools/ant/attribute/IfSetAttribute.java
new file mode 100644
index 000000000..3502793a0
--- /dev/null
+++ b/src/main/org/apache/tools/ant/attribute/IfSetAttribute.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.attribute;
+
+import org.apache.tools.ant.UnknownElement;
+
+/**
+ * Check if an attribute value as a property is set or not
+ */
+public class IfSetAttribute extends BaseIfAttribute {
+ /** The unless version */
+ public static class Unless extends IfSetAttribute {
+ { setPositive(false); }
+ }
+ /**
+ * check if the attribute value is blank or not
+ * {@inheritDoc}
+ */
+ public boolean isEnabled(UnknownElement el, String value) {
+ return convertResult(getProject().getProperty(value) != null);
+ }
+}
diff --git a/src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java b/src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java
new file mode 100644
index 000000000..43bc8944c
--- /dev/null
+++ b/src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.attribute;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.UnknownElement;
+
+/**
+ * Check if an attribute value is true or not.
+ */
+public class IfTrueAttribute extends BaseIfAttribute {
+ /** The unless version */
+ public static class Unless extends IfTrueAttribute {
+ { setPositive(false); }
+ }
+
+ /**
+ * check if the attribute value is true or not
+ * {@inheritDoc}
+ */
+ public boolean isEnabled(UnknownElement el, String value) {
+ return convertResult(Project.toBoolean(value));
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java b/src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java
new file mode 100644
index 000000000..ce49d412f
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.taskdefs;
+
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.ComponentHelper;
+import org.apache.tools.ant.AntTypeDefinition;
+import org.apache.tools.ant.attribute.AttributeNamespace;
+
+/**
+ * Defintion to allow the uri to be considered for
+ * ant attributes.
+ *
+ * @since Ant 1.8.0
+ */
+public final class AttributeNamespaceDef extends AntlibDefinition {
+
+ /**
+ * Run the definition.
+ * This registers the xml namespace (uri) as a namepace for
+ * attributes.
+ */
+ public void execute() {
+ String componentName = ProjectHelper.nsToComponentName(
+ getURI());
+ AntTypeDefinition def = new AntTypeDefinition();
+ def.setName(componentName);
+ def.setClassName(AttributeNamespace.class.getName());
+ def.setClass(AttributeNamespace.class);
+ def.setRestrict(true);
+ def.setClassLoader(AttributeNamespace.class.getClassLoader());
+ ComponentHelper.getComponentHelper(getProject())
+ .addDataTypeDefinition(def);
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
index 54c03ea19..9cf1499fe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties
+++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
@@ -20,6 +20,7 @@ antstructure=org.apache.tools.ant.taskdefs.AntStructure
antversion=org.apache.tools.ant.taskdefs.condition.AntVersion
apply=org.apache.tools.ant.taskdefs.Transform
apt=org.apache.tools.ant.taskdefs.Apt
+attributenamespacedef=org.apache.tools.ant.taskdefs.AttributeNamespaceDef
augment=org.apache.tools.ant.taskdefs.AugmentReference
available=org.apache.tools.ant.taskdefs.Available
basename=org.apache.tools.ant.taskdefs.Basename
diff --git a/src/tests/antunit/core/ant-attribute-test.xml b/src/tests/antunit/core/ant-attribute-test.xml
new file mode 100644
index 000000000..5d76c7a20
--- /dev/null
+++ b/src/tests/antunit/core/ant-attribute-test.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+