public int compare(Object o1, Object o2) { RefType t1 = baseType(o1); RefType t2 = baseType(o2); if (t1.equals(t2)) { // There should never be both AnySubType(t) and // t in a ThrowableSet, but if it happens, put // AnySubType(t) first: if (o1 instanceof AnySubType) { if (o2 instanceof AnySubType) { return 0; } else { return -1; } } else if (o2 instanceof AnySubType) { return 1; } else { return 0; } } else { return t1.toString().compareTo(t2.toString()); } }
/** * Utility method which prints the abbreviations of the elements in a passed {@link Set} of * exception types. * * @param s The exceptions to print. * @param connector The character to insert between exceptions. * @return An abbreviated representation of the exceptions. */ private String toAbbreviatedString(Set s, char connector) { final String JAVA_LANG = "java.lang."; final int JAVA_LANG_LENGTH = JAVA_LANG.length(); final String EXCEPTION = "Exception"; final int EXCEPTION_LENGTH = EXCEPTION.length(); Collection vmErrorThrowables = ThrowableSet.Manager.v().VM_ERRORS.exceptionsIncluded; boolean containsAllVmErrors = s.containsAll(vmErrorThrowables); StringBuffer buf = new StringBuffer(); if (containsAllVmErrors) { buf.append(connector); buf.append("vmErrors"); } for (Iterator it = sortedThrowableIterator(s); it.hasNext(); ) { RefLikeType reflikeType = (RefLikeType) it.next(); RefType baseType = null; if (reflikeType instanceof RefType) { baseType = (RefType) reflikeType; if (vmErrorThrowables.contains(baseType) && containsAllVmErrors) { continue; // Already accounted for vmErrors. } else { buf.append(connector); } } else if (reflikeType instanceof AnySubType) { buf.append(connector); buf.append('('); baseType = ((AnySubType) reflikeType).getBase(); } String typeName = baseType.toString(); if (typeName.startsWith(JAVA_LANG)) { typeName = typeName.substring(JAVA_LANG_LENGTH); } if (typeName.length() > EXCEPTION_LENGTH && typeName.endsWith(EXCEPTION)) { typeName = typeName.substring(0, typeName.length() - EXCEPTION_LENGTH); } buf.append(typeName); if (reflikeType instanceof AnySubType) { buf.append(')'); } } return buf.toString(); }
/** * Returns a <code>ThrowableSet</code> which contains <code>e</code> and all of its subclasses as * well as the exceptions in this set. * * <p><code>e</code> should be an instance of {@link AnySubType} if you know that the compile-time * type of the exception you are representing is <code>e</code>, but the exception may be * instantiated at run-time by a subclass of <code>e</code>. * * <p>For example, if you were recording the type of the exception thrown by * * <pre> * catch (IOException e) { * throw e; * } * </pre> * * you would call * * <pre> * <code>add(AnySubtype.v(Scene.v().getRefType("java.lang.Exception.IOException")))</code> * </pre> * * since the handler might rethrow any subclass of <code>IOException</code>. * * @param e represents a subtree of the exception class hierarchy to add to this set. * @return a set containing <code>e</code> and all its subclasses, as well as the exceptions * represented by this set. * @throws ThrowableSet.AlreadyHasExclusionsException if this <code>ThrowableSet</code> is the * result of a {@link #whichCatchableAs(RefType)} operation and, thus, unable to represent the * addition of <code>e</code>. */ public ThrowableSet add(AnySubType e) throws ThrowableSet.AlreadyHasExclusionsException { if (INSTRUMENTING) { Manager.v().addsOfAnySubType++; } ThrowableSet result = getMemoizedAdds(e); if (result != null) { if (INSTRUMENTING) { Manager.v().addsInclusionFromMemo++; Manager.v().addsExclusionWithoutSearch++; } return result; } else { FastHierarchy hierarchy = Scene.v().getOrMakeFastHierarchy(); RefType newBase = e.getBase(); if (INSTRUMENTING) { if (exceptionsExcluded.size() != 0) { Manager.v().addsExclusionWithSearch++; } else { Manager.v().addsExclusionWithoutSearch++; } } for (Iterator i = exceptionsExcluded.iterator(); i.hasNext(); ) { RefType exclusionBase = ((AnySubType) i.next()).getBase(); if (hierarchy.canStoreType(newBase, exclusionBase) || hierarchy.canStoreType(exclusionBase, newBase)) { if (INSTRUMENTING) { // To ensure that the subcategories total properly: Manager.v().addsInclusionInterrupted++; } throw new AlreadyHasExclusionsException( "ThrowableSet.add(" + e.toString() + ") to the set [ " + this.toString() + "] where " + exclusionBase.toString() + " is excluded."); } } if (this.exceptionsIncluded.contains(e)) { if (INSTRUMENTING) { Manager.v().addsInclusionFromMap++; } return this; } else { if (INSTRUMENTING) { Manager.v().addsInclusionFromSearch++; } int changes = 0; boolean addNewException = true; Set resultSet = new HashSet(); for (Iterator i = this.exceptionsIncluded.iterator(); i.hasNext(); ) { RefLikeType incumbent = (RefLikeType) i.next(); if (incumbent instanceof RefType) { if (hierarchy.canStoreType(incumbent, newBase)) { // Omit incumbent from result. changes++; } else { resultSet.add(incumbent); } } else if (incumbent instanceof AnySubType) { RefType incumbentBase = ((AnySubType) incumbent).getBase(); // We have to use the base types in these hierarchy calls // because we want to know if _all_ possible // types represented by e can be represented by // the incumbent, or vice versa. if (hierarchy.canStoreType(newBase, incumbentBase)) { addNewException = false; resultSet.add(incumbent); } else if (hierarchy.canStoreType(incumbentBase, newBase)) { // Omit incumbent from result; changes++; } else { resultSet.add(incumbent); } } else { // assertion failure. throw new IllegalStateException( "ThrowableSet.add(AnySubType): Set element " + incumbent.toString() + " is neither a RefType nor an AnySubType."); } } if (addNewException) { resultSet.add(e); changes++; } if (changes > 0) { result = Manager.v().registerSetIfNew(resultSet, this.exceptionsExcluded); } else { result = this; } memoizedAdds.put(e, result); return result; } } }
/** * Returns a <code>ThrowableSet</code> which contains <code>e</code> in addition to the exceptions * in this <code>ThrowableSet</code>. * * <p>Add <code>e</code> as a {@link RefType} when you know that the run-time class of the * exception you are representing is necessarily <code>e</code> and cannot be a subclass of <code> * e</code>. * * <p>For example, if you were recording the type of the exception thrown by * * <pre> * throw new IOException("Permission denied"); * </pre> * * you would call * * <pre> * <code>add(Scene.v().getRefType("java.lang.Exception.IOException"))</code> * </pre> * * since the class of the exception is necessarily <code>IOException</code>. * * @param e the exception class * @return a set containing <code>e</code> as well as the exceptions in this set. * @throws {@link ThrowableSet.IllegalStateException} if this <code>ThrowableSet</code> is the * result of a {@link #whichCatchableAs(RefType)} operation and, thus, unable to represent the * addition of <code>e</code>. */ public ThrowableSet add(RefType e) throws ThrowableSet.AlreadyHasExclusionsException { if (INSTRUMENTING) { Manager.v().addsOfRefType++; } if (this.exceptionsIncluded.contains(e)) { if (INSTRUMENTING) { Manager.v().addsInclusionFromMap++; Manager.v().addsExclusionWithoutSearch++; } return this; } else { ThrowableSet result = getMemoizedAdds(e); if (result != null) { if (INSTRUMENTING) { Manager.v().addsInclusionFromMemo++; Manager.v().addsExclusionWithoutSearch++; } return result; } else { if (INSTRUMENTING) { Manager.v().addsInclusionFromSearch++; if (exceptionsExcluded.size() != 0) { Manager.v().addsExclusionWithSearch++; } else { Manager.v().addsExclusionWithoutSearch++; } } FastHierarchy hierarchy = Scene.v().getOrMakeFastHierarchy(); for (Iterator i = exceptionsExcluded.iterator(); i.hasNext(); ) { RefType exclusionBase = ((AnySubType) i.next()).getBase(); if (hierarchy.canStoreType(e, exclusionBase)) { throw new AlreadyHasExclusionsException( "ThrowableSet.add(RefType): adding" + e.toString() + " to the set [ " + this.toString() + "] where " + exclusionBase.toString() + " is excluded."); } } for (Iterator i = exceptionsIncluded.iterator(); i.hasNext(); ) { RefLikeType incumbent = (RefLikeType) i.next(); if (incumbent instanceof AnySubType) { // Need to use incumbent.getBase() because // hierarchy.canStoreType() assumes that parent // is not an AnySubType. RefType incumbentBase = ((AnySubType) incumbent).getBase(); if (hierarchy.canStoreType(e, incumbentBase)) { memoizedAdds.put(e, this); return this; } } else if (!(incumbent instanceof RefType)) { // assertion failure. throw new IllegalStateException( "ThrowableSet.add(RefType): Set element " + incumbent.toString() + " is neither a RefType nor an AnySubType."); } } Set resultSet = new HashSet(this.exceptionsIncluded); resultSet.add(e); result = Manager.v().registerSetIfNew(resultSet, this.exceptionsExcluded); memoizedAdds.put(e, result); return result; } } }