mbenson 2005/05/23 12:28:09 Modified: src/main/org/apache/tools/ant/types DataType.java Added: src/main/org/apache/tools/ant/util IdentityStack.java Log: new methods for reference checking and logging Revision Changes Path 1.1 ant/src/main/org/apache/tools/ant/util/IdentityStack.java Index: IdentityStack.java =================================================================== /* * 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 <code>.equals()</code> 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 <code>.equals()</code> 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 <code>.equals()</code> 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; } } 1.26 +112 -22 ant/src/main/org/apache/tools/ant/types/DataType.java Index: DataType.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/types/DataType.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- DataType.java 25 Apr 2005 22:13:29 -0000 1.25 +++ DataType.java 23 May 2005 19:28:09 -0000 1.26 @@ -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 @@ * */ public abstract class DataType extends ProjectComponent { + /** * The description the user has set. * @@ -106,6 +109,40 @@ } /** + * Gets as descriptive as possible a name used for this datatype instance. + * @return <code>String</code> 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 * directly or indirectly reference this instance, including this @@ -120,9 +157,9 @@ * <p>The general contract of this method is that it shouldn't do * anything if [EMAIL PROTECTED] #checked <code>checked</code>} is true and * set it to true on exit.</p> - * @param stack the stack of references to check - * @param project the project to use to dereference the references - * @throws BuildException on error + * @param stack the stack of references to check. + * @param project the project to use to dereference the references. + * @throws BuildException on error. */ protected void dieOnCircularReference(final Stack stack, final Project project) @@ -134,43 +171,96 @@ Object o = ref.getReferencedObject(project); if (o instanceof DataType) { - if (stack.contains(o)) { + IdentityStack id = IdentityStack.getInstance(stack); + + if (id.contains(o)) { throw circularReference(); } else { - stack.push(o); - ((DataType) o).dieOnCircularReference(stack, project); - stack.pop(); + id.push(o); + ((DataType) o).dieOnCircularReference(id, project); + id.pop(); } } checked = true; } /** + * Allow DataTypes outside org.apache.tools.ant.types to indirectly call + * dieOnCircularReference on nested DataTypes. + * @param dt the DataType to check. + * @param stack the stack of references to check. + * @param project the project to use to dereference the references. + * @throws BuildException on error. + * @since Ant 1.7 + */ + public static void invokeCircularReferenceCheck(DataType dt, Stack stk, + Project p) { + dt.dieOnCircularReference(stk, p); + } + + /** + * Performs the check for circular references and returns the + * referenced object. + * @return the dereferenced object. + * @throws BuildException if the reference is invalid (circular ref, wrong class, etc). + * @since Ant 1.7 + */ + protected Object getCheckedRef() { + return getCheckedRef(getProject()); + } + + /** * Performs the check for circular references and returns the * referenced object. - * @param requiredClass the class that this reference should be a subclass of - * @param dataTypeName the name of the datatype that the reference should be (error message - * use only) - * @return the derefenced object + * @param project the Ant Project instance against which to resolve references. + * @return the dereferenced object. + * @throws BuildException if the reference is invalid (circular ref, wrong class, etc). + * @since Ant 1.7 + */ + protected Object getCheckedRef(Project p) { + return getCheckedRef(getClass(), getDataTypeName(), p); + } + + /** + * Performs the check for circular references and returns the + * referenced object. + * @param requiredClass the class that this reference should be a subclass of. + * @param dataTypeName the name of the datatype that the reference should be + * (error message use only). + * @return the dereferenced object. * @throws BuildException if the reference is invalid (circular ref, wrong class, etc). */ protected Object getCheckedRef(final Class requiredClass, final String dataTypeName) { - if (!checked) { - Stack stk = new Stack(); - stk.push(this); - dieOnCircularReference(stk, getProject()); - } + return getCheckedRef(requiredClass, dataTypeName, getProject()); + } - Object o = ref.getReferencedObject(getProject()); + /** + * Performs the check for circular references and returns the + * referenced object. This version allows the fallback Project instance to be specified. + * @param requiredClass the class that this reference should be a subclass of. + * @param dataTypeName the name of the datatype that the reference should be + * (error message use only). + * @param project the fallback Project instance for dereferencing. + * @return the dereferenced object. + * @throws BuildException if the reference is invalid (circular ref, wrong class, etc), + * or if <code>project</code> is <code>null</code>. + * @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 @@ * get the reference set on this object * @return the reference or null */ - protected Reference getRefid() { + public Reference getRefid() { return ref; }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]