git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271752 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -39,7 +39,7 @@ public class Property | |||||
| /** | /** | ||||
| * Sets the property value from a nested element. | * Sets the property value from a nested element. | ||||
| */ | */ | ||||
| public void set( final DataType value ) | |||||
| public void add( final DataType value ) | |||||
| throws TaskException | throws TaskException | ||||
| { | { | ||||
| setValue( value ); | setValue( value ); | ||||
| @@ -21,8 +21,8 @@ class ConfigurationState | |||||
| private final Object m_object; | private final Object m_object; | ||||
| public ConfigurationState( final ObjectConfigurer configurer, | public ConfigurationState( final ObjectConfigurer configurer, | ||||
| final Object object, | |||||
| final int propertyCount ) | |||||
| final Object object, | |||||
| final int propertyCount ) | |||||
| { | { | ||||
| m_configurer = configurer; | m_configurer = configurer; | ||||
| m_object = object; | m_object = object; | ||||
| @@ -140,7 +140,7 @@ public class DefaultConfigurer | |||||
| { | { | ||||
| final String message = | final String message = | ||||
| REZ.getString( "no-such-attribute.error", elemName, name ); | REZ.getString( "no-such-attribute.error", elemName, name ); | ||||
| throw new ReportableConfigurationException( message ); | |||||
| throw new ReportableConfigurationException( message ); | |||||
| } | } | ||||
| catch( final Exception ce ) | catch( final Exception ce ) | ||||
| { | { | ||||
| @@ -299,7 +299,7 @@ public class DefaultConfigurer | |||||
| // Locate the configurer for the child element | // Locate the configurer for the child element | ||||
| final PropertyConfigurer childConfigurer = | final PropertyConfigurer childConfigurer = | ||||
| getConfigurerFromName( state.getConfigurer(), name, true ); | |||||
| getConfigurerFromName( state.getConfigurer(), name, true, true ); | |||||
| // Create & configure the child element | // Create & configure the child element | ||||
| final Object child = | final Object child = | ||||
| @@ -317,7 +317,6 @@ public class DefaultConfigurer | |||||
| final TaskContext context ) | final TaskContext context ) | ||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| // Extract the id | // Extract the id | ||||
| final String id = element.getAttribute( "id" ); | final String id = element.getAttribute( "id" ); | ||||
| if( 1 != element.getAttributeNames().length || | if( 1 != element.getAttributeNames().length || | ||||
| @@ -329,7 +328,7 @@ public class DefaultConfigurer | |||||
| // Set the property | // Set the property | ||||
| final String name = element.getName(); | final String name = element.getName(); | ||||
| setReference( state, name, id, context ); | |||||
| setReference( state, name, id, context, true ); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -338,29 +337,30 @@ public class DefaultConfigurer | |||||
| private void setReference( final ConfigurationState state, | private void setReference( final ConfigurationState state, | ||||
| final String refName, | final String refName, | ||||
| final String unresolvedId, | final String unresolvedId, | ||||
| final TaskContext context ) | |||||
| final TaskContext context, | |||||
| final boolean isAdder ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| // Adjust the name | // Adjust the name | ||||
| final String name = refName.substring( 0, refName.length() - 4 ); | final String name = refName.substring( 0, refName.length() - 4 ); | ||||
| // Locate the configurer for the property | // Locate the configurer for the property | ||||
| final PropertyConfigurer childConfigurer | |||||
| = getConfigurerFromName( state.getConfigurer(), name, false ); | |||||
| final PropertyConfigurer configurer = | |||||
| getConfigurerFromName( state.getConfigurer(), name, false, isAdder ); | |||||
| // Resolve any props in the id | // Resolve any props in the id | ||||
| String id = context.resolveValue( unresolvedId ).toString(); | String id = context.resolveValue( unresolvedId ).toString(); | ||||
| // Locate the referenced object | // Locate the referenced object | ||||
| Object ref = context.getProperty( id ); | Object ref = context.getProperty( id ); | ||||
| if( ref == null ) | |||||
| if( null == ref ) | |||||
| { | { | ||||
| final String message = REZ.getString( "unknown-reference.error", id ); | final String message = REZ.getString( "unknown-reference.error", id ); | ||||
| throw new ConfigurationException( message ); | throw new ConfigurationException( message ); | ||||
| } | } | ||||
| // Convert the object, if necessary | // Convert the object, if necessary | ||||
| final Class type = childConfigurer.getType(); | |||||
| final Class type = configurer.getType(); | |||||
| if( !type.isInstance( ref ) ) | if( !type.isInstance( ref ) ) | ||||
| { | { | ||||
| try | try | ||||
| @@ -375,7 +375,7 @@ public class DefaultConfigurer | |||||
| } | } | ||||
| // Set the child element | // Set the child element | ||||
| childConfigurer.addValue( state, ref ); | |||||
| configurer.addValue( state, ref ); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -390,13 +390,12 @@ public class DefaultConfigurer | |||||
| if( name.toLowerCase().endsWith( "-ref" ) ) | if( name.toLowerCase().endsWith( "-ref" ) ) | ||||
| { | { | ||||
| // A reference | // A reference | ||||
| setReference( state, name, value, context ); | |||||
| setReference( state, name, value, context, false ); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| // Set the value | // Set the value | ||||
| PropertyConfigurer propConfigurer | |||||
| = getConfigurerFromName( state.getConfigurer(), name, false ); | |||||
| PropertyConfigurer propConfigurer = getConfigurerFromName( state.getConfigurer(), name, false, false ); | |||||
| setValue( propConfigurer, state, value, context ); | setValue( propConfigurer, state, value, context ); | ||||
| } | } | ||||
| } | } | ||||
| @@ -495,35 +494,46 @@ public class DefaultConfigurer | |||||
| */ | */ | ||||
| private PropertyConfigurer getConfigurerFromName( final ObjectConfigurer configurer, | private PropertyConfigurer getConfigurerFromName( final ObjectConfigurer configurer, | ||||
| final String name, | final String name, | ||||
| boolean ignoreRoleName ) | |||||
| boolean ignoreRoleName, | |||||
| final boolean isAdder ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| // Try a named property | // Try a named property | ||||
| PropertyConfigurer propertyConfigurer = configurer.getProperty( name ); | |||||
| if( propertyConfigurer != null ) | |||||
| if( !isAdder ) | |||||
| { | { | ||||
| return propertyConfigurer; | |||||
| PropertyConfigurer propertyConfigurer = configurer.getSetter( name ); | |||||
| if( propertyConfigurer != null ) | |||||
| { | |||||
| return propertyConfigurer; | |||||
| } | |||||
| } | } | ||||
| // Try a typed property | |||||
| propertyConfigurer = configurer.getTypedProperty(); | |||||
| if( propertyConfigurer != null ) | |||||
| else | |||||
| { | { | ||||
| if( ignoreRoleName ) | |||||
| PropertyConfigurer propertyConfigurer = configurer.getAdder( name ); | |||||
| if( propertyConfigurer != null ) | |||||
| { | { | ||||
| return propertyConfigurer; | return propertyConfigurer; | ||||
| } | } | ||||
| else | |||||
| // Try a typed property | |||||
| propertyConfigurer = configurer.getTypedProperty(); | |||||
| if( propertyConfigurer != null ) | |||||
| { | { | ||||
| // Check the role name | |||||
| final RoleInfo roleInfo = m_roleManager.getRoleByType( propertyConfigurer.getType() ); | |||||
| if( roleInfo != null && name.equalsIgnoreCase( roleInfo.getShorthand() ) ) | |||||
| if( ignoreRoleName ) | |||||
| { | { | ||||
| return propertyConfigurer; | return propertyConfigurer; | ||||
| } | } | ||||
| else | |||||
| { | |||||
| // Check the role name | |||||
| final RoleInfo roleInfo = m_roleManager.getRoleByType( propertyConfigurer.getType() ); | |||||
| if( roleInfo != null && name.equalsIgnoreCase( roleInfo.getShorthand() ) ) | |||||
| { | |||||
| return propertyConfigurer; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| // Unknown prop | // Unknown prop | ||||
| throw new NoSuchPropertyException(); | throw new NoSuchPropertyException(); | ||||
| } | } | ||||
| @@ -35,19 +35,19 @@ class DefaultObjectConfigurer | |||||
| private final Class m_class; | private final Class m_class; | ||||
| /** | /** | ||||
| * Map from lowercase property name -> PropertyConfigurer. | |||||
| * All property configurers. (For XML elements) | |||||
| */ | */ | ||||
| private final Map m_props = new HashMap(); | |||||
| private final HashMap m_adders = new HashMap(); | |||||
| /** | /** | ||||
| * All property configurers. | |||||
| * Setter property configurers. (For XML attributes) | |||||
| */ | */ | ||||
| private final List m_allProps = new ArrayList(); | |||||
| private final HashMap m_setters = new HashMap(); | |||||
| /** | /** | ||||
| * The typed property configurer. | * The typed property configurer. | ||||
| */ | */ | ||||
| private PropertyConfigurer m_typedPropConfigurer; | |||||
| private PropertyConfigurer m_typedPropertyConfigurer; | |||||
| /** | /** | ||||
| * Content configurer. | * Content configurer. | ||||
| @@ -80,19 +80,20 @@ class DefaultObjectConfigurer | |||||
| private void enableProperties() | private void enableProperties() | ||||
| throws ConfigurationException | throws ConfigurationException | ||||
| { | { | ||||
| final Map adders = findAdders(); | |||||
| final Map configurers = findPropertyConfigurers(); | |||||
| // Add the elements | // Add the elements | ||||
| final Iterator iterator = adders.keySet().iterator(); | |||||
| final Iterator iterator = configurers.keySet().iterator(); | |||||
| while( iterator.hasNext() ) | while( iterator.hasNext() ) | ||||
| { | { | ||||
| final String propName = (String)iterator.next(); | |||||
| final Method addMethod = (Method)adders.get( propName ); | |||||
| final String name = (String)iterator.next(); | |||||
| final Method method = (Method)configurers.get( name ); | |||||
| final boolean isSetter = method.getName().startsWith( "set" ); | |||||
| // Determine and check the return type | // Determine and check the return type | ||||
| final Class type = addMethod.getParameterTypes()[ 0 ]; | |||||
| final boolean isTypedProp = ( propName.length() == 0 ); | |||||
| final Class type = method.getParameterTypes()[ 0 ]; | |||||
| final boolean isTypedProp = ( name.length() == 0 ); | |||||
| if( isTypedProp && !type.isInterface() ) | if( isTypedProp && !type.isInterface() ) | ||||
| { | { | ||||
| final String message = | final String message = | ||||
| @@ -101,27 +102,48 @@ class DefaultObjectConfigurer | |||||
| type.getName() ); | type.getName() ); | ||||
| throw new ConfigurationException( message ); | throw new ConfigurationException( message ); | ||||
| } | } | ||||
| // Determine the max count for the property | |||||
| int maxCount = Integer.MAX_VALUE; | |||||
| if( addMethod != null && addMethod.getName().startsWith( "set" ) ) | |||||
| else if( isTypedProp && isSetter ) | |||||
| { | |||||
| final String message = | |||||
| REZ.getString( "typed-setter-not-allowed.error", | |||||
| m_class.getName(), | |||||
| type.getName() ); | |||||
| throw new ConfigurationException( message ); | |||||
| } | |||||
| else if( isTypedProp && null != m_typedPropertyConfigurer ) | |||||
| { | { | ||||
| maxCount = 1; | |||||
| final String message = | |||||
| REZ.getString( "typed-adder-duplicates.error", | |||||
| m_class.getName(), | |||||
| type.getName() ); | |||||
| throw new ConfigurationException( message ); | |||||
| } | } | ||||
| final DefaultPropertyConfigurer configurer = | |||||
| new DefaultPropertyConfigurer( m_allProps.size(), | |||||
| type, | |||||
| addMethod, | |||||
| maxCount ); | |||||
| m_allProps.add( configurer ); | |||||
| if( isTypedProp ) | |||||
| // Determine the max count for the property | |||||
| if( isSetter ) | |||||
| { | { | ||||
| m_typedPropConfigurer = configurer; | |||||
| final DefaultPropertyConfigurer setter = | |||||
| new DefaultPropertyConfigurer( getPropertyCount(), | |||||
| type, | |||||
| method, | |||||
| 1 ); | |||||
| m_setters.put( name, setter ); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| m_props.put( propName, configurer ); | |||||
| final DefaultPropertyConfigurer configurer = | |||||
| new DefaultPropertyConfigurer( getPropertyCount(), | |||||
| type, | |||||
| method, | |||||
| Integer.MAX_VALUE ); | |||||
| if( isTypedProp ) | |||||
| { | |||||
| m_typedPropertyConfigurer = configurer; | |||||
| } | |||||
| else | |||||
| { | |||||
| m_adders.put( name, configurer ); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -130,7 +152,7 @@ class DefaultObjectConfigurer | |||||
| * Locate all 'add' and 'set' methods which return void, and take a | * Locate all 'add' and 'set' methods which return void, and take a | ||||
| * single parameter. | * single parameter. | ||||
| */ | */ | ||||
| private Map findAdders() | |||||
| private Map findPropertyConfigurers() | |||||
| throws ConfigurationException | throws ConfigurationException | ||||
| { | { | ||||
| final Map adders = new HashMap(); | final Map adders = new HashMap(); | ||||
| @@ -163,6 +185,12 @@ class DefaultObjectConfigurer | |||||
| if( adders.containsKey( propName ) ) | if( adders.containsKey( propName ) ) | ||||
| { | { | ||||
| final Method candidate = (Method)adders.get( propName ); | final Method candidate = (Method)adders.get( propName ); | ||||
| final String operation = methodName.substring( 0, 3 ); | |||||
| if( !candidate.getName().startsWith( operation ) ) | |||||
| { | |||||
| continue; | |||||
| } | |||||
| final Class currentType = candidate.getParameterTypes()[ 0 ]; | final Class currentType = candidate.getParameterTypes()[ 0 ]; | ||||
| // Ditch the string version, if any | // Ditch the string version, if any | ||||
| @@ -226,14 +254,20 @@ class DefaultObjectConfigurer | |||||
| final Class type = method.getParameterTypes()[ 0 ]; | final Class type = method.getParameterTypes()[ 0 ]; | ||||
| m_contentConfigurer = | m_contentConfigurer = | ||||
| new DefaultPropertyConfigurer( m_allProps.size(), | |||||
| new DefaultPropertyConfigurer( getPropertyCount(), | |||||
| type, | type, | ||||
| method, | method, | ||||
| 1 ); | 1 ); | ||||
| m_allProps.add( m_contentConfigurer ); | |||||
| } | } | ||||
| } | } | ||||
| private int getPropertyCount() | |||||
| { | |||||
| final int typedSize = ( null != m_typedPropertyConfigurer ) ? 1 : 0; | |||||
| final int contentSize = ( null != m_contentConfigurer ) ? 1 : 0; | |||||
| return m_adders.size() + m_setters.size() + contentSize + typedSize; | |||||
| } | |||||
| /** | /** | ||||
| * Locates the configurer for a particular class. | * Locates the configurer for a particular class. | ||||
| */ | */ | ||||
| @@ -251,7 +285,7 @@ class DefaultObjectConfigurer | |||||
| public ConfigurationState startConfiguration( Object object ) | public ConfigurationState startConfiguration( Object object ) | ||||
| throws ConfigurationException | throws ConfigurationException | ||||
| { | { | ||||
| return new ConfigurationState( this, object, m_allProps.size() ); | |||||
| return new ConfigurationState( this, object, getPropertyCount() ); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -269,9 +303,17 @@ class DefaultObjectConfigurer | |||||
| /** | /** | ||||
| * Returns a configurer for an element of this class. | * Returns a configurer for an element of this class. | ||||
| */ | */ | ||||
| public PropertyConfigurer getProperty( final String name ) | |||||
| public PropertyConfigurer getAdder( final String name ) | |||||
| { | |||||
| return (PropertyConfigurer)m_adders.get( name ); | |||||
| } | |||||
| /** | |||||
| * Returns a configurer for an element of this class. | |||||
| */ | |||||
| public PropertyConfigurer getSetter( final String name ) | |||||
| { | { | ||||
| return (PropertyConfigurer)m_props.get( name ); | |||||
| return (PropertyConfigurer)m_setters.get( name ); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -279,7 +321,7 @@ class DefaultObjectConfigurer | |||||
| */ | */ | ||||
| public PropertyConfigurer getTypedProperty() | public PropertyConfigurer getTypedProperty() | ||||
| { | { | ||||
| return m_typedPropConfigurer; | |||||
| return m_typedPropertyConfigurer; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -26,17 +26,17 @@ class DefaultPropertyConfigurer | |||||
| private final static Resources REZ = | private final static Resources REZ = | ||||
| ResourceManager.getPackageResources( DefaultPropertyConfigurer.class ); | ResourceManager.getPackageResources( DefaultPropertyConfigurer.class ); | ||||
| private final int m_propIndex; | |||||
| private final int m_propertyIndex; | |||||
| private final Class m_type; | private final Class m_type; | ||||
| private final Method m_addMethod; | |||||
| private final Method m_method; | |||||
| private final int m_maxCount; | private final int m_maxCount; | ||||
| public DefaultPropertyConfigurer( final int propIndex, | public DefaultPropertyConfigurer( final int propIndex, | ||||
| final Class type, | final Class type, | ||||
| final Method addMethod, | |||||
| final Method method, | |||||
| final int maxCount ) | final int maxCount ) | ||||
| { | { | ||||
| m_propIndex = propIndex; | |||||
| m_propertyIndex = propIndex; | |||||
| if( type.isPrimitive() ) | if( type.isPrimitive() ) | ||||
| { | { | ||||
| m_type = getComplexTypeFor( type ); | m_type = getComplexTypeFor( type ); | ||||
| @@ -45,8 +45,13 @@ class DefaultPropertyConfigurer | |||||
| { | { | ||||
| m_type = type; | m_type = type; | ||||
| } | } | ||||
| m_addMethod = addMethod; | |||||
| m_method = method; | |||||
| m_maxCount = maxCount; | m_maxCount = maxCount; | ||||
| if( null == m_method ) | |||||
| { | |||||
| throw new NullPointerException( "method" ); | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -64,22 +69,18 @@ class DefaultPropertyConfigurer | |||||
| throws ConfigurationException | throws ConfigurationException | ||||
| { | { | ||||
| final ConfigurationState defState = (ConfigurationState)state; | final ConfigurationState defState = (ConfigurationState)state; | ||||
| // Check the property count | // Check the property count | ||||
| if( defState.getPropertyCount( m_propIndex ) >= m_maxCount ) | |||||
| if( defState.getPropertyCount( m_propertyIndex ) >= m_maxCount ) | |||||
| { | { | ||||
| final String message = REZ.getString( "too-many-values.error" ); | final String message = REZ.getString( "too-many-values.error" ); | ||||
| throw new ConfigurationException( message ); | throw new ConfigurationException( message ); | ||||
| } | } | ||||
| defState.incPropertyCount( m_propIndex ); | |||||
| defState.incPropertyCount( m_propertyIndex ); | |||||
| try | try | ||||
| { | { | ||||
| // Add the value | // Add the value | ||||
| if( null != m_addMethod ) | |||||
| { | |||||
| m_addMethod.invoke( defState.getObject(), new Object[]{value} ); | |||||
| } | |||||
| m_method.invoke( defState.getObject(), new Object[]{value} ); | |||||
| } | } | ||||
| catch( final InvocationTargetException ite ) | catch( final InvocationTargetException ite ) | ||||
| { | { | ||||
| @@ -40,13 +40,22 @@ interface ObjectConfigurer | |||||
| throws ConfigurationException; | throws ConfigurationException; | ||||
| /** | /** | ||||
| * Returns a configurer for a property of this class. | |||||
| * Returns a configurer for a atribute property of this class. | |||||
| * | * | ||||
| * @param name The element name. Property names are case-insensitive. | |||||
| * @param name The attribute name. | |||||
| * @return A configurer for the property, or null if the property is not | * @return A configurer for the property, or null if the property is not | ||||
| * valid for this class. | * valid for this class. | ||||
| */ | */ | ||||
| PropertyConfigurer getProperty( String name ); | |||||
| PropertyConfigurer getSetter( String name ); | |||||
| /** | |||||
| * Returns a configurer for a element property of this class. | |||||
| * | |||||
| * @param name The element name. | |||||
| * @return A configurer for the property, or null if the property is not | |||||
| * valid for this class. | |||||
| */ | |||||
| PropertyConfigurer getAdder( String name ); | |||||
| /** | /** | ||||
| * Returns a configurer for the text content of this class. | * Returns a configurer for the text content of this class. | ||||
| @@ -17,3 +17,5 @@ typed-adder-non-interface.error=The typed adder for class "{0}" must have a sing | |||||
| create-typed-object.error=Could not create an object of type "{0}" of class {1}. | create-typed-object.error=Could not create an object of type "{0}" of class {1}. | ||||
| unknown-reference.error=Could not find referenced object "{0}". | unknown-reference.error=Could not find referenced object "{0}". | ||||
| bad-configure-element.error=Could not configure element <{0}>. | bad-configure-element.error=Could not configure element <{0}>. | ||||
| typed-setter-not-allowed.error=Not allowed to have "typed" setters as found in class {0}. | |||||
| typed-adder-duplicates.error=Multiple typed adders found in class {0}. | |||||