KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > type > ExceptionSet


1 /*
2  * Bytecode Analysis Framework
3  * Copyright (C) 2004 University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.ba.type;
21
22 import java.io.Serializable JavaDoc;
23 import java.util.BitSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.NoSuchElementException JavaDoc;
26
27 import org.apache.bcel.generic.ObjectType;
28 import org.apache.bcel.generic.ReferenceType;
29 import org.apache.bcel.generic.Type;
30
31 import edu.umd.cs.findbugs.ba.Hierarchy;
32
33 /**
34  * Class for keeping track of exceptions that can be
35  * thrown by an instruction. We distinguish <em>explicit</em>
36  * and <em>implicit</em> exceptions. Explicit exceptions
37  * are explicitly declared, thrown, or caught. Implicit exceptions
38  * are runtime faults (NPE, array out of bounds)
39  * not explicitly handled by the user code.
40  *
41  * @author David Hovemeyer
42  * @see TypeAnalysis
43  */

44 public class ExceptionSet implements Serializable JavaDoc {
45         private static final long serialVersionUID = 1;
46
47     private ExceptionSetFactory factory;
48     private BitSet JavaDoc exceptionSet;
49     private BitSet JavaDoc explicitSet;
50     private int size;
51     private boolean universalHandler;
52     private Type commonSupertype;
53
54     /**
55      * Object to iterate over the exception types in the set.
56      */

57     public class ThrownExceptionIterator implements Iterator JavaDoc<ObjectType> {
58         private int last = -1, next = -1;
59
60         ThrownExceptionIterator() {
61             findNext();
62         }
63
64         public boolean hasNext() {
65             if (last == next)
66                 findNext();
67             return next < factory.getNumTypes();
68         }
69
70         public ObjectType next() {
71             if (!hasNext())
72                 throw new NoSuchElementException JavaDoc();
73             ObjectType result = factory.getType(next);
74             last = next;
75             return result;
76         }
77
78         public boolean isExplicit() {
79             return explicitSet.get(last);
80         }
81
82         public void remove() {
83             exceptionSet.clear(last);
84             explicitSet.clear(last);
85             --size;
86             commonSupertype = null;
87         }
88
89         private void findNext() {
90             ++next;
91             while (next < factory.getNumTypes()) {
92                 if (exceptionSet.get(next))
93                     break;
94                 ++next;
95             }
96         }
97     }
98
99     /**
100      * Constructor.
101      * Creates an empty set.
102      */

103     ExceptionSet(ExceptionSetFactory factory) {
104         this.factory = factory;
105         this.exceptionSet = new BitSet JavaDoc();
106         this.explicitSet = new BitSet JavaDoc();
107         this.size = 0;
108         this.universalHandler = false;
109     }
110
111     /**
112      * Return an exact copy of this object.
113      */

114     public ExceptionSet duplicate() {
115         ExceptionSet dup = factory.createExceptionSet();
116         dup.exceptionSet.clear();
117         dup.exceptionSet.or(this.exceptionSet);
118         dup.explicitSet.clear();
119         dup.explicitSet.or(this.explicitSet);
120         dup.size = this.size;
121         dup.universalHandler = this.universalHandler;
122         dup.commonSupertype = this.commonSupertype;
123
124         return dup;
125     }
126
127     @Override JavaDoc
128          public int hashCode() {
129         return exceptionSet.hashCode() + explicitSet.hashCode();
130     }
131
132     @Override JavaDoc
133          public boolean equals(Object JavaDoc o) {
134         if (o == null) return false;
135         if (o.getClass() != this.getClass()) return false;
136
137         ExceptionSet other = (ExceptionSet) o;
138         return exceptionSet.equals(other.exceptionSet)
139                 && explicitSet.equals(other.explicitSet)
140                 && universalHandler == other.universalHandler;
141     }
142
143     /**
144      * Get the least (lowest in the lattice) common supertype
145      * of the exceptions in the set. Returns the special TOP
146      * type if the set is empty.
147      */

148     public Type getCommonSupertype() throws ClassNotFoundException JavaDoc {
149         if (commonSupertype != null)
150             return commonSupertype;
151
152         if (isEmpty()) {
153             // This probably means that we're looking at an
154
// infeasible exception path.
155
return TypeFrame.getTopType();
156         }
157
158         // Compute first common superclass
159
ThrownExceptionIterator i = iterator();
160         ReferenceType result = i.next();
161         while (i.hasNext()) {
162             result = result.getFirstCommonSuperclass(i.next());
163             if (result == null) {
164                 // This should only happen if the class hierarchy
165
// is incomplete. We'll just be conservative.
166
result = Type.THROWABLE;
167                 break;
168             }
169         }
170
171         // Cache and return the result
172
commonSupertype = result;
173         return result;
174     }
175
176     /**
177      * Return an iterator over thrown exceptions.
178      */

179     public ThrownExceptionIterator iterator() {
180         return new ThrownExceptionIterator();
181     }
182
183     /**
184      * Return whether or not the set is empty.
185      */

186     public boolean isEmpty() {
187         return size == 0;
188     }
189
190     /**
191      * Checks to see if the exception set is a singleton set
192      * containing just the named exception
193      * @param exceptionName (in dotted format)
194      * @return true if it is
195      */

196     public boolean isSingleton(String JavaDoc exceptionName) {
197         if (size != 1) return false;
198         ObjectType e = iterator().next();
199         return e.toString().equals(exceptionName);
200         
201     }
202     /**
203      * Add an explicit exception.
204      *
205      * @param type type of the exception
206      */

207     public void addExplicit(ObjectType type) {
208         add(type, true);
209     }
210
211     /**
212      * Add an implicit exception.
213      *
214      * @param type type of the exception
215      */

216     public void addImplicit(ObjectType type) {
217         add(type, false);
218     }
219
220     /**
221      * Add an exception.
222      *
223      * @param type the exception type
224      * @param explicit true if the exception is explicitly declared
225      * or thrown, false if implicit
226      */

227     public void add(ObjectType type, boolean explicit) {
228         int index = factory.getIndexOfType(type);
229         if (!exceptionSet.get(index))
230             ++size;
231         exceptionSet.set(index);
232         if (explicit)
233             explicitSet.set(index);
234
235         commonSupertype = null;
236     }
237
238     /**
239      * Add all exceptions in the given set.
240      *
241      * @param other the set
242      */

243     public void addAll(ExceptionSet other) {
244         exceptionSet.or(other.exceptionSet);
245         explicitSet.or(other.explicitSet);
246         size = countBits(exceptionSet);
247
248         commonSupertype = null;
249     }
250
251     private int countBits(BitSet JavaDoc bitSet) {
252         int count = 0;
253         for (int i = 0; i < factory.getNumTypes(); ++i) {
254             if (bitSet.get(i))
255                 ++count;
256         }
257         return count;
258     }
259
260     /**
261      * Remove all exceptions from the set.
262      */

263     public void clear() {
264         exceptionSet.clear();
265         explicitSet.clear();
266         universalHandler = false;
267         commonSupertype = null;
268     }
269
270     /**
271      * Return whether or not a universal exception handler
272      * was reached by the set.
273      */

274     public void sawUniversal() {
275         clear();
276         universalHandler = true;
277     }
278
279     /**
280      * Mark the set as having reached a universal exception handler.
281      */

282     public boolean sawUniversalHandler() {
283         return universalHandler;
284     }
285
286     /**
287      * Return whether or not the set contains any checked exceptions.
288      */

289     public boolean containsCheckedExceptions() throws ClassNotFoundException JavaDoc {
290         for (ThrownExceptionIterator i = iterator(); i.hasNext();) {
291             ObjectType type = i.next();
292             if (!Hierarchy.isUncheckedException(type))
293                 return true;
294         }
295         return false;
296     }
297
298     /**
299      * Return whether or not the set contains any explicit exceptions.
300      */

301     public boolean containsExplicitExceptions() {
302         for (ThrownExceptionIterator i = iterator(); i.hasNext();) {
303             i.next();
304             if (i.isExplicit())
305                 return true;
306         }
307         return false;
308     }
309
310     @Override JavaDoc
311          public String JavaDoc toString() {
312         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
313         buf.append('{');
314         boolean first = true;
315         for (ThrownExceptionIterator i = iterator(); i.hasNext();) {
316             ObjectType type = i.next();
317             if (first)
318                 first = false;
319             else
320                 buf.append(',');
321             boolean implicit = !i.isExplicit();
322             if (implicit) buf.append('[');
323             buf.append(type.toString());
324             if (implicit) buf.append(']');
325         }
326         buf.append('}');
327         return buf.toString();
328     }
329 }
330
331 // vim:ts=4
332
Popular Tags