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