View Javadoc
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  }