KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > binding > classes > BranchWrapper


1 /*
2 Copyright (c) 2004, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.binding.classes;
30
31 import org.apache.bcel.generic.BranchHandle;
32 import org.apache.bcel.generic.InstructionHandle;
33
34 /**
35  * Wrapper for branch handle. This preserves a snapshot of the stack state for
36  * the branch instruction, matching it against the stack state for the target
37  * instruction when set.
38  *
39  * @author Dennis M. Sosnoski
40  * @version 1.0
41  */

42
43 public class BranchWrapper
44 {
45     /** Track source code location for generated branches. */
46     private static boolean s_trackSource;
47     
48     /** Continue on after code generation error flag. */
49     private static boolean s_errorOverride;
50     
51     /** Actual wrapped instruction handle. */
52     private final BranchHandle m_branchHandle;
53     
54     /** Stack state for branch origin. */
55     private final String JavaDoc[] m_stackTypes;
56     
57     /** Object that generated branch. */
58     private final Object JavaDoc m_sourceObject;
59     
60     /** Code generation backtrace for source of branch. */
61     private final Throwable JavaDoc m_sourceTrace;
62
63     /**
64      * Constructor.
65      *
66      * @param hand branch handle
67      * @param types array of types of values on stack
68      * @param src object responsible for generating branch
69      */

70
71     /*package*/ BranchWrapper(BranchHandle hand, String JavaDoc[] types, Object JavaDoc src) {
72         m_branchHandle = hand;
73         m_stackTypes = types;
74         m_sourceObject = src;
75         if (s_trackSource) {
76             m_sourceTrace = new Throwable JavaDoc();
77         } else {
78             m_sourceTrace = null;
79         }
80     }
81     
82     /**
83      * Get branch origin stack state information.
84      *
85      * @return array of types of values on stack
86      */

87      
88     /*package*/ String JavaDoc[] getStackState() {
89         return m_stackTypes;
90     }
91     
92     /**
93      * Generate description of stack state.
94      *
95      * @param types array of types on stack
96      * @return stack state description
97      */

98      
99     private String JavaDoc describeStack(String JavaDoc[] types) {
100         StringBuffer JavaDoc buff = new StringBuffer JavaDoc();
101         for (int i = 0; i < types.length; i++) {
102             buff.append(" ");
103             buff.append(i);
104             buff.append(": ");
105             buff.append(types[i]);
106             buff.append('\n');
107         }
108         return buff.toString();
109     }
110     
111     /**
112      * Report branch target error. Dumps the stack trace for the source of the
113      * branch, if source tracking is enabled, and generates an exception that
114      * includes the stack state information.
115      *
116      * @param text basic error message text
117      * @param types stack state description
118      * @param mb method builder using this code
119      * @return complete error description text
120      */

121      
122     private String JavaDoc buildReport(String JavaDoc text, String JavaDoc[] types, MethodBuilder mb) {
123         
124         // start by dumping branch generation source trace
125
if (m_sourceTrace != null) {
126             System.err.println("Backtrack for branch source:");
127             m_sourceTrace.printStackTrace(System.err);
128         }
129         
130         // generate error message leading text
131
StringBuffer JavaDoc buff = new StringBuffer JavaDoc(text);
132         buff.append("\n in method ");
133         buff.append(mb.getClassFile().getName());
134         buff.append('.');
135         buff.append(mb.getName());
136         buff.append("\n generated by ");
137         buff.append(m_sourceObject.toString());
138         buff.append("\n from stack:\n");
139         buff.append(describeStack(m_stackTypes));
140         buff.append(" to stack:\n");
141         buff.append(describeStack(types));
142         return buff.toString();
143     }
144     
145     /**
146      * Set target instruction for branch. Validates the branch source stack
147      * state against the branch target stack state.
148      *
149      * @param hand target branch instruction handle
150      * @param types stack state description
151      * @param mb method builder using this code
152      */

153      
154     /*package*/ void setTarget(InstructionHandle hand, String JavaDoc[] types,
155         MethodBuilder mb) {
156         
157         // match stack states
158
if (types.length == m_stackTypes.length) {
159             boolean match = true;
160             for (int i = 0; i < types.length; i++) {
161                 String JavaDoc stype = m_stackTypes[i];
162                 if (!types[i].equals(stype)) {
163                     if (!"<null>".equals(types[i]) && !"<null>".equals(stype)) {
164                         if (m_sourceTrace != null) {
165                             System.err.println("Backtrack for branch source:");
166                             m_sourceTrace.printStackTrace(System.err);
167                         }
168                         String JavaDoc text = buildReport
169                             ("Stack value type mismatch on branch", types, mb);
170                         if (s_errorOverride) {
171                             new Throwable JavaDoc(text).printStackTrace(System.err);
172                         } else {
173                             throw new IllegalStateException JavaDoc(text);
174                         }
175                     }
176                 }
177             }
178         } else {
179             String JavaDoc text =
180                 buildReport("Stack size mismatch on branch", types, mb);
181             if (s_errorOverride) {
182                 new Throwable JavaDoc(text).printStackTrace(System.err);
183             } else {
184                 throw new IllegalStateException JavaDoc(text);
185             }
186         }
187         
188         // set the branch target
189
m_branchHandle.setTarget(hand);
190     }
191     
192     /**
193      * Set target instruction for branch. Validates the branch source stack
194      * state against the branch target stack state.
195      *
196      * @param target branch target wrapper
197      * @param mb method builder using this code
198      */

199      
200     public void setTarget(BranchTarget target, MethodBuilder mb) {
201         setTarget(target.getInstruction(), target.getStack(), mb);
202     }
203     
204     /**
205      * Set branch code generation tracking state. When set, this saves a stack
206      * trace for each generated branch instruction, allowing the source of a
207      * branch to be traced when an error occurs in setting the branch target.
208      *
209      * @param track <code>true</code> to enable branch code generation tracking,
210      * <code>false</code> to disable it
211      */

212      
213     public static void setTracking(boolean track) {
214         s_trackSource = track;
215     }
216     
217     /**
218      * Set target setting error override state. When set, this blocks throwing
219      * an exception when an error occurs on setting the branch target, instead
220      * just printing the information to the console.
221      *
222      * @param over <code>true</code> to override exception on target error,
223      * <code>false</code> to allow it
224      */

225      
226     public static void setErrorOverride(boolean over) {
227         s_errorOverride = over;
228     }
229 }
Popular Tags