/*
* Copyright (C) 2001 Mika Riekkinen, Joni Suominen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alt.jiapi.instrumentor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
//import java.util.logging.Logger;
import org.apache.log4j.Category;
import alt.jiapi.Runtime;
import alt.jiapi.reflect.InstructionFactory;
import alt.jiapi.reflect.InstructionList;
import alt.jiapi.reflect.JiapiClass;
import alt.jiapi.reflect.JiapiField;
import alt.jiapi.reflect.JiapiMethod;
import alt.jiapi.reflect.JiapiRuntimeException;
import alt.jiapi.reflect.Loader;
/**
* Creates a patch which sets a value for a field.
*
* @author Mika Riekkinen
* @author Joni Suominen
* @version $Revision: 1.12 $ $Date: 2004/03/15 14:47:53 $
*/
public class FieldAssignInstrumentor extends AbstractInstrumentor {
//private static Logger log = Logger.getLogger(FieldAssignInstrumentor.class.getName());
private static Category log = Runtime.getLogCategory(FieldAssignInstrumentor.class);
private String fieldName;
private Object value;
private JiapiMethod getFieldValue;
public FieldAssignInstrumentor(String fieldName, Object value) {
this.fieldName = fieldName;
this.value = value;
Runtime.setFieldValue(fieldName, value);
try {
Loader l = new Loader();
JiapiClass jc = l.loadClass("alt.jiapi.Runtime");
// Class []params = new Class[] { String.class };
// getFieldValue = Runtime.class.getMethod("getFieldValue", params);
getFieldValue = jc.getDeclaredMethod("getFieldValue", new String[] {"java.lang.String"});
}
catch (Exception e) {
// not possible, but just in case
e.printStackTrace();
throw new RuntimeException(e.toString());
}
}
public void instrument(InstructionList il) {
// Native or abstract methods can't be instrumented.
int modifiers = il.getDeclaringMethod().getModifiers();
if (Modifier.isNative(modifiers) || Modifier.isAbstract(modifiers)) {
log.info("Skipping abstract or native method: " +
il.getDeclaringMethod().getName());
forward(il);
return;
}
InstructionFactory factory =
il.getDeclaringMethod().getInstructionFactory();
JiapiClass jc = getCurrentClass();
JiapiField field = null;
try {
field = jc.getDeclaredField(fieldName);
}
catch (NoSuchFieldException e) {
throw new JiapiRuntimeException("No such field: " + e.getMessage());
}
// Get the initialized value from Runtime.
il.add(factory.pushConstant(fieldName));
il.add(factory.invoke(getFieldValue));
// Cast the field.
il.add(factory.cast(field.getTypeName()));
// Set the field.
il.add(factory.setField(field));
forward(il);
}
}