Browse Source

Remove IntrospectionHelper for the time being.

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270194 13f79535-47bb-0310-9956-ffa450edef68
master
Peter Donald 23 years ago
parent
commit
bff8b8303f
2 changed files with 0 additions and 1708 deletions
  1. +0
    -854
      proposal/myrmidon/src/main/org/apache/tools/ant/IntrospectionHelper.java
  2. +0
    -854
      proposal/myrmidon/src/todo/org/apache/tools/ant/IntrospectionHelper.java

+ 0
- 854
proposal/myrmidon/src/main/org/apache/tools/ant/IntrospectionHelper.java View File

@@ -1,854 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.tools.ant;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import org.apache.myrmidon.api.TaskException;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.FileUtils;

/**
* Helper class that collects the methods a task or nested element holds to set
* attributes, create nested elements or hold PCDATA elements.
*
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
*/
public class IntrospectionHelper implements BuildListener
{

/**
* instances we've already created
*/
private static Hashtable helpers = new Hashtable();

/**
* The method to add PCDATA stuff.
*/
private Method addText = null;

/**
* holds the attribute setter methods.
*/
private Hashtable attributeSetters;

/**
* holds the types of the attributes that could be set.
*/
private Hashtable attributeTypes;

/**
* The Class that's been introspected.
*/
private Class bean;

/**
* Holds methods to create nested elements.
*/
private Hashtable nestedCreators;

/**
* Holds methods to store configured nested elements.
*/
private Hashtable nestedStorers;

/**
* Holds the types of nested elements that could be created.
*/
private Hashtable nestedTypes;

private IntrospectionHelper( final Class bean )
throws TaskException
{
attributeTypes = new Hashtable();
attributeSetters = new Hashtable();
nestedTypes = new Hashtable();
nestedCreators = new Hashtable();
nestedStorers = new Hashtable();

this.bean = bean;

Method[] methods = bean.getMethods();
for( int i = 0; i < methods.length; i++ )
{
final Method m = methods[ i ];
final String name = m.getName();
Class returnType = m.getReturnType();
Class[] args = m.getParameterTypes();

// hide addTask for TaskContainers
if( org.apache.tools.ant.TaskContainer.class.isAssignableFrom( bean )
&& args.length == 1 && "addTask".equals( name )
&& org.apache.tools.ant.Task.class.equals( args[ 0 ] ) )
{
continue;
}

if( "addText".equals( name )
&& java.lang.Void.TYPE.equals( returnType )
&& args.length == 1
&& java.lang.String.class.equals( args[ 0 ] ) )
{

addText = methods[ i ];

}
else if( name.startsWith( "set" )
&& java.lang.Void.TYPE.equals( returnType )
&& args.length == 1
&& !args[ 0 ].isArray() )
{

String propName = getPropertyName( name, "set" );
if( attributeSetters.get( propName ) != null )
{
if( java.lang.String.class.equals( args[ 0 ] ) )
{
/*
* Ignore method m, as there is an overloaded
* form of this method that takes in a
* non-string argument, which gains higher
* priority.
*/
continue;
}
/*
* If the argument is not a String, and if there
* is an overloaded form of this method already defined,
* we just override that with the new one.
* This mechanism does not guarantee any specific order
* in which the methods will be selected: so any code
* that depends on the order in which "set" methods have
* been defined, is not guaranteed to be selected in any
* particular order.
*/
}
AttributeSetter as = createAttributeSetter( m, args[ 0 ] );
if( as != null )
{
attributeTypes.put( propName, args[ 0 ] );
attributeSetters.put( propName, as );
}

}
else if( name.startsWith( "create" )
&& !returnType.isArray()
&& !returnType.isPrimitive()
&& args.length == 0 )
{

String propName = getPropertyName( name, "create" );
nestedTypes.put( propName, returnType );
nestedCreators.put( propName,
new NestedCreator()
{

public Object create( Object parent )
throws InvocationTargetException,
IllegalAccessException
{

return m.invoke( parent, new Object[]{} );
}

} );

}
else if( name.startsWith( "addConfigured" )
&& java.lang.Void.TYPE.equals( returnType )
&& args.length == 1
&& !java.lang.String.class.equals( args[ 0 ] )
&& !args[ 0 ].isArray()
&& !args[ 0 ].isPrimitive() )
{

try
{
final Constructor c =
args[ 0 ].getConstructor( new Class[]{} );
String propName = getPropertyName( name, "addConfigured" );
nestedTypes.put( propName, args[ 0 ] );
nestedCreators.put( propName,
new NestedCreator()
{

public Object create( Object parent )
throws InvocationTargetException, IllegalAccessException, InstantiationException
{

Object o = c.newInstance( new Object[]{} );
return o;
}

} );
nestedStorers.put( propName,
new NestedStorer()
{

public void store( Object parent, Object child )
throws InvocationTargetException, IllegalAccessException, InstantiationException
{

m.invoke( parent, new Object[]{child} );
}

} );
}
catch( NoSuchMethodException nse )
{
}
}
else if( name.startsWith( "add" )
&& java.lang.Void.TYPE.equals( returnType )
&& args.length == 1
&& !java.lang.String.class.equals( args[ 0 ] )
&& !args[ 0 ].isArray()
&& !args[ 0 ].isPrimitive() )
{

try
{
final Constructor c =
args[ 0 ].getConstructor( new Class[]{} );
String propName = getPropertyName( name, "add" );
nestedTypes.put( propName, args[ 0 ] );
nestedCreators.put( propName,
new NestedCreator()
{

public Object create( Object parent )
throws InvocationTargetException, IllegalAccessException, InstantiationException
{

Object o = c.newInstance( new Object[]{} );
m.invoke( parent, new Object[]{o} );
return o;
}

} );
}
catch( NoSuchMethodException nse )
{
}
}
}
}

/**
* Factory method for helper objects.
*
* @param c Description of Parameter
* @return The Helper value
*/
public static synchronized IntrospectionHelper getHelper( Class c )
{
IntrospectionHelper ih = (IntrospectionHelper)helpers.get( c );
if( ih == null )
{
ih = new IntrospectionHelper( c );
helpers.put( c, ih );
}
return ih;
}

/**
* Sets the named attribute.
*
* @param p The new Attribute value
* @param element The new Attribute value
* @param attributeName The new Attribute value
* @param value The new Attribute value
* @exception BuildException Description of Exception
*/
public void setAttribute( Project p, Object element, String attributeName,
String value )
throws TaskException
{
AttributeSetter as = (AttributeSetter)attributeSetters.get( attributeName );
if( as == null )
{
String msg = getElementName( p, element ) +
//String msg = "Class " + element.getClass().getName() +
" doesn't support the \"" + attributeName + "\" attribute.";
throw new TaskException( msg );
}
try
{
as.set( p, element, value );
}
catch( IllegalAccessException ie )
{
// impossible as getMethods should only return public methods
throw new TaskException( ie.toString(), ie );
}
catch( InvocationTargetException ite )
{
Throwable t = ite.getTargetException();
if( t instanceof TaskException )
{
throw (TaskException)t;
}
throw new TaskException( t.toString(), t );
}
}

/**
* returns the type of a named attribute.
*
* @param attributeName Description of Parameter
* @return The AttributeType value
* @exception TaskException Description of Exception
*/
public Class getAttributeType( String attributeName )
throws TaskException
{
Class at = (Class)attributeTypes.get( attributeName );
if( at == null )
{
String msg = "Class " + bean.getName() +
" doesn't support the \"" + attributeName + "\" attribute.";
throw new TaskException( msg );
}
return at;
}

/**
* Return all attribues supported by the introspected class.
*
* @return The Attributes value
*/
public Enumeration getAttributes()
{
return attributeSetters.keys();
}

/**
* returns the type of a named nested element.
*
* @param elementName Description of Parameter
* @return The ElementType value
* @exception TaskException Description of Exception
*/
public Class getElementType( String elementName )
throws TaskException
{
Class nt = (Class)nestedTypes.get( elementName );
if( nt == null )
{
String msg = "Class " + bean.getName() +
" doesn't support the nested \"" + elementName + "\" element.";
throw new TaskException( msg );
}
return nt;
}

/**
* Return all nested elements supported by the introspected class.
*
* @return The NestedElements value
*/
public Enumeration getNestedElements()
{
return nestedTypes.keys();
}

/**
* Adds PCDATA areas.
*
* @param project The feature to be added to the Text attribute
* @param element The feature to be added to the Text attribute
* @param text The feature to be added to the Text attribute
*/
public void addText( Project project, Object element, String text )
throws TaskException
{
if( addText == null )
{
String msg = getElementName( project, element ) +
//String msg = "Class " + element.getClass().getName() +
" doesn't support nested text data.";
throw new TaskException( msg );
}
try
{
addText.invoke( element, new String[]{text} );
}
catch( IllegalAccessException ie )
{
// impossible as getMethods should only return public methods
throw new TaskException( ie.getMessage(), ie );
}
catch( InvocationTargetException ite )
{
Throwable t = ite.getTargetException();
if( t instanceof TaskException )
{
throw (TaskException)t;
}
throw new TaskException( t.getMessage(), t );
}
}

public void buildFinished( BuildEvent event )
{
attributeTypes.clear();
attributeSetters.clear();
nestedTypes.clear();
nestedCreators.clear();
addText = null;
helpers.clear();
}

public void buildStarted( BuildEvent event )
{
}

/**
* Creates a named nested element.
*
* @param project Description of Parameter
* @param element Description of Parameter
* @param elementName Description of Parameter
* @return Description of the Returned Value
* @exception TaskException Description of Exception
*/
public Object createElement( Project project, Object element, String elementName )
throws TaskException
{
NestedCreator nc = (NestedCreator)nestedCreators.get( elementName );
if( nc == null )
{
String msg = getElementName( project, element ) +
" doesn't support the nested \"" + elementName + "\" element.";
throw new TaskException( msg );
}
try
{
Object nestedElement = nc.create( element );
if( nestedElement instanceof ProjectComponent )
{
( (ProjectComponent)nestedElement ).setProject( project );
}
return nestedElement;
}
catch( IllegalAccessException ie )
{
// impossible as getMethods should only return public methods
throw new TaskException( ie.getMessage(), ie );
}
catch( InstantiationException ine )
{
// impossible as getMethods should only return public methods
throw new TaskException( ine.getMessage(), ine );
}
catch( InvocationTargetException ite )
{
Throwable t = ite.getTargetException();
if( t instanceof TaskException )
{
throw (TaskException)t;
}
throw new TaskException( t.getMessage(), t );
}
}

public void messageLogged( BuildEvent event )
{
}

/**
* Creates a named nested element.
*
* @param project Description of Parameter
* @param element Description of Parameter
* @param child Description of Parameter
* @param elementName Description of Parameter
* @exception TaskException Description of Exception
*/
public void storeElement( Project project, Object element, Object child, String elementName )
throws TaskException
{
if( elementName == null )
{
return;
}
NestedStorer ns = (NestedStorer)nestedStorers.get( elementName );
if( ns == null )
{
return;
}
try
{
ns.store( element, child );
}
catch( IllegalAccessException ie )
{
// impossible as getMethods should only return public methods
throw new TaskException( ie.getMessage(), ie );
}
catch( InstantiationException ine )
{
// impossible as getMethods should only return public methods
throw new TaskException( ine.getMessage(), ine );
}
catch( InvocationTargetException ite )
{
Throwable t = ite.getTargetException();
if( t instanceof TaskException )
{
throw (TaskException)t;
}
throw new TaskException( t.getMessage(), t );
}
}

/**
* Does the introspected class support PCDATA?
*
* @return Description of the Returned Value
*/
public boolean supportsCharacters()
{
return addText != null;
}

public void targetFinished( BuildEvent event )
{
}

public void targetStarted( BuildEvent event )
{
}

public void taskFinished( BuildEvent event )
{
}

public void taskStarted( BuildEvent event )
{
}

protected String getElementName( Project project, Object element )
{
Hashtable elements = project.getTaskDefinitions();
String typeName = "task";
if( !elements.contains( element.getClass() ) )
{
elements = project.getDataTypeDefinitions();
typeName = "data type";
if( !elements.contains( element.getClass() ) )
{
elements = null;
}
}

if( elements != null )
{
Enumeration e = elements.keys();
while( e.hasMoreElements() )
{
String elementName = (String)e.nextElement();
Class elementClass = (Class)elements.get( elementName );
if( element.getClass().equals( elementClass ) )
{
return "The <" + elementName + "> " + typeName;
}
}
}

return "Class " + element.getClass().getName();
}

/**
* extract the name of a property from a method name - subtracting a given
* prefix.
*
* @param methodName Description of Parameter
* @param prefix Description of Parameter
* @return The PropertyName value
*/
private String getPropertyName( String methodName, String prefix )
{
int start = prefix.length();
return methodName.substring( start ).toLowerCase( Locale.US );
}

/**
* Create a proper implementation of AttributeSetter for the given attribute
* type.
*
* @param m Description of Parameter
* @param arg Description of Parameter
* @return Description of the Returned Value
*/
private AttributeSetter createAttributeSetter( final Method m,
final Class arg )
throws TaskException
{

// simplest case - setAttribute expects String
if( java.lang.String.class.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new String[]{value} );
}
};
// now for the primitive types, use their wrappers
}
else if( java.lang.Character.class.equals( arg )
|| java.lang.Character.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Character[]{new Character( value.charAt( 0 ) )} );
}

};
}
else if( java.lang.Byte.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Byte[]{new Byte( value )} );
}

};
}
else if( java.lang.Short.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Short[]{new Short( value )} );
}

};
}
else if( java.lang.Integer.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Integer[]{new Integer( value )} );
}

};
}
else if( java.lang.Long.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Long[]{new Long( value )} );
}

};
}
else if( java.lang.Float.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Float[]{new Float( value )} );
}

};
}
else if( java.lang.Double.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Double[]{new Double( value )} );
}

};
// boolean gets an extra treatment, because we have a nice method
// in Project
}
else if( java.lang.Boolean.class.equals( arg )
|| java.lang.Boolean.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent,
new Boolean[]{new Boolean( Project.toBoolean( value ) )} );
}

};
// Class doesn't have a String constructor but a decent factory method
}
else if( java.lang.Class.class.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException, TaskException
{
try
{
m.invoke( parent, new Class[]{Class.forName( value )} );
}
catch( ClassNotFoundException ce )
{
throw new TaskException( ce.toString(), ce );
}
}
};
// resolve relative paths through Project
}
else if( java.io.File.class.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
final File file =
FileUtils.newFileUtils().resolveFile( p.getBaseDir(), value );
m.invoke( parent, new File[]{file} );
}

};
// resolve relative paths through Project
}
else if( org.apache.tools.ant.types.Path.class.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Path[]{new Path( p, value )} );
}

};
// EnumeratedAttributes have their own helper class
}
else if( org.apache.tools.ant.types.EnumeratedAttribute.class.isAssignableFrom( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException, TaskException
{
try
{
org.apache.tools.ant.types.EnumeratedAttribute ea = (org.apache.tools.ant.types.EnumeratedAttribute)arg.newInstance();
ea.setValue( value );
m.invoke( parent, new EnumeratedAttribute[]{ea} );
}
catch( InstantiationException ie )
{
throw new TaskException( ie.getMessage(), ie );
}
}
};

// worst case. look for a public String constructor and use it
}
else
{

try
{
final Constructor c =
arg.getConstructor( new Class[]{java.lang.String.class} );

return
new AttributeSetter()
{
public void set( Project p, Object parent,
String value )
throws InvocationTargetException, IllegalAccessException, TaskException
{
try
{
Object attribute = c.newInstance( new String[]{value} );
if( attribute instanceof ProjectComponent )
{
( (ProjectComponent)attribute ).setProject( p );
}
m.invoke( parent, new Object[]{attribute} );
}
catch( InstantiationException ie )
{
throw new TaskException( ie.getMessage(), ie );
}
}
};
}
catch( NoSuchMethodException nme )
{
}
}

return null;
}

private interface AttributeSetter
{
void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException,
TaskException;
}

private interface NestedCreator
{
Object create( Object parent )
throws InvocationTargetException, IllegalAccessException, InstantiationException;
}

private interface NestedStorer
{
void store( Object parent, Object child )
throws InvocationTargetException, IllegalAccessException, InstantiationException;
}
}

+ 0
- 854
proposal/myrmidon/src/todo/org/apache/tools/ant/IntrospectionHelper.java View File

@@ -1,854 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.tools.ant;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import org.apache.myrmidon.api.TaskException;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.FileUtils;

/**
* Helper class that collects the methods a task or nested element holds to set
* attributes, create nested elements or hold PCDATA elements.
*
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
*/
public class IntrospectionHelper implements BuildListener
{

/**
* instances we've already created
*/
private static Hashtable helpers = new Hashtable();

/**
* The method to add PCDATA stuff.
*/
private Method addText = null;

/**
* holds the attribute setter methods.
*/
private Hashtable attributeSetters;

/**
* holds the types of the attributes that could be set.
*/
private Hashtable attributeTypes;

/**
* The Class that's been introspected.
*/
private Class bean;

/**
* Holds methods to create nested elements.
*/
private Hashtable nestedCreators;

/**
* Holds methods to store configured nested elements.
*/
private Hashtable nestedStorers;

/**
* Holds the types of nested elements that could be created.
*/
private Hashtable nestedTypes;

private IntrospectionHelper( final Class bean )
throws TaskException
{
attributeTypes = new Hashtable();
attributeSetters = new Hashtable();
nestedTypes = new Hashtable();
nestedCreators = new Hashtable();
nestedStorers = new Hashtable();

this.bean = bean;

Method[] methods = bean.getMethods();
for( int i = 0; i < methods.length; i++ )
{
final Method m = methods[ i ];
final String name = m.getName();
Class returnType = m.getReturnType();
Class[] args = m.getParameterTypes();

// hide addTask for TaskContainers
if( org.apache.tools.ant.TaskContainer.class.isAssignableFrom( bean )
&& args.length == 1 && "addTask".equals( name )
&& org.apache.tools.ant.Task.class.equals( args[ 0 ] ) )
{
continue;
}

if( "addText".equals( name )
&& java.lang.Void.TYPE.equals( returnType )
&& args.length == 1
&& java.lang.String.class.equals( args[ 0 ] ) )
{

addText = methods[ i ];

}
else if( name.startsWith( "set" )
&& java.lang.Void.TYPE.equals( returnType )
&& args.length == 1
&& !args[ 0 ].isArray() )
{

String propName = getPropertyName( name, "set" );
if( attributeSetters.get( propName ) != null )
{
if( java.lang.String.class.equals( args[ 0 ] ) )
{
/*
* Ignore method m, as there is an overloaded
* form of this method that takes in a
* non-string argument, which gains higher
* priority.
*/
continue;
}
/*
* If the argument is not a String, and if there
* is an overloaded form of this method already defined,
* we just override that with the new one.
* This mechanism does not guarantee any specific order
* in which the methods will be selected: so any code
* that depends on the order in which "set" methods have
* been defined, is not guaranteed to be selected in any
* particular order.
*/
}
AttributeSetter as = createAttributeSetter( m, args[ 0 ] );
if( as != null )
{
attributeTypes.put( propName, args[ 0 ] );
attributeSetters.put( propName, as );
}

}
else if( name.startsWith( "create" )
&& !returnType.isArray()
&& !returnType.isPrimitive()
&& args.length == 0 )
{

String propName = getPropertyName( name, "create" );
nestedTypes.put( propName, returnType );
nestedCreators.put( propName,
new NestedCreator()
{

public Object create( Object parent )
throws InvocationTargetException,
IllegalAccessException
{

return m.invoke( parent, new Object[]{} );
}

} );

}
else if( name.startsWith( "addConfigured" )
&& java.lang.Void.TYPE.equals( returnType )
&& args.length == 1
&& !java.lang.String.class.equals( args[ 0 ] )
&& !args[ 0 ].isArray()
&& !args[ 0 ].isPrimitive() )
{

try
{
final Constructor c =
args[ 0 ].getConstructor( new Class[]{} );
String propName = getPropertyName( name, "addConfigured" );
nestedTypes.put( propName, args[ 0 ] );
nestedCreators.put( propName,
new NestedCreator()
{

public Object create( Object parent )
throws InvocationTargetException, IllegalAccessException, InstantiationException
{

Object o = c.newInstance( new Object[]{} );
return o;
}

} );
nestedStorers.put( propName,
new NestedStorer()
{

public void store( Object parent, Object child )
throws InvocationTargetException, IllegalAccessException, InstantiationException
{

m.invoke( parent, new Object[]{child} );
}

} );
}
catch( NoSuchMethodException nse )
{
}
}
else if( name.startsWith( "add" )
&& java.lang.Void.TYPE.equals( returnType )
&& args.length == 1
&& !java.lang.String.class.equals( args[ 0 ] )
&& !args[ 0 ].isArray()
&& !args[ 0 ].isPrimitive() )
{

try
{
final Constructor c =
args[ 0 ].getConstructor( new Class[]{} );
String propName = getPropertyName( name, "add" );
nestedTypes.put( propName, args[ 0 ] );
nestedCreators.put( propName,
new NestedCreator()
{

public Object create( Object parent )
throws InvocationTargetException, IllegalAccessException, InstantiationException
{

Object o = c.newInstance( new Object[]{} );
m.invoke( parent, new Object[]{o} );
return o;
}

} );
}
catch( NoSuchMethodException nse )
{
}
}
}
}

/**
* Factory method for helper objects.
*
* @param c Description of Parameter
* @return The Helper value
*/
public static synchronized IntrospectionHelper getHelper( Class c )
{
IntrospectionHelper ih = (IntrospectionHelper)helpers.get( c );
if( ih == null )
{
ih = new IntrospectionHelper( c );
helpers.put( c, ih );
}
return ih;
}

/**
* Sets the named attribute.
*
* @param p The new Attribute value
* @param element The new Attribute value
* @param attributeName The new Attribute value
* @param value The new Attribute value
* @exception BuildException Description of Exception
*/
public void setAttribute( Project p, Object element, String attributeName,
String value )
throws TaskException
{
AttributeSetter as = (AttributeSetter)attributeSetters.get( attributeName );
if( as == null )
{
String msg = getElementName( p, element ) +
//String msg = "Class " + element.getClass().getName() +
" doesn't support the \"" + attributeName + "\" attribute.";
throw new TaskException( msg );
}
try
{
as.set( p, element, value );
}
catch( IllegalAccessException ie )
{
// impossible as getMethods should only return public methods
throw new TaskException( ie.toString(), ie );
}
catch( InvocationTargetException ite )
{
Throwable t = ite.getTargetException();
if( t instanceof TaskException )
{
throw (TaskException)t;
}
throw new TaskException( t.toString(), t );
}
}

/**
* returns the type of a named attribute.
*
* @param attributeName Description of Parameter
* @return The AttributeType value
* @exception TaskException Description of Exception
*/
public Class getAttributeType( String attributeName )
throws TaskException
{
Class at = (Class)attributeTypes.get( attributeName );
if( at == null )
{
String msg = "Class " + bean.getName() +
" doesn't support the \"" + attributeName + "\" attribute.";
throw new TaskException( msg );
}
return at;
}

/**
* Return all attribues supported by the introspected class.
*
* @return The Attributes value
*/
public Enumeration getAttributes()
{
return attributeSetters.keys();
}

/**
* returns the type of a named nested element.
*
* @param elementName Description of Parameter
* @return The ElementType value
* @exception TaskException Description of Exception
*/
public Class getElementType( String elementName )
throws TaskException
{
Class nt = (Class)nestedTypes.get( elementName );
if( nt == null )
{
String msg = "Class " + bean.getName() +
" doesn't support the nested \"" + elementName + "\" element.";
throw new TaskException( msg );
}
return nt;
}

/**
* Return all nested elements supported by the introspected class.
*
* @return The NestedElements value
*/
public Enumeration getNestedElements()
{
return nestedTypes.keys();
}

/**
* Adds PCDATA areas.
*
* @param project The feature to be added to the Text attribute
* @param element The feature to be added to the Text attribute
* @param text The feature to be added to the Text attribute
*/
public void addText( Project project, Object element, String text )
throws TaskException
{
if( addText == null )
{
String msg = getElementName( project, element ) +
//String msg = "Class " + element.getClass().getName() +
" doesn't support nested text data.";
throw new TaskException( msg );
}
try
{
addText.invoke( element, new String[]{text} );
}
catch( IllegalAccessException ie )
{
// impossible as getMethods should only return public methods
throw new TaskException( ie.getMessage(), ie );
}
catch( InvocationTargetException ite )
{
Throwable t = ite.getTargetException();
if( t instanceof TaskException )
{
throw (TaskException)t;
}
throw new TaskException( t.getMessage(), t );
}
}

public void buildFinished( BuildEvent event )
{
attributeTypes.clear();
attributeSetters.clear();
nestedTypes.clear();
nestedCreators.clear();
addText = null;
helpers.clear();
}

public void buildStarted( BuildEvent event )
{
}

/**
* Creates a named nested element.
*
* @param project Description of Parameter
* @param element Description of Parameter
* @param elementName Description of Parameter
* @return Description of the Returned Value
* @exception TaskException Description of Exception
*/
public Object createElement( Project project, Object element, String elementName )
throws TaskException
{
NestedCreator nc = (NestedCreator)nestedCreators.get( elementName );
if( nc == null )
{
String msg = getElementName( project, element ) +
" doesn't support the nested \"" + elementName + "\" element.";
throw new TaskException( msg );
}
try
{
Object nestedElement = nc.create( element );
if( nestedElement instanceof ProjectComponent )
{
( (ProjectComponent)nestedElement ).setProject( project );
}
return nestedElement;
}
catch( IllegalAccessException ie )
{
// impossible as getMethods should only return public methods
throw new TaskException( ie.getMessage(), ie );
}
catch( InstantiationException ine )
{
// impossible as getMethods should only return public methods
throw new TaskException( ine.getMessage(), ine );
}
catch( InvocationTargetException ite )
{
Throwable t = ite.getTargetException();
if( t instanceof TaskException )
{
throw (TaskException)t;
}
throw new TaskException( t.getMessage(), t );
}
}

public void messageLogged( BuildEvent event )
{
}

/**
* Creates a named nested element.
*
* @param project Description of Parameter
* @param element Description of Parameter
* @param child Description of Parameter
* @param elementName Description of Parameter
* @exception TaskException Description of Exception
*/
public void storeElement( Project project, Object element, Object child, String elementName )
throws TaskException
{
if( elementName == null )
{
return;
}
NestedStorer ns = (NestedStorer)nestedStorers.get( elementName );
if( ns == null )
{
return;
}
try
{
ns.store( element, child );
}
catch( IllegalAccessException ie )
{
// impossible as getMethods should only return public methods
throw new TaskException( ie.getMessage(), ie );
}
catch( InstantiationException ine )
{
// impossible as getMethods should only return public methods
throw new TaskException( ine.getMessage(), ine );
}
catch( InvocationTargetException ite )
{
Throwable t = ite.getTargetException();
if( t instanceof TaskException )
{
throw (TaskException)t;
}
throw new TaskException( t.getMessage(), t );
}
}

/**
* Does the introspected class support PCDATA?
*
* @return Description of the Returned Value
*/
public boolean supportsCharacters()
{
return addText != null;
}

public void targetFinished( BuildEvent event )
{
}

public void targetStarted( BuildEvent event )
{
}

public void taskFinished( BuildEvent event )
{
}

public void taskStarted( BuildEvent event )
{
}

protected String getElementName( Project project, Object element )
{
Hashtable elements = project.getTaskDefinitions();
String typeName = "task";
if( !elements.contains( element.getClass() ) )
{
elements = project.getDataTypeDefinitions();
typeName = "data type";
if( !elements.contains( element.getClass() ) )
{
elements = null;
}
}

if( elements != null )
{
Enumeration e = elements.keys();
while( e.hasMoreElements() )
{
String elementName = (String)e.nextElement();
Class elementClass = (Class)elements.get( elementName );
if( element.getClass().equals( elementClass ) )
{
return "The <" + elementName + "> " + typeName;
}
}
}

return "Class " + element.getClass().getName();
}

/**
* extract the name of a property from a method name - subtracting a given
* prefix.
*
* @param methodName Description of Parameter
* @param prefix Description of Parameter
* @return The PropertyName value
*/
private String getPropertyName( String methodName, String prefix )
{
int start = prefix.length();
return methodName.substring( start ).toLowerCase( Locale.US );
}

/**
* Create a proper implementation of AttributeSetter for the given attribute
* type.
*
* @param m Description of Parameter
* @param arg Description of Parameter
* @return Description of the Returned Value
*/
private AttributeSetter createAttributeSetter( final Method m,
final Class arg )
throws TaskException
{

// simplest case - setAttribute expects String
if( java.lang.String.class.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new String[]{value} );
}
};
// now for the primitive types, use their wrappers
}
else if( java.lang.Character.class.equals( arg )
|| java.lang.Character.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Character[]{new Character( value.charAt( 0 ) )} );
}

};
}
else if( java.lang.Byte.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Byte[]{new Byte( value )} );
}

};
}
else if( java.lang.Short.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Short[]{new Short( value )} );
}

};
}
else if( java.lang.Integer.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Integer[]{new Integer( value )} );
}

};
}
else if( java.lang.Long.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Long[]{new Long( value )} );
}

};
}
else if( java.lang.Float.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Float[]{new Float( value )} );
}

};
}
else if( java.lang.Double.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Double[]{new Double( value )} );
}

};
// boolean gets an extra treatment, because we have a nice method
// in Project
}
else if( java.lang.Boolean.class.equals( arg )
|| java.lang.Boolean.TYPE.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent,
new Boolean[]{new Boolean( Project.toBoolean( value ) )} );
}

};
// Class doesn't have a String constructor but a decent factory method
}
else if( java.lang.Class.class.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException, TaskException
{
try
{
m.invoke( parent, new Class[]{Class.forName( value )} );
}
catch( ClassNotFoundException ce )
{
throw new TaskException( ce.toString(), ce );
}
}
};
// resolve relative paths through Project
}
else if( java.io.File.class.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
final File file =
FileUtils.newFileUtils().resolveFile( p.getBaseDir(), value );
m.invoke( parent, new File[]{file} );
}

};
// resolve relative paths through Project
}
else if( org.apache.tools.ant.types.Path.class.equals( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException
{
m.invoke( parent, new Path[]{new Path( p, value )} );
}

};
// EnumeratedAttributes have their own helper class
}
else if( org.apache.tools.ant.types.EnumeratedAttribute.class.isAssignableFrom( arg ) )
{
return
new AttributeSetter()
{
public void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException, TaskException
{
try
{
org.apache.tools.ant.types.EnumeratedAttribute ea = (org.apache.tools.ant.types.EnumeratedAttribute)arg.newInstance();
ea.setValue( value );
m.invoke( parent, new EnumeratedAttribute[]{ea} );
}
catch( InstantiationException ie )
{
throw new TaskException( ie.getMessage(), ie );
}
}
};

// worst case. look for a public String constructor and use it
}
else
{

try
{
final Constructor c =
arg.getConstructor( new Class[]{java.lang.String.class} );

return
new AttributeSetter()
{
public void set( Project p, Object parent,
String value )
throws InvocationTargetException, IllegalAccessException, TaskException
{
try
{
Object attribute = c.newInstance( new String[]{value} );
if( attribute instanceof ProjectComponent )
{
( (ProjectComponent)attribute ).setProject( p );
}
m.invoke( parent, new Object[]{attribute} );
}
catch( InstantiationException ie )
{
throw new TaskException( ie.getMessage(), ie );
}
}
};
}
catch( NoSuchMethodException nme )
{
}
}

return null;
}

private interface AttributeSetter
{
void set( Project p, Object parent, String value )
throws InvocationTargetException, IllegalAccessException,
TaskException;
}

private interface NestedCreator
{
Object create( Object parent )
throws InvocationTargetException, IllegalAccessException, InstantiationException;
}

private interface NestedStorer
{
void store( Object parent, Object child )
throws InvocationTargetException, IllegalAccessException, InstantiationException;
}
}

Loading…
Cancel
Save