KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > DeepSubtypeAnalysis


1 package edu.umd.cs.findbugs;
2
3 import java.util.HashSet JavaDoc;
4 import java.util.Set JavaDoc;
5
6 import org.apache.bcel.Repository;
7 import org.apache.bcel.classfile.JavaClass;
8
9 import edu.umd.cs.findbugs.ba.AnalysisContext;
10 import edu.umd.cs.findbugs.ba.ch.Subtypes;
11
12 public class DeepSubtypeAnalysis {
13     static private JavaClass serializable;
14
15     static private JavaClass collection;
16     static private JavaClass comparator;
17
18     static private JavaClass map;
19     static private JavaClass remote;
20     static private ClassNotFoundException JavaDoc storedException;
21
22     static {
23         try {
24             serializable = AnalysisContext.lookupSystemClass("java.io.Serializable");
25             collection = AnalysisContext.lookupSystemClass("java.util.Collection");
26             map = AnalysisContext.lookupSystemClass("java.util.Map");
27             comparator = AnalysisContext.lookupSystemClass("java.util.Comparator");
28             
29         } catch (ClassNotFoundException JavaDoc e) {
30             storedException = e;
31         }
32         try {
33             remote = AnalysisContext.lookupSystemClass("java.rmi.Remote");
34         } catch (ClassNotFoundException JavaDoc e) {
35             if (storedException == null) storedException = e;
36         }
37     }
38
39     private static boolean containsConcreteClasses(Set JavaDoc<JavaClass> s) {
40         for (JavaClass c : s)
41             if (!c.isInterface() && !c.isAbstract())
42                 return true;
43         return false;
44     }
45
46     public static double isDeepSerializable(String JavaDoc refSig)
47             throws ClassNotFoundException JavaDoc {
48         if (storedException != null)
49             throw storedException;
50
51         if (isPrimitiveComponentClass(refSig))
52             return 1.0;
53         
54         String JavaDoc refName = getComponentClass(refSig);
55         if (refName.equals("java.lang.Object"))
56             return 0.99;
57
58         JavaClass refJavaClass = Repository.lookupClass(refName);
59         return isDeepSerializable(refJavaClass);
60     }
61
62     public static double isDeepRemote(String JavaDoc refSig) {
63         if (remote == null) return 0.1;
64         
65         String JavaDoc refName = getComponentClass(refSig);
66         if (refName.equals("java.lang.Object"))
67             return 0.99;
68
69         JavaClass refJavaClass;
70         try {
71             refJavaClass = Repository.lookupClass(refName);
72             return deepInstanceOf(refJavaClass, remote);
73         } catch (ClassNotFoundException JavaDoc e) {
74             return 0.99;
75         }
76         
77
78     }
79     private static boolean isPrimitiveComponentClass(String JavaDoc refSig) {
80         int c = 0;
81         while (c < refSig.length() && refSig.charAt(c) == '[') {
82             c++;
83         }
84         
85         // If the string is now empty, then we evidently have
86
// an invalid type signature. We'll return "true",
87
// which in turn will cause isDeepSerializable() to return
88
// 1.0, hopefully avoiding any warnings from being generated
89
// by whatever detector is calling us.
90
return c >= refSig.length() || refSig.charAt(c) != 'L';
91     }
92     
93     public static String JavaDoc getComponentClass(String JavaDoc refSig) {
94         while (refSig.charAt(0) == '[')
95             refSig = refSig.substring(1);
96         
97         //TODO: This method now returns primitive type signatures, is this ok?
98
if (refSig.charAt(0) == 'L')
99             return refSig.substring(1, refSig.length() - 1).replace('/', '.');
100         return refSig;
101     }
102
103     public static double isDeepSerializable(JavaClass x)
104             throws ClassNotFoundException JavaDoc {
105         if (storedException != null)
106             throw storedException;
107
108         double result = deepInstanceOf(x, serializable);
109         if (result >= 0.9)
110             return result;
111         result = Math.max(result, deepInstanceOf(x, collection));
112         if (result >= 0.9)
113             return result;
114         result = Math.max(result, deepInstanceOf(x, map));
115         if (result >= 0.9)
116             return result;
117         result = Math.max(result, 0.5*deepInstanceOf(x, comparator));
118         if (result >= 0.9)
119             return result;
120         return result;
121     }
122
123     /**
124      * Given two JavaClasses, try to estimate the probability that an reference
125      * of type x is also an instance of type y. Will return 0 only if it is
126      * impossible and 1 only if it is guaranteed.
127      *
128      * @param x
129      * Known type of object
130      * @param y
131      * Type queried about
132      * @return 0 - 1 value indicating probablility
133      */

134
135     public static double deepInstanceOf(String JavaDoc x, String JavaDoc y)
136     throws ClassNotFoundException JavaDoc {
137         return deepInstanceOf(AnalysisContext.currentAnalysisContext().lookupClass(x),
138                 AnalysisContext.currentAnalysisContext().lookupClass(y));
139     }
140
141     /**
142      * Given two JavaClasses, try to estimate the probability that an reference
143      * of type x is also an instance of type y. Will return 0 only if it is
144      * impossible and 1 only if it is guaranteed.
145      *
146      * @param x
147      * Known type of object
148      * @param y
149      * Type queried about
150      * @return 0 - 1 value indicating probablility
151      */

152     public static double deepInstanceOf(JavaClass x, JavaClass y)
153             throws ClassNotFoundException JavaDoc {
154
155         if (x.equals(y))
156             return 1.0;
157         boolean xIsSubtypeOfY = Repository.instanceOf(x, y);
158         if (xIsSubtypeOfY)
159             return 1.0;
160         boolean yIsSubtypeOfX = Repository.instanceOf(y, x);
161         if (!yIsSubtypeOfX) {
162             if (x.isFinal() || y.isFinal())
163                 return 0.0;
164             if (!x.isInterface() && !y.isInterface())
165                 return 0.0;
166         }
167
168         Subtypes subtypes = AnalysisContext.currentAnalysisContext()
169                 .getSubtypes();
170         subtypes.addClass(x);
171         subtypes.addClass(y);
172
173         Set JavaDoc<JavaClass> xSubtypes = subtypes.getTransitiveSubtypes(x);
174
175         Set JavaDoc<JavaClass> ySubtypes = subtypes.getTransitiveSubtypes(y);
176
177         boolean emptyIntersection = true;
178         
179         boolean concreteClassesInXButNotY = false;
180         for(JavaClass s : xSubtypes) {
181             if (ySubtypes.contains(s)) emptyIntersection = false;
182             else if (!s.isInterface() && !s.isAbstract())
183                 concreteClassesInXButNotY = true;
184         }
185
186         
187         if (emptyIntersection) {
188             if (concreteClassesInXButNotY) {
189                 if (x.isAbstract() || x.isInterface()) return 0.2;
190                 return 0.1;
191             }
192             return 0.3;
193         }
194
195         // exist classes that are both X and Y
196

197         if (!concreteClassesInXButNotY) {
198             // only abstract/interfaces that are X but not Y
199
return 0.99;
200         }
201
202         // Concrete classes in X but not Y
203
return 0.7;
204
205     }
206 }
207
Popular Tags