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