Index: src/tests/antunit/core/ant-attribute-test.xml =================================================================== --- src/tests/antunit/core/ant-attribute-test.xml (revision 0) +++ src/tests/antunit/core/ant-attribute-test.xml (revision 0) @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: src/main/org/apache/tools/ant/ComponentHelper.java =================================================================== --- src/main/org/apache/tools/ant/ComponentHelper.java (revision 574890) +++ src/main/org/apache/tools/ant/ComponentHelper.java (working copy) @@ -289,6 +289,7 @@ public void initDefaultDefinitions() { initTasks(); initTypes(); + new DefaultDefinitions(this).execute(); } /** Index: src/main/org/apache/tools/ant/UnknownElement.java =================================================================== --- src/main/org/apache/tools/ant/UnknownElement.java (revision 574890) +++ src/main/org/apache/tools/ant/UnknownElement.java (working copy) @@ -167,6 +167,9 @@ * */ public void configure(Object realObject) { + if (realObject == null) { + return; + } realThing = realObject; getWrapper().setProxy(realThing); @@ -278,10 +281,8 @@ */ 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) { @@ -340,6 +341,14 @@ RuntimeConfigurable childWrapper = parentWrapper.getChild(i); UnknownElement child = (UnknownElement) 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)) { @@ -405,6 +414,9 @@ * @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(); Index: src/main/org/apache/tools/ant/DefaultDefinitions.java =================================================================== --- src/main/org/apache/tools/ant/DefaultDefinitions.java (revision 0) +++ src/main/org/apache/tools/ant/DefaultDefinitions.java (revision 0) @@ -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); + } +} Index: src/main/org/apache/tools/ant/attribute/AttributeNamespace.java =================================================================== --- src/main/org/apache/tools/ant/attribute/AttributeNamespace.java (revision 0) +++ src/main/org/apache/tools/ant/attribute/AttributeNamespace.java (revision 0) @@ -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 { +} Index: src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java =================================================================== --- src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java (revision 0) +++ src/main/org/apache/tools/ant/attribute/IfTrueAttribute.java (revision 0) @@ -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)); + } +} Index: src/main/org/apache/tools/ant/attribute/EnableAttribute.java =================================================================== --- src/main/org/apache/tools/ant/attribute/EnableAttribute.java (revision 0) +++ src/main/org/apache/tools/ant/attribute/EnableAttribute.java (revision 0) @@ -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); +} Index: src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java =================================================================== --- src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java (revision 0) +++ src/main/org/apache/tools/ant/attribute/IfBlankAttribute.java (revision 0) @@ -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))); + } +} Index: src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java =================================================================== --- src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java (revision 0) +++ src/main/org/apache/tools/ant/attribute/BaseIfAttribute.java (revision 0) @@ -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; + } +} Index: src/main/org/apache/tools/ant/attribute/IfSetAttribute.java =================================================================== --- src/main/org/apache/tools/ant/attribute/IfSetAttribute.java (revision 0) +++ src/main/org/apache/tools/ant/attribute/IfSetAttribute.java (revision 0) @@ -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); + } +} Index: src/main/org/apache/tools/ant/RuntimeConfigurable.java =================================================================== --- src/main/org/apache/tools/ant/RuntimeConfigurable.java (revision 574890) +++ src/main/org/apache/tools/ant/RuntimeConfigurable.java (working copy) @@ -29,6 +29,8 @@ import java.util.Map; import java.util.Iterator; +import org.apache.tools.ant.attribute.EnableAttribute; + import org.apache.tools.ant.util.CollectionUtils; import org.xml.sax.AttributeList; import org.xml.sax.helpers.AttributeListImpl; @@ -64,6 +66,9 @@ */ 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. The following code is copied from AttributeImpl. @@ -119,7 +124,74 @@ 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 < attributeNames.size(); ++i) { + String name = (String) attributeNames.get(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. * @@ -184,6 +256,9 @@ * @param value the attribute's value. */ public synchronized void setAttribute(String name, String value) { + if (name.indexOf(':') != -1) { + namespacedAttribute = true; + } if (name.equalsIgnoreCase(ProjectHelper.ANT_TYPE)) { this.polyType = value; } else { Index: src/main/org/apache/tools/ant/MagicNames.java =================================================================== --- src/main/org/apache/tools/ant/MagicNames.java (revision 574890) +++ src/main/org/apache/tools/ant/MagicNames.java (working copy) @@ -193,5 +193,8 @@ */ public static final String REFID_PROJECT_HELPER = "ant.projectHelper"; + /** Name of the namespace "type" (note: cannot be used as an element)*/ + public static final String ATTRIBUTE_NAMESPACE = "antribute namespace"; + } Index: src/main/org/apache/tools/ant/ProjectHelper.java =================================================================== --- src/main/org/apache/tools/ant/ProjectHelper.java (revision 574890) +++ src/main/org/apache/tools/ant/ProjectHelper.java (working copy) @@ -55,6 +55,9 @@ /** The URI for antlib current definitions */ public static final String ANT_CURRENT_URI = "ant:current"; + /** The URI for ant specific attributes */ + 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:"; @@ -484,6 +487,15 @@ } /** + * Convert an attribute namespace to a "component name". + * @param ns the xml namespace uri. + * @return the converted value. + */ + public static String nsToComponentName(String ns) { + return "attribute namespace:" + ns; + } + + /** * Add location to build exception. * @param ex the build exception, if the build exception * does not include Index: src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java =================================================================== --- src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java (revision 0) +++ src/main/org/apache/tools/ant/taskdefs/AttributeNamespaceDef.java (revision 0) @@ -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); + } +} Index: src/main/org/apache/tools/ant/taskdefs/defaults.properties =================================================================== --- src/main/org/apache/tools/ant/taskdefs/defaults.properties (revision 574890) +++ src/main/org/apache/tools/ant/taskdefs/defaults.properties (working copy) @@ -4,6 +4,7 @@ antstructure=org.apache.tools.ant.taskdefs.AntStructure antversion=org.apache.tools.ant.taskdefs.condition.AntVersion apply=org.apache.tools.ant.taskdefs.Transform +attributenamespacedef=org.apache.tools.ant.taskdefs.AttributeNamespaceDef available=org.apache.tools.ant.taskdefs.Available basename=org.apache.tools.ant.taskdefs.Basename buildnumber=org.apache.tools.ant.taskdefs.BuildNumber Index: src/etc/checkstyle/checkstyle-config =================================================================== --- src/etc/checkstyle/checkstyle-config (revision 574890) +++ src/etc/checkstyle/checkstyle-config (working copy) @@ -80,8 +80,8 @@ - - + + Index: lib/optional/ant-antunit-1.0.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream