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 * https://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
18 package org.apache.commons.jexl3.internal.introspection;
19
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Modifier;
22
23 import org.apache.commons.jexl3.introspection.JexlPropertySet;
24
25 /**
26 * A JexlPropertySet for public fields.
27 */
28 public final class FieldSetExecutor implements JexlPropertySet {
29 /**
30 * Attempts to discover a FieldSetExecutor.
31 *
32 * @param is the introspector
33 * @param clazz the class to find the get method from
34 * @param identifier the key to use as an argument to the get method
35 * @param value the value to set the field to
36 * @return the executor if found, null otherwise
37 */
38 public static JexlPropertySet discover(final Introspector is,
39 final Class<?> clazz,
40 final String identifier,
41 final Object value) {
42 if (identifier != null) {
43 final Field field = is.getField(clazz, identifier);
44 if (field != null
45 && !Modifier.isFinal(field.getModifiers())
46 && (value == null || MethodKey.isInvocationConvertible(field.getType(), value.getClass(), false))) {
47 return new FieldSetExecutor(field);
48 }
49 }
50 return null;
51 }
52
53 /**
54 * The public field.
55 */
56 private final Field field;
57
58 /**
59 * Creates a new instance of FieldPropertySet.
60 * @param theField the class public field
61 */
62 private FieldSetExecutor(final Field theField) {
63 field = theField;
64 }
65
66 @Override
67 public Object invoke(final Object obj, final Object arg) throws Exception {
68 field.set(obj, arg);
69 return arg;
70 }
71
72 @Override
73 public boolean isCacheable() {
74 return true;
75 }
76
77 @Override
78 public boolean tryFailed(final Object rval) {
79 return rval == Uberspect.TRY_FAILED;
80 }
81
82 @Override
83 public Object tryInvoke(final Object obj, final Object key, final Object value) {
84 if (obj.getClass().equals(field.getDeclaringClass())
85 && key.equals(field.getName())
86 && (value == null || MethodKey.isInvocationConvertible(field.getType(), value.getClass(), false))) {
87 try {
88 field.set(obj, value);
89 return value;
90 } catch (final IllegalAccessException xill) {
91 return Uberspect.TRY_FAILED;
92 }
93 }
94 return Uberspect.TRY_FAILED;
95 }
96 }