Search in sources :

Example 1 with EnumeratedAttribute

use of org.apache.tools.ant.types.EnumeratedAttribute in project ant by apache.

the class IntrospectionHelper method createAttributeSetter.

/**
 * Creates an implementation of AttributeSetter for the given
 * attribute type. Conversions (where necessary) are automatically
 * made for the following types:
 * <ul>
 * <li>String (left as it is)
 * <li>Character/char (first character is used)
 * <li>Boolean/boolean
 * ({@link Project#toBoolean(String) Project.toBoolean(String)} is used)
 * <li>Class (Class.forName is used)
 * <li>File (resolved relative to the appropriate project)
 * <li>Path (resolve relative to the appropriate project)
 * <li>Resource (resolved as a FileResource relative to the appropriate project)
 * <li>FileProvider (resolved as a FileResource relative to the appropriate project)
 * <li>EnumeratedAttribute (uses its own
 * {@link EnumeratedAttribute#setValue(String) setValue} method)
 * <li>Other primitive types (wrapper classes are used with constructors
 * taking String)
 * </ul>
 *
 * If none of the above covers the given parameters, a constructor for the
 * appropriate class taking a String parameter is used if it is available.
 *
 * @param m The method to invoke on the bean when the setter is invoked.
 *          Must not be <code>null</code>.
 * @param arg The type of the single argument of the bean's method.
 *            Must not be <code>null</code>.
 * @param attrName the name of the attribute for which the setter is being
 *                 created.
 *
 * @return an appropriate AttributeSetter instance, or <code>null</code>
 *         if no appropriate conversion is available.
 */
private AttributeSetter createAttributeSetter(final Method m, final Class<?> arg, final String attrName) {
    // use wrappers for primitive classes, e.g. int and
    // Integer are treated identically
    final Class<?> reflectedArg = PRIMITIVE_TYPE_MAP.containsKey(arg) ? PRIMITIVE_TYPE_MAP.get(arg) : arg;
    // Object.class - it gets handled differently by AttributeSetter
    if (java.lang.Object.class == reflectedArg) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException {
                throw new BuildException("Internal ant problem - this should not get called");
            }
        };
    }
    // simplest case - setAttribute expects String
    if (String.class.equals(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException {
                m.invoke(parent, (Object[]) new String[] { value });
            }
        };
    }
    // char and Character get special treatment - take the first character
    if (java.lang.Character.class.equals(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException {
                if (value.length() == 0) {
                    throw new BuildException("The value \"\" is not a " + "legal value for attribute \"" + attrName + "\"");
                }
                m.invoke(parent, (Object[]) new Character[] { value.charAt(0) });
            }
        };
    }
    // boolean and Boolean get special treatment because we have a nice method in Project
    if (java.lang.Boolean.class.equals(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException {
                m.invoke(parent, (Object[]) new Boolean[] { Project.toBoolean(value) ? Boolean.TRUE : Boolean.FALSE });
            }
        };
    }
    // Class doesn't have a String constructor but a decent factory method
    if (java.lang.Class.class.equals(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException, BuildException {
                try {
                    m.invoke(parent, Class.forName(value));
                } catch (final ClassNotFoundException ce) {
                    throw new BuildException(ce);
                }
            }
        };
    }
    // resolve relative paths through Project
    if (java.io.File.class.equals(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException {
                m.invoke(parent, p.resolveFile(value));
            }
        };
    }
    // resolve relative nio paths through Project
    if (java.nio.file.Path.class.equals(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException {
                m.invoke(parent, p.resolveFile(value).toPath());
            }
        };
    }
    // resolve Resources/FileProviders as FileResources relative to Project:
    if (Resource.class.equals(reflectedArg) || FileProvider.class.equals(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException, BuildException {
                m.invoke(parent, new FileResource(p, p.resolveFile(value)));
            }
        };
    }
    // EnumeratedAttributes have their own helper class
    if (EnumeratedAttribute.class.isAssignableFrom(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException, BuildException {
                try {
                    final EnumeratedAttribute ea = (EnumeratedAttribute) reflectedArg.newInstance();
                    ea.setValue(value);
                    m.invoke(parent, ea);
                } catch (final InstantiationException ie) {
                    throw new BuildException(ie);
                }
            }
        };
    }
    final AttributeSetter setter = getEnumSetter(reflectedArg, m, arg);
    if (setter != null) {
        return setter;
    }
    if (java.lang.Long.class.equals(reflectedArg)) {
        return new AttributeSetter(m, arg) {

            @Override
            public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException, BuildException {
                try {
                    m.invoke(parent, StringUtils.parseHumanSizes(value));
                } catch (final NumberFormatException e) {
                    throw new BuildException("Can't assign non-numeric" + " value '" + value + "' to" + " attribute " + attrName);
                } catch (final InvocationTargetException e) {
                    throw e;
                } catch (final IllegalAccessException e) {
                    throw e;
                } catch (final Exception e) {
                    throw new BuildException(e);
                }
            }
        };
    }
    // worst case. look for a public String constructor and use it
    // also supports new Whatever(Project, String) as for Path or Reference
    // This is used (deliberately) for all primitives/wrappers other than
    // char, boolean, and long.
    boolean includeProject;
    Constructor<?> c;
    try {
        // First try with Project.
        c = reflectedArg.getConstructor(Project.class, String.class);
        includeProject = true;
    } catch (final NoSuchMethodException nme) {
        // OK, try without.
        try {
            c = reflectedArg.getConstructor(String.class);
            includeProject = false;
        } catch (final NoSuchMethodException nme2) {
            // Well, no matching constructor.
            return null;
        }
    }
    final boolean finalIncludeProject = includeProject;
    final Constructor<?> finalConstructor = c;
    return new AttributeSetter(m, arg) {

        @Override
        public void set(final Project p, final Object parent, final String value) throws InvocationTargetException, IllegalAccessException, BuildException {
            try {
                final Object[] args = finalIncludeProject ? new Object[] { p, value } : new Object[] { value };
                final Object attribute = finalConstructor.newInstance(args);
                if (p != null) {
                    p.setProjectReference(attribute);
                }
                m.invoke(parent, attribute);
            } catch (final InvocationTargetException e) {
                final Throwable cause = e.getCause();
                if (cause instanceof IllegalArgumentException) {
                    throw new BuildException("Can't assign value '" + value + "' to attribute " + attrName + ", reason: " + cause.getClass() + " with message '" + cause.getMessage() + "'");
                }
                throw e;
            } catch (final InstantiationException ie) {
                throw new BuildException(ie);
            }
        }
    };
}
Also used : Resource(org.apache.tools.ant.types.Resource) FileResource(org.apache.tools.ant.types.resources.FileResource) FileResource(org.apache.tools.ant.types.resources.FileResource) EnumeratedAttribute(org.apache.tools.ant.types.EnumeratedAttribute) InvocationTargetException(java.lang.reflect.InvocationTargetException) InvocationTargetException(java.lang.reflect.InvocationTargetException) FileProvider(org.apache.tools.ant.types.resources.FileProvider)

Aggregations

InvocationTargetException (java.lang.reflect.InvocationTargetException)1 EnumeratedAttribute (org.apache.tools.ant.types.EnumeratedAttribute)1 Resource (org.apache.tools.ant.types.Resource)1 FileProvider (org.apache.tools.ant.types.resources.FileProvider)1 FileResource (org.apache.tools.ant.types.resources.FileResource)1