diff --git a/src/main/org/apache/tools/ant/types/DataType.java b/src/main/org/apache/tools/ant/types/DataType.java
index 65a4e8b99..78192c5c5 100644
--- a/src/main/org/apache/tools/ant/types/DataType.java
+++ b/src/main/org/apache/tools/ant/types/DataType.java
@@ -17,11 +17,13 @@
package org.apache.tools.ant.types;
-
import java.util.Stack;
-import org.apache.tools.ant.BuildException;
+
import org.apache.tools.ant.Project;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.ProjectComponent;
+import org.apache.tools.ant.util.IdentityStack;
/**
* Base class for those classes that can appear inside the build file
@@ -35,6 +37,7 @@ import org.apache.tools.ant.ProjectComponent;
*
*/
public abstract class DataType extends ProjectComponent {
+
/**
* The description the user has set.
*
@@ -105,6 +108,40 @@ public abstract class DataType extends ProjectComponent {
checked = false;
}
+ /**
+ * Gets as descriptive as possible a name used for this datatype instance.
+ * @return String
name.
+ */
+ protected String getDataTypeName() {
+ Project p = getProject();
+ if (p != null) {
+ return ComponentHelper.getComponentHelper(p)
+ .getElementName(this, true);
+ }
+ String classname = getClass().getName();
+ return classname.substring(classname.lastIndexOf('.') + 1);
+ }
+
+ /**
+ * Convenience method.
+ * @since Ant 1.7
+ */
+ protected void dieOnCircularReference() {
+ dieOnCircularReference(getProject());
+ }
+
+ /**
+ * Convenience method.
+ * @param p the Ant Project instance against which to resolve references.
+ * @since Ant 1.7
+ */
+ protected void dieOnCircularReference(Project p) {
+ if (checked || !isReference()) {
+ return;
+ }
+ dieOnCircularReference(new IdentityStack(this), p);
+ }
+
/**
* Check to see whether any DataType we hold references to is
* included in the Stack (which holds all DataType instances that
@@ -120,9 +157,9 @@ public abstract class DataType extends ProjectComponent {
*
The general contract of this method is that it shouldn't do
* anything if {@link #checked checked
} is true and
* set it to true on exit.
project
is null
.
+ * @since Ant 1.7
+ */
+ protected Object getCheckedRef(final Class requiredClass,
+ final String dataTypeName, final Project project) {
+ dieOnCircularReference(project);
+ if (project == null) {
+ throw new BuildException("No Project specified");
+ }
+ Object o = ref.getReferencedObject(project);
if (!(requiredClass.isAssignableFrom(o.getClass()))) {
log("Class " + o.getClass() + " is not a subclass of " + requiredClass,
Project.MSG_VERBOSE);
String msg = ref.getRefId() + " doesn\'t denote a " + dataTypeName;
throw new BuildException(msg);
- } else {
- return o;
}
+ return o;
}
/**
@@ -223,7 +313,7 @@ public abstract class DataType extends ProjectComponent {
* get the reference set on this object
* @return the reference or null
*/
- protected Reference getRefid() {
+ public Reference getRefid() {
return ref;
}
diff --git a/src/main/org/apache/tools/ant/util/IdentityStack.java b/src/main/org/apache/tools/ant/util/IdentityStack.java
new file mode 100755
index 000000000..f0a024b61
--- /dev/null
+++ b/src/main/org/apache/tools/ant/util/IdentityStack.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.util;
+
+import java.util.Stack;
+
+/**
+ * Identity Stack.
+ * @since Ant 1.7
+ */
+public class IdentityStack extends Stack {
+
+ /**
+ * Get an IdentityStack containing the contents of the specified Stack.
+ * @param s the Stack to copy.
+ * @return an IdentityStack instance.
+ */
+ public static IdentityStack getInstance(Stack s) {
+ if (s instanceof IdentityStack) {
+ return (IdentityStack) s;
+ }
+ IdentityStack result = new IdentityStack();
+ result.addAll(s);
+ return result;
+ }
+
+ /**
+ * Default constructor.
+ */
+ public IdentityStack() {
+ }
+
+ /**
+ * Construct a new IdentityStack with the specified Object
+ * as the bottom element.
+ * @param o the bottom element.
+ */
+ public IdentityStack(Object o) {
+ super();
+ push(o);
+ }
+
+ /**
+ * Override methods that use .equals()
comparisons on elements.
+ * @param o the Object to search for.
+ * @see Vector#contains(Object)
+ */
+ public synchronized boolean contains(Object o) {
+ return indexOf(o) >= 0;
+ }
+
+ /**
+ * Override methods that use .equals()
comparisons on elements.
+ * @param o the Object to search for.
+ * @param pos the position from which to search.
+ * @see Vector#indexOf(Object, int)
+ */
+ public synchronized int indexOf(Object o, int pos) {
+ for (int i = pos; i < size(); i++)
+ {
+ if (get(i) == o) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Override methods that use .equals()
comparisons on elements.
+ * @param o the Object to search for.
+ * @param pos the position from which to search (backward).
+ * @see Vector#indexOf(Object, int)
+ */
+ public synchronized int lastIndexOf(Object o, int pos) {
+ for (int i = pos; i >= 0; i--)
+ {
+ if (get(i) == o) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+}
+