001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.jexl2.internal;
019 import java.lang.reflect.InvocationTargetException;
020 /**
021 * Specialized executor to set a property in an object.
022 * @since 2.0
023 */
024 public final class PropertySetExecutor extends AbstractExecutor.Set {
025 /** Index of the first character of the set{p,P}roperty. */
026 private static final int SET_START_INDEX = 3;
027 /** The property. */
028 private final String property;
029
030 /**
031 * Creates an instance by attempting discovery of the set method.
032 * @param is the introspector
033 * @param clazz the class to introspect
034 * @param identifier the property to set
035 * @param arg the value to set into the property
036 */
037 public PropertySetExecutor(Introspector is, Class<?> clazz, String identifier, Object arg) {
038 super(clazz, discover(is, clazz, identifier, arg));
039 property = identifier;
040
041 }
042
043 /** {@inheritDoc} */
044 @Override
045 public Object getTargetProperty() {
046 return property;
047 }
048
049 /** {@inheritDoc} */
050 @Override
051 public Object execute(Object o, Object arg)
052 throws IllegalAccessException, InvocationTargetException {
053 Object[] pargs = {arg};
054 if (method != null) {
055 method.invoke(o, pargs);
056 }
057 return arg;
058 }
059
060 /** {@inheritDoc} */
061 @Override
062 public Object tryExecute(Object o, Object identifier, Object arg) {
063 if (o != null && method != null
064 // ensure method name matches the property name
065 && property.equals(identifier)
066 // object class should be same as executor's method declaring class
067 && objectClass.equals(o.getClass())
068 // we are guaranteed the method has one parameter since it is a set(x)
069 && (arg == null || method.getParameterTypes()[0].equals(arg.getClass()))) {
070 try {
071 return execute(o, arg);
072 } catch (InvocationTargetException xinvoke) {
073 return TRY_FAILED; // fail
074 } catch (IllegalAccessException xill) {
075 return TRY_FAILED;// fail
076 }
077 }
078 return TRY_FAILED;
079 }
080
081
082 /**
083 * Discovers the method for a {@link PropertySet}.
084 * <p>The method to be found should be named "set{P,p}property.</p>
085 *@param is the introspector
086 *@param clazz the class to find the get method from
087 *@param property the name of the property to set
088 *@param arg the value to assign to the property
089 *@return the method if found, null otherwise
090 */
091 private static java.lang.reflect.Method discover(Introspector is,
092 final Class<?> clazz, String property, Object arg) {
093 // first, we introspect for the set<identifier> setter method
094 Object[] params = {arg};
095 StringBuilder sb = new StringBuilder("set");
096 sb.append(property);
097 // uppercase nth char
098 char c = sb.charAt(SET_START_INDEX);
099 sb.setCharAt(SET_START_INDEX, Character.toUpperCase(c));
100 java.lang.reflect.Method method = is.getMethod(clazz, sb.toString(), params);
101 // lowercase nth char
102 if (method == null) {
103 sb.setCharAt(SET_START_INDEX, Character.toLowerCase(c));
104 method = is.getMethod(clazz, sb.toString(), params);
105 }
106
107 return method;
108 }
109 }
110