KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2 Copyright (c) 2003-2005, 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.Constants;
32 import org.apache.bcel.classfile.ExceptionTable;
33 import org.apache.bcel.classfile.Method;
34
35 /**
36  * Binding method information. Tracks a method used by the binding code,
37  * supplying hash code and equality checking based on the method signature and
38  * actual byte code of the method, ignoring the method name. This allows
39  * comparisons between methods generated by different bindings, and between
40  * generated and existing methods.
41  *
42  * @author Dennis M. Sosnoski
43  * @version 1.0
44  */

45
46 public abstract class BindingMethod
47 {
48     /** Owning class file information. */
49     private ClassFile m_classFile;
50
51     /**
52      * Constructor.
53      *
54      * @param cf owning class file information
55      */

56
57     protected BindingMethod(ClassFile cf) {
58         m_classFile = cf;
59     }
60
61     /**
62      * Get class file containing method.
63      *
64      * @return class file owning this method
65      */

66
67     public ClassFile getClassFile() {
68         return m_classFile;
69     }
70
71     /**
72      * Get name of method. This abstract method must be implemented by every
73      * subclass.
74      *
75      * @return method name
76      */

77
78     public abstract String JavaDoc getName();
79     
80     /**
81      * Get signature. This abstract method must be implemented by every
82      * subclass.
83      *
84      * @return signature for method
85      */

86      
87     public abstract String JavaDoc getSignature();
88     
89     /**
90      * Get access flags. This abstract method must be implemented by every
91      * subclass.
92      *
93      * @return flags for access type of method
94      */

95      
96     public abstract int getAccessFlags();
97     
98     /**
99      * Set access flags. This abstract method must be implemented by every
100      * subclass.
101      *
102      * @param flags access type to be set
103      */

104      
105     public abstract void setAccessFlags(int flags);
106     
107     /**
108      * Get the actual method.
109      *
110      * @return method information
111      */

112      
113     public abstract Method getMethod();
114     
115     /**
116      * Get the method item.
117      *
118      * @return method item information
119      */

120      
121     public abstract ClassItem getItem();
122
123     /**
124      * Make accessible method. Check if this method is accessible from another
125      * class, and if not decreases the access restrictions to make it
126      * accessible.
127      *
128      * @param src class file for required access
129      */

130
131     public void makeAccessible(ClassFile src) {
132         
133         // no need to change if already public access
134
int access = getAccessFlags();
135         if ((access & Constants.ACC_PUBLIC) == 0) {
136             
137             // check for same package as most restrictive case
138
ClassFile dest = getClassFile();
139             if (dest.getPackage().equals(src.getPackage())) {
140                 if ((access & Constants.ACC_PRIVATE) != 0) {
141                     access = access - Constants.ACC_PRIVATE;
142                 }
143             } else {
144                 
145                 // check if access is from a subclass of this method class
146
ClassFile ancestor = src;
147                 while ((ancestor = ancestor.getSuperFile()) != null) {
148                     if (ancestor == dest) {
149                         break;
150                     }
151                 }
152                 
153                 // handle access adjustments based on subclass status
154
if (ancestor == null) {
155                     int clear = Constants.ACC_PRIVATE |
156                         Constants.ACC_PROTECTED;
157                     access = (access & ~clear) | Constants.ACC_PUBLIC;
158                 } else if ((access & Constants.ACC_PROTECTED) == 0) {
159                     access = (access & ~Constants.ACC_PRIVATE) |
160                         Constants.ACC_PROTECTED;
161                 }
162             }
163             
164             // set new access flags
165
if (access != getAccessFlags()) {
166                 setAccessFlags(access);
167             }
168         }
169     }
170
171     /**
172      * Computes the hash code for a method. The hash code is based on the
173      * method signature, the exceptions thrown, and the actual byte code
174      * (including the exception handlers).
175      *
176      * @return computed hash code for method
177      */

178
179     public static int computeMethodHash(Method method) {
180         int hash = method.getSignature().hashCode();
181         ExceptionTable etab = method.getExceptionTable();
182         if (etab != null) {
183             String JavaDoc[] excepts = etab.getExceptionNames();
184             for (int i = 0; i < excepts.length; i++) {
185                 hash += excepts[i].hashCode();
186             }
187         }
188         byte[] code = method.getCode().getCode();
189         for (int i = 0; i < code.length; i++) {
190             hash = hash * 49 + code[i];
191         }
192         return hash;
193     }
194
195     /**
196      * Get hash code. This abstract method must be implemented by every
197      * subclass, using the same algorithm in each case. See one of the existing
198      * subclasses for details.
199      *
200      * @return hash code for this method
201      */

202
203     public abstract int hashCode();
204
205     /**
206      * Check if objects are equal. Compares first based on hash code, then on
207      * the actual byte code sequence.
208      *
209      * @return <code>true</code> if equal objects, <code>false</code> if not
210      */

211
212     public boolean equals(Object JavaDoc obj) {
213         if (obj instanceof BindingMethod) {
214             BindingMethod comp = (BindingMethod)obj;
215             if (hashCode() == comp.hashCode() &&
216                 getSignature().equals(comp.getSignature())) {
217                 return ClassFile.equalMethods
218                     (this.getMethod(), comp.getMethod());
219             }
220         }
221         return false;
222     }
223 }
224
Popular Tags