    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.jexl2.internal;
    018
    019    import java.lang.reflect.InvocationTargetException;
    020
    021    /**
    022     * Specialized executor to get a property from an object.
    023     * <p>Duck as in duck-typing for an interface like:
    024     * <code>
    025     * interface Get {
    026     *      Object get(Object key);
    027     * }
    028     * </code>
    029     * </p>
    030     * @since 2.0
    031     */
    032    public final class DuckGetExecutor extends AbstractExecutor.Get {
    033        /** The property. */
    034        private final Object property;
    035
    036        /**
    037         * Creates an instance by attempting discovery of the get method.
    038         * @param is the introspector
    039         * @param clazz the class to introspect
    040         * @param identifier the property to get
    041         */
    042        public DuckGetExecutor(Introspector is, Class<?> clazz, Object identifier) {
    043            super(clazz, discover(is, clazz, identifier));
    044            property = identifier;
    045        }
    046
    047        /** {@inheritDoc} */
    048        @Override
    049        public Object getTargetProperty() {
    050            return property;
    051        }
    052
    053        /**
    054         * Get the property from the object.
    055         * @param obj the object.
    056         * @return object.get(property)
    057         * @throws IllegalAccessException Method is inaccessible.
    058         * @throws InvocationTargetException Method body throws an exception.
    059         */
    060        @Override
    061        public Object execute(Object obj)
    062                throws IllegalAccessException, InvocationTargetException {
    063            Object[] args = {property};
    064            return method == null ? null : method.invoke(obj, args);
    065        }
    066
    067        /** {@inheritDoc} */
    068        @Override
    069        public Object tryExecute(Object obj, Object key) {
    070            if (obj != null && method !=  null
    071                // ensure method name matches the property name
    072                && property.equals(key)
    073                && objectClass.equals(obj.getClass())) {
    074                try {
    075                    Object[] args = {property};
    076                    return method.invoke(obj, args);
    077                } catch (InvocationTargetException xinvoke) {
    078                    return TRY_FAILED; // fail
    079                } catch (IllegalAccessException xill) {
    080                    return TRY_FAILED;// fail
    081                }
    082            }
    083            return TRY_FAILED;
    084        }
    085
    086        /**
    087         * Discovers a method for a {@link GetExecutor.DuckGet}.
    088         *@param is the introspector
    089         *@param clazz the class to find the get method from
    090         *@param identifier the key to use as an argument to the get method
    091         *@return the method if found, null otherwise
    092         */
    093        private static java.lang.reflect.Method discover(Introspector is,
    094                final Class<?> clazz, Object identifier) {
    095            return is.getMethod(clazz, "get", makeArgs(identifier));
    096        }
    097    }