• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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