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