1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.jexl3.internal.introspection;
18
19 import java.lang.reflect.InvocationTargetException;
20 import org.apache.commons.jexl3.JexlException;
21
22 /**
23 * Specialized executor to get a property from an object.
24 * <p>Duck as in duck-typing for an interface like:
25 * <code>
26 * interface Get {
27 * Object get(Object key);
28 * }
29 * </code>
30 * </p>
31 * @since 2.0
32 */
33 public final class DuckGetExecutor extends AbstractExecutor.Get {
34 /** The property, may be null. */
35 private final Object property;
36
37 /**
38 * Attempts to discover a DuckGetExecutor.
39 * @param is the introspector
40 * @param clazz the class to find the get method from
41 * @param identifier the key to use as an argument to the get method
42 * @return the executor if found, null otherwise
43 */
44 public static DuckGetExecutor discover(final Introspector is, final Class<?> clazz, final Object identifier) {
45 final java.lang.reflect.Method method = is.getMethod(clazz, "get", identifier);
46 return method == null? null : new DuckGetExecutor(clazz, method, identifier);
47 }
48
49 /**
50 * Creates an instance.
51 * @param clazz he class the get method applies to
52 * @param method the method held by this executor
53 * @param identifier the property to get
54 */
55 private DuckGetExecutor(final Class<?> clazz, final java.lang.reflect.Method method, final Object identifier) {
56 super(clazz, method);
57 property = identifier;
58 }
59
60 @Override
61 public Object getTargetProperty() {
62 return property;
63 }
64
65 @Override
66 public Object invoke(final Object obj) throws IllegalAccessException, InvocationTargetException {
67 final Object[] args = {property};
68 return method == null ? null : method.invoke(obj, args);
69 }
70
71 @Override
72 public Object tryInvoke(final Object obj, final Object key) {
73 if (obj != null
74 && objectClass.equals(obj.getClass())
75 // ensure method name matches the property name
76 && method != null
77 && ((property == null && key == null)
78 || (property != null && property.equals(key)))) {
79 try {
80 final Object[] args = {property};
81 return method.invoke(obj, args);
82 } catch (IllegalAccessException | IllegalArgumentException xill) {
83 return TRY_FAILED;// fail
84 } catch (final InvocationTargetException xinvoke) {
85 throw JexlException.tryFailed(xinvoke); // throw
86 }
87 }
88 return TRY_FAILED;
89 }
90 }