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 */ 017package org.apache.commons.jexl3.internal.introspection; 018 019import java.lang.reflect.InvocationTargetException; 020import org.apache.commons.jexl3.JexlException; 021 022/** 023 * Specialized executor to get a property from an object. 024 * <p>Duck as in duck-typing for an interface like: 025 * <code> 026 * interface Get { 027 * Object get(Object key); 028 * } 029 * </code> 030 * </p> 031 * @since 2.0 032 */ 033public final class DuckGetExecutor extends AbstractExecutor.Get { 034 /** The property, may be null. */ 035 private final Object property; 036 037 /** 038 * Attempts to discover a DuckGetExecutor. 039 * @param is the introspector 040 * @param clazz the class to find the get method from 041 * @param identifier the key to use as an argument to the get method 042 * @return the executor if found, null otherwise 043 */ 044 public static DuckGetExecutor discover(final Introspector is, final Class<?> clazz, final Object identifier) { 045 final java.lang.reflect.Method method = is.getMethod(clazz, "get", makeArgs(identifier)); 046 return method == null? null : new DuckGetExecutor(clazz, method, identifier); 047 } 048 049 /** 050 * Creates an instance. 051 * @param clazz he class the get method applies to 052 * @param method the method held by this executor 053 * @param identifier the property to get 054 */ 055 private DuckGetExecutor(final Class<?> clazz, final java.lang.reflect.Method method, final Object identifier) { 056 super(clazz, method); 057 property = identifier; 058 } 059 060 @Override 061 public Object getTargetProperty() { 062 return property; 063 } 064 065 @Override 066 public Object invoke(final Object obj) throws IllegalAccessException, InvocationTargetException { 067 final Object[] args = {property}; 068 return method == null ? null : method.invoke(obj, args); 069 } 070 071 @Override 072 public Object tryInvoke(final Object obj, final Object key) { 073 if (obj != null 074 && objectClass.equals(obj.getClass()) 075 // ensure method name matches the property name 076 && method != null 077 && ((property == null && key == null) 078 || (property != null && property.equals(key)))) { 079 try { 080 final Object[] args = {property}; 081 return method.invoke(obj, args); 082 } catch (IllegalAccessException | IllegalArgumentException xill) { 083 return TRY_FAILED;// fail 084 } catch (final InvocationTargetException xinvoke) { 085 throw JexlException.tryFailed(xinvoke); // throw 086 } 087 } 088 return TRY_FAILED; 089 } 090}