1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later, 9 * or the Apache License Version 2.0. 10 * 11 * Software distributed under the License is distributed on an "AS IS" basis, 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 * for the specific language governing rights and limitations under the 14 * License. 15 */ 16 17 package javassist.tools; 18 19 import java.util.HashMap; 20 import java.util.Map; 21 import java.util.UUID; 22 23 import javassist.CannotCompileException; 24 import javassist.CtBehavior; 25 26 /** 27 * Creates bytecode that when executed calls back to the instance's result method. 28 * 29 * <p>Example of how to create and insert a callback:</p> 30 * <pre> 31 * ctMethod.insertAfter(new Callback("Thread.currentThread()") { 32 * public void result(Object[] objects) { 33 * Thread thread = (Thread) objects[0]; 34 * // do something with thread... 35 * } 36 * }.sourceCode()); 37 * </pre> 38 * <p>Contains utility methods for inserts callbacks in <code>CtBehaviour</code>, example:</p> 39 * <pre> 40 * insertAfter(ctBehaviour, new Callback("Thread.currentThread(), dummyString") { 41 * public void result(Object[] objects) { 42 * Thread thread = (Thread) objects[0]; 43 * // do something with thread... 44 * } 45 * }); 46 * </pre> 47 * 48 * @author Marten Hedborg 49 * @author Shigeru Chiba 50 */ 51 public abstract class Callback { 52 53 public static Map<String,Callback> callbacks = new HashMap<String,Callback>(); 54 55 private final String sourceCode; 56 57 /** 58 * Constructs a new <code>Callback</code> object. 59 * 60 * @param src The source code representing the inserted callback bytecode. 61 * Can be one or many single statements each returning one object. 62 * If many single statements are used they must be comma separated. 63 */ Callback(String src)64 public Callback(String src){ 65 String uuid = UUID.randomUUID().toString(); 66 callbacks.put(uuid, this); 67 sourceCode = "((javassist.tools.Callback) javassist.tools.Callback.callbacks.get(\""+uuid+"\")).result(new Object[]{"+src+"});"; 68 } 69 70 /** 71 * Gets called when bytecode is executed 72 * 73 * @param objects Objects that the bytecode in callback returns 74 */ result(Object[] objects)75 public abstract void result(Object[] objects); 76 77 @Override toString()78 public String toString(){ 79 return sourceCode(); 80 } 81 sourceCode()82 public String sourceCode(){ 83 return sourceCode; 84 } 85 86 /** 87 * Utility method to insert callback at the beginning of the body. 88 * 89 * @param callback The callback 90 * 91 * @see CtBehavior#insertBefore(String) 92 */ insertBefore(CtBehavior behavior, Callback callback)93 public static void insertBefore(CtBehavior behavior, Callback callback) 94 throws CannotCompileException 95 { 96 behavior.insertBefore(callback.toString()); 97 } 98 99 /** 100 * Utility method to inserts callback at the end of the body. 101 * The callback is inserted just before every return instruction. 102 * It is not executed when an exception is thrown. 103 * 104 * @param behavior The behaviour to insert callback in 105 * @param callback The callback 106 * 107 * @see CtBehavior#insertAfter(String, boolean) 108 */ insertAfter(CtBehavior behavior,Callback callback)109 public static void insertAfter(CtBehavior behavior,Callback callback) 110 throws CannotCompileException 111 { 112 behavior.insertAfter(callback.toString(), false); 113 } 114 115 /** 116 * Utility method to inserts callback at the end of the body. 117 * The callback is inserted just before every return instruction. 118 * It is not executed when an exception is thrown. 119 * 120 * @param behavior The behaviour to insert callback in 121 * @param callback The callback representing the inserted. 122 * @param asFinally True if the inserted is executed 123 * Not only when the control normally returns 124 * but also when an exception is thrown. 125 * If this parameter is true, the inserted code cannot 126 * access local variables. 127 * 128 * @see CtBehavior#insertAfter(String, boolean) 129 */ insertAfter(CtBehavior behavior, Callback callback, boolean asFinally)130 public static void insertAfter(CtBehavior behavior, Callback callback, boolean asFinally) 131 throws CannotCompileException 132 { 133 behavior.insertAfter(callback.toString(), asFinally); 134 } 135 136 /** 137 * Utility method to inserts callback at the specified line in the body. 138 * 139 * @param behavior The behaviour to insert callback in 140 * @param callback The callback representing. 141 * @param lineNum The line number. The callback is inserted at the 142 * beginning of the code at the line specified by this 143 * line number. 144 * 145 * @return The line number at which the callback has been inserted. 146 * 147 * @see CtBehavior#insertAt(int, String) 148 */ insertAt(CtBehavior behavior, Callback callback, int lineNum)149 public static int insertAt(CtBehavior behavior, Callback callback, int lineNum) 150 throws CannotCompileException 151 { 152 return behavior.insertAt(lineNum, callback.toString()); 153 } 154 } 155