1 19 20 package edu.umd.cs.findbugs.ba.type; 21 22 import java.io.Serializable ; 23 import java.util.BitSet ; 24 import java.util.Iterator ; 25 import java.util.NoSuchElementException ; 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 44 public class ExceptionSet implements Serializable { 45 private static final long serialVersionUID = 1; 46 47 private ExceptionSetFactory factory; 48 private BitSet exceptionSet; 49 private BitSet explicitSet; 50 private int size; 51 private boolean universalHandler; 52 private Type commonSupertype; 53 54 57 public class ThrownExceptionIterator implements Iterator <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 (); 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 103 ExceptionSet(ExceptionSetFactory factory) { 104 this.factory = factory; 105 this.exceptionSet = new BitSet (); 106 this.explicitSet = new BitSet (); 107 this.size = 0; 108 this.universalHandler = false; 109 } 110 111 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 128 public int hashCode() { 129 return exceptionSet.hashCode() + explicitSet.hashCode(); 130 } 131 132 @Override 133 public boolean equals(Object 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 148 public Type getCommonSupertype() throws ClassNotFoundException { 149 if (commonSupertype != null) 150 return commonSupertype; 151 152 if (isEmpty()) { 153 return TypeFrame.getTopType(); 156 } 157 158 ThrownExceptionIterator i = iterator(); 160 ReferenceType result = i.next(); 161 while (i.hasNext()) { 162 result = result.getFirstCommonSuperclass(i.next()); 163 if (result == null) { 164 result = Type.THROWABLE; 167 break; 168 } 169 } 170 171 commonSupertype = result; 173 return result; 174 } 175 176 179 public ThrownExceptionIterator iterator() { 180 return new ThrownExceptionIterator(); 181 } 182 183 186 public boolean isEmpty() { 187 return size == 0; 188 } 189 190 196 public boolean isSingleton(String exceptionName) { 197 if (size != 1) return false; 198 ObjectType e = iterator().next(); 199 return e.toString().equals(exceptionName); 200 201 } 202 207 public void addExplicit(ObjectType type) { 208 add(type, true); 209 } 210 211 216 public void addImplicit(ObjectType type) { 217 add(type, false); 218 } 219 220 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 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 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 263 public void clear() { 264 exceptionSet.clear(); 265 explicitSet.clear(); 266 universalHandler = false; 267 commonSupertype = null; 268 } 269 270 274 public void sawUniversal() { 275 clear(); 276 universalHandler = true; 277 } 278 279 282 public boolean sawUniversalHandler() { 283 return universalHandler; 284 } 285 286 289 public boolean containsCheckedExceptions() throws ClassNotFoundException { 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 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 311 public String toString() { 312 StringBuffer buf = new StringBuffer (); 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 | Popular Tags |