001: package soot.toolkits.exceptions;
002:
003: import soot.*;
004: import java.util.*;
005:
006: /**
007: * Class which packages together some objects useful in
008: * unit tests of exception handling.
009: */
010: public class ExceptionTestUtility {
011:
012: // Individual Throwable types for our tests:
013: final RefType THROWABLE;
014: final RefType EXCEPTION;
015: final RefType RUNTIME_EXCEPTION;
016: final RefType ARITHMETIC_EXCEPTION;
017: final RefType ARRAY_STORE_EXCEPTION;
018: final RefType CLASS_CAST_EXCEPTION;
019: final RefType ILLEGAL_MONITOR_STATE_EXCEPTION;
020: final RefType INDEX_OUT_OF_BOUNDS_EXCEPTION;
021: final RefType ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION;
022: final RefType STRING_INDEX_OUT_OF_BOUNDS_EXCEPTION;
023: final RefType NEGATIVE_ARRAY_SIZE_EXCEPTION;
024: final RefType NULL_POINTER_EXCEPTION;
025: final RefType ERROR;
026: final RefType LINKAGE_ERROR;
027: final RefType CLASS_CIRCULARITY_ERROR;
028: final RefType CLASS_FORMAT_ERROR;
029: final RefType UNSUPPORTED_CLASS_VERSION_ERROR;
030: final RefType EXCEPTION_IN_INITIALIZER_ERROR;
031: final RefType INCOMPATIBLE_CLASS_CHANGE_ERROR;
032: final RefType ABSTRACT_METHOD_ERROR;
033: final RefType ILLEGAL_ACCESS_ERROR;
034: final RefType INSTANTIATION_ERROR;
035: final RefType NO_SUCH_FIELD_ERROR;
036: final RefType NO_SUCH_METHOD_ERROR;
037: final RefType NO_CLASS_DEF_FOUND_ERROR;
038: final RefType UNSATISFIED_LINK_ERROR;
039: final RefType VERIFY_ERROR;
040: final RefType THREAD_DEATH;
041: final RefType VIRTUAL_MACHINE_ERROR;
042: final RefType INTERNAL_ERROR;
043: final RefType OUT_OF_MEMORY_ERROR;
044: final RefType STACK_OVERFLOW_ERROR;
045: final RefType UNKNOWN_ERROR;
046: final RefType AWT_ERROR;
047: final RefType UNDECLARED_THROWABLE_EXCEPTION;
048: final RefType UNSUPPORTED_LOOK_AND_FEEL_EXCEPTION;
049:
050: // The universe of all Throwable types for our tests:
051: final Set ALL_TEST_THROWABLES;
052:
053: // Set that matches the representation of all Throwables used
054: // internally by ThrowableSet:
055: final Set ALL_THROWABLES_REP;
056:
057: // Some useful subsets of our Throwable universe:
058: final Set VM_ERRORS;
059: final Set VM_ERRORS_PLUS_SUPERTYPES;
060: final Set VM_AND_RESOLVE_CLASS_ERRORS;
061: final Set VM_AND_RESOLVE_CLASS_ERRORS_PLUS_SUPERTYPES;
062: final Set VM_AND_RESOLVE_FIELD_ERRORS;
063: final Set VM_AND_RESOLVE_FIELD_ERRORS_PLUS_SUPERTYPES;
064: final Set VM_AND_RESOLVE_METHOD_ERRORS;
065: final Set VM_AND_RESOLVE_METHOD_ERRORS_PLUS_SUPERTYPES;
066: final Set ALL_TEST_ERRORS;
067: final Set ALL_TEST_ERRORS_PLUS_SUPERTYPES;
068: final Set PERENNIAL_THROW_EXCEPTIONS;
069: final Set PERENNIAL_THROW_EXCEPTIONS_PLUS_SUPERTYPES;
070: final Set THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE;
071: final Set THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUPERTYPES;
072: final Set THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUBTYPES;
073: final Set THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUBTYPES_PLUS_SUPERTYPES;
074:
075: // Sets that match the representations of subsets of Errors used
076: // internally by ThrowableSet:
077: final Set VM_AND_RESOLVE_CLASS_ERRORS_REP;
078: final Set VM_AND_RESOLVE_FIELD_ERRORS_REP;
079: final Set VM_AND_RESOLVE_METHOD_ERRORS_REP;
080: final Set ALL_ERRORS_REP;
081:
082: ExceptionTestUtility(String pathToJavaLib) {
083: Scene.v().setSootClassPath(pathToJavaLib);
084:
085: THROWABLE = Scene.v().getRefType("java.lang.Throwable");
086:
087: ERROR = Scene.v().getRefType("java.lang.Error");
088:
089: Scene.v().loadClassAndSupport("java.lang.Exception");
090: EXCEPTION = Scene.v().getRefType("java.lang.Exception");
091:
092: // runtime exceptions.
093: RUNTIME_EXCEPTION = Scene.v().getRefType(
094: "java.lang.RuntimeException");
095:
096: ARITHMETIC_EXCEPTION = Scene.v().getRefType(
097: "java.lang.ArithmeticException");
098:
099: ARRAY_STORE_EXCEPTION = Scene.v().getRefType(
100: "java.lang.ArrayStoreException");
101:
102: CLASS_CAST_EXCEPTION = Scene.v().getRefType(
103: "java.lang.ClassCastException");
104:
105: ILLEGAL_MONITOR_STATE_EXCEPTION = Scene.v().getRefType(
106: "java.lang.IllegalMonitorStateException");
107:
108: INDEX_OUT_OF_BOUNDS_EXCEPTION = Scene.v().getRefType(
109: "java.lang.IndexOutOfBoundsException");
110:
111: ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = Scene.v().getRefType(
112: "java.lang.ArrayIndexOutOfBoundsException");
113:
114: Scene.v().loadClassAndSupport(
115: "java.lang.StringIndexOutOfBoundsException");
116: STRING_INDEX_OUT_OF_BOUNDS_EXCEPTION = Scene.v().getRefType(
117: "java.lang.StringIndexOutOfBoundsException");
118:
119: NEGATIVE_ARRAY_SIZE_EXCEPTION = Scene.v().getRefType(
120: "java.lang.NegativeArraySizeException");
121:
122: NULL_POINTER_EXCEPTION = Scene.v().getRefType(
123: "java.lang.NullPointerException");
124:
125: // linkage errors.
126: LINKAGE_ERROR = Scene.v().getRefType("java.lang.LinkageError");
127:
128: CLASS_CIRCULARITY_ERROR = Scene.v().getRefType(
129: "java.lang.ClassCircularityError");
130:
131: CLASS_FORMAT_ERROR = Scene.v().getRefType(
132: "java.lang.ClassFormatError");
133:
134: Scene.v().loadClassAndSupport(
135: "java.lang.UnsupportedClassVersionError");
136: UNSUPPORTED_CLASS_VERSION_ERROR = Scene.v().getRefType(
137: "java.lang.UnsupportedClassVersionError");
138:
139: EXCEPTION_IN_INITIALIZER_ERROR = Scene.v().getRefType(
140: "java.lang.ExceptionInInitializerError");
141:
142: INCOMPATIBLE_CLASS_CHANGE_ERROR = Scene.v().getRefType(
143: "java.lang.IncompatibleClassChangeError");
144:
145: ABSTRACT_METHOD_ERROR = Scene.v().getRefType(
146: "java.lang.AbstractMethodError");
147:
148: ILLEGAL_ACCESS_ERROR = Scene.v().getRefType(
149: "java.lang.IllegalAccessError");
150:
151: INSTANTIATION_ERROR = Scene.v().getRefType(
152: "java.lang.InstantiationError");
153:
154: NO_SUCH_FIELD_ERROR = Scene.v().getRefType(
155: "java.lang.NoSuchFieldError");
156:
157: NO_SUCH_METHOD_ERROR = Scene.v().getRefType(
158: "java.lang.NoSuchMethodError");
159:
160: NO_CLASS_DEF_FOUND_ERROR = Scene.v().getRefType(
161: "java.lang.NoClassDefFoundError");
162:
163: UNSATISFIED_LINK_ERROR = Scene.v().getRefType(
164: "java.lang.UnsatisfiedLinkError");
165:
166: VERIFY_ERROR = Scene.v().getRefType("java.lang.VerifyError");
167:
168: // Token non-linkage Error (in the sense that it is not among
169: // Errors that the VM might throw itself during linkage---any
170: // error could be generated during linking by a static
171: // initializer).
172: Scene.v().loadClassAndSupport("java.awt.AWTError");
173: AWT_ERROR = Scene.v().getRefType("java.awt.AWTError");
174:
175: // VM errors:
176: INTERNAL_ERROR = Scene.v()
177: .getRefType("java.lang.InternalError");
178:
179: OUT_OF_MEMORY_ERROR = Scene.v().getRefType(
180: "java.lang.OutOfMemoryError");
181:
182: STACK_OVERFLOW_ERROR = Scene.v().getRefType(
183: "java.lang.StackOverflowError");
184:
185: UNKNOWN_ERROR = Scene.v().getRefType("java.lang.UnknownError");
186:
187: THREAD_DEATH = Scene.v().getRefType("java.lang.ThreadDeath");
188:
189: Scene.v().loadClassAndSupport("java.lang.VirtualMachineError");
190: VIRTUAL_MACHINE_ERROR = Scene.v().getRefType(
191: "java.lang.VirtualMachineError");
192:
193: // Two Throwables that our test statements will never throw (except
194: // for invoke statements--in the absence of interprocedural analysis,
195: // we have to assume they can throw anything).
196: Scene.v().loadClassAndSupport(
197: "java.lang.reflect.UndeclaredThrowableException");
198: UNDECLARED_THROWABLE_EXCEPTION = Scene.v().getRefType(
199: "java.lang.reflect.UndeclaredThrowableException");
200:
201: Scene.v().loadClassAndSupport(
202: "javax.swing.UnsupportedLookAndFeelException");
203: UNSUPPORTED_LOOK_AND_FEEL_EXCEPTION = Scene.v().getRefType(
204: "javax.swing.UnsupportedLookAndFeelException");
205:
206: VM_ERRORS = Collections.unmodifiableSet(new ExceptionHashSet(
207: Arrays.asList(new RefType[] { THREAD_DEATH,
208: INTERNAL_ERROR, OUT_OF_MEMORY_ERROR,
209: STACK_OVERFLOW_ERROR, UNKNOWN_ERROR, })));
210:
211: Set temp = new ExceptionHashSet(VM_ERRORS);
212: temp.add(VIRTUAL_MACHINE_ERROR);
213: temp.add(ERROR);
214: temp.add(THROWABLE);
215: VM_ERRORS_PLUS_SUPERTYPES = Collections.unmodifiableSet(temp);
216:
217: temp = new ExceptionHashSet(VM_ERRORS);
218: temp.add(CLASS_CIRCULARITY_ERROR);
219: temp.add(ILLEGAL_ACCESS_ERROR);
220: temp.add(INCOMPATIBLE_CLASS_CHANGE_ERROR);
221: temp.add(LINKAGE_ERROR);
222: temp.add(NO_CLASS_DEF_FOUND_ERROR);
223: temp.add(VERIFY_ERROR);
224: Set tempForRep = new ExceptionHashSet(temp);
225: tempForRep.add(AnySubType.v(CLASS_FORMAT_ERROR));
226: VM_AND_RESOLVE_CLASS_ERRORS_REP = Collections
227: .unmodifiableSet(tempForRep);
228:
229: temp.add(CLASS_FORMAT_ERROR);
230: temp.add(UNSUPPORTED_CLASS_VERSION_ERROR);
231: VM_AND_RESOLVE_CLASS_ERRORS = Collections.unmodifiableSet(temp);
232: temp.add(VIRTUAL_MACHINE_ERROR);
233: temp.add(ERROR);
234: temp.add(THROWABLE);
235: VM_AND_RESOLVE_CLASS_ERRORS_PLUS_SUPERTYPES = Collections
236: .unmodifiableSet(temp);
237:
238: temp = new ExceptionHashSet(VM_AND_RESOLVE_CLASS_ERRORS_REP);
239: temp.add(NO_SUCH_FIELD_ERROR);
240: VM_AND_RESOLVE_FIELD_ERRORS_REP = Collections
241: .unmodifiableSet(temp);
242:
243: temp = new ExceptionHashSet(VM_AND_RESOLVE_CLASS_ERRORS);
244: temp.add(NO_SUCH_FIELD_ERROR);
245: VM_AND_RESOLVE_FIELD_ERRORS = Collections.unmodifiableSet(temp);
246: temp.add(VIRTUAL_MACHINE_ERROR);
247: temp.add(ERROR);
248: temp.add(THROWABLE);
249: VM_AND_RESOLVE_FIELD_ERRORS_PLUS_SUPERTYPES = Collections
250: .unmodifiableSet(temp);
251:
252: temp = new ExceptionHashSet(VM_AND_RESOLVE_CLASS_ERRORS_REP);
253: temp.add(ABSTRACT_METHOD_ERROR);
254: temp.add(NO_SUCH_METHOD_ERROR);
255: temp.add(UNSATISFIED_LINK_ERROR);
256: VM_AND_RESOLVE_METHOD_ERRORS_REP = Collections
257: .unmodifiableSet(temp);
258:
259: temp = new ExceptionHashSet(VM_AND_RESOLVE_CLASS_ERRORS);
260: temp.add(ABSTRACT_METHOD_ERROR);
261: temp.add(NO_SUCH_METHOD_ERROR);
262: temp.add(UNSATISFIED_LINK_ERROR);
263: VM_AND_RESOLVE_METHOD_ERRORS = Collections
264: .unmodifiableSet(temp);
265: temp.add(VIRTUAL_MACHINE_ERROR);
266: temp.add(ERROR);
267: temp.add(THROWABLE);
268: VM_AND_RESOLVE_METHOD_ERRORS_PLUS_SUPERTYPES = Collections
269: .unmodifiableSet(temp);
270:
271: temp = new ExceptionHashSet();
272: temp.add(AnySubType.v(Scene.v().getRefType("java.lang.Error")));
273: ALL_ERRORS_REP = Collections.unmodifiableSet(temp);
274:
275: temp = new ExceptionHashSet(VM_AND_RESOLVE_METHOD_ERRORS);
276: temp.add(NO_SUCH_FIELD_ERROR);
277: temp.add(EXCEPTION_IN_INITIALIZER_ERROR);
278: temp.add(INSTANTIATION_ERROR);
279: temp.add(AWT_ERROR);
280: ALL_TEST_ERRORS = Collections.unmodifiableSet(temp);
281:
282: temp = new ExceptionHashSet(ALL_TEST_ERRORS);
283: temp.add(VIRTUAL_MACHINE_ERROR);
284: temp.add(ERROR);
285: temp.add(THROWABLE);
286: ALL_TEST_ERRORS_PLUS_SUPERTYPES = Collections
287: .unmodifiableSet(temp);
288:
289: temp = new ExceptionHashSet(VM_ERRORS);
290: temp.add(ILLEGAL_MONITOR_STATE_EXCEPTION);
291: temp.add(NULL_POINTER_EXCEPTION);
292: PERENNIAL_THROW_EXCEPTIONS = Collections.unmodifiableSet(temp);
293:
294: temp = new ExceptionHashSet(VM_ERRORS_PLUS_SUPERTYPES);
295: temp.add(ILLEGAL_MONITOR_STATE_EXCEPTION);
296: temp.add(NULL_POINTER_EXCEPTION);
297: temp.add(RUNTIME_EXCEPTION);
298: temp.add(EXCEPTION);
299: PERENNIAL_THROW_EXCEPTIONS_PLUS_SUPERTYPES = Collections
300: .unmodifiableSet(temp);
301:
302: temp = new ExceptionHashSet(PERENNIAL_THROW_EXCEPTIONS);
303: temp.add(INCOMPATIBLE_CLASS_CHANGE_ERROR);
304: THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE = Collections
305: .unmodifiableSet(temp);
306:
307: temp = new ExceptionHashSet(
308: PERENNIAL_THROW_EXCEPTIONS_PLUS_SUPERTYPES);
309: temp.add(INCOMPATIBLE_CLASS_CHANGE_ERROR);
310: temp.add(LINKAGE_ERROR);
311: THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUPERTYPES = Collections
312: .unmodifiableSet(temp);
313:
314: temp = new ExceptionHashSet(
315: THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE);
316: temp.add(ABSTRACT_METHOD_ERROR);
317: temp.add(ILLEGAL_ACCESS_ERROR);
318: temp.add(INSTANTIATION_ERROR);
319: ;
320: temp.add(NO_SUCH_FIELD_ERROR);
321: temp.add(NO_SUCH_METHOD_ERROR);
322: THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUBTYPES = Collections
323: .unmodifiableSet(temp);
324:
325: temp = new ExceptionHashSet(
326: THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUPERTYPES);
327: temp.add(ABSTRACT_METHOD_ERROR);
328: temp.add(ILLEGAL_ACCESS_ERROR);
329: temp.add(INSTANTIATION_ERROR);
330: ;
331: temp.add(NO_SUCH_FIELD_ERROR);
332: temp.add(NO_SUCH_METHOD_ERROR);
333: THROW_PLUS_INCOMPATIBLE_CLASS_CHANGE_PLUS_SUBTYPES_PLUS_SUPERTYPES = Collections
334: .unmodifiableSet(temp);
335:
336: temp = new ExceptionHashSet(Arrays.asList(new RefType[] {
337: THROWABLE, EXCEPTION, RUNTIME_EXCEPTION,
338: ARITHMETIC_EXCEPTION, ARRAY_STORE_EXCEPTION,
339: CLASS_CAST_EXCEPTION, ILLEGAL_MONITOR_STATE_EXCEPTION,
340: INDEX_OUT_OF_BOUNDS_EXCEPTION,
341: ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION,
342: STRING_INDEX_OUT_OF_BOUNDS_EXCEPTION,
343: NEGATIVE_ARRAY_SIZE_EXCEPTION, NULL_POINTER_EXCEPTION,
344: ERROR, LINKAGE_ERROR, CLASS_CIRCULARITY_ERROR,
345: CLASS_FORMAT_ERROR, UNSUPPORTED_CLASS_VERSION_ERROR,
346: EXCEPTION_IN_INITIALIZER_ERROR,
347: INCOMPATIBLE_CLASS_CHANGE_ERROR, ABSTRACT_METHOD_ERROR,
348: ILLEGAL_ACCESS_ERROR, INSTANTIATION_ERROR,
349: NO_SUCH_FIELD_ERROR, NO_SUCH_METHOD_ERROR,
350: NO_CLASS_DEF_FOUND_ERROR, UNSATISFIED_LINK_ERROR,
351: VERIFY_ERROR, THREAD_DEATH, VIRTUAL_MACHINE_ERROR,
352: INTERNAL_ERROR, OUT_OF_MEMORY_ERROR,
353: STACK_OVERFLOW_ERROR, UNKNOWN_ERROR, AWT_ERROR,
354: UNDECLARED_THROWABLE_EXCEPTION,
355: UNSUPPORTED_LOOK_AND_FEEL_EXCEPTION, }));
356: ALL_TEST_THROWABLES = Collections.unmodifiableSet(temp);
357:
358: temp = new ExceptionHashSet();
359: temp.add(AnySubType.v(Scene.v().getRefType(
360: "java.lang.Throwable")));
361: ALL_THROWABLES_REP = Collections.unmodifiableSet(temp);
362: }
363:
364: /**
365: * Verifies that the argument <code>set</code> is catchable as
366: * any of the exceptions in <code>members</code>.
367: *
368: * @param set <code>ThrowableSet</code> whose membership is
369: * being checked.
370: *
371: * @param members A {@link List} of {@link RefType} objects representing
372: * Throwable classes.
373: *
374: */
375: public boolean catchableAsAllOf(ThrowableSet set, List members) {
376: boolean result = true;
377: for (Iterator i = members.iterator(); i.hasNext();) {
378: RefType member = (RefType) i.next();
379: result = result && set.catchableAs(member);
380: }
381: return result;
382: }
383:
384: /**
385: * Verifies that the argument <code>set</code> is not catchable as
386: * any of the exceptions in <code>members</code>.
387: *
388: * @param set <code>ThrowableSet</code> whose membership is
389: * being checked.
390: *
391: * @param members A {@link List} of {@link RefType} objects representing
392: * Throwable classes.
393: *
394: */
395: public boolean catchableAsNoneOf(ThrowableSet set, List members) {
396: boolean result = true;
397: for (Iterator i = members.iterator(); i.hasNext();) {
398: RefType member = (RefType) i.next();
399: result = result && (!set.catchableAs(member));
400: }
401: return result;
402: }
403:
404: /**
405: * Verifies that the argument <code>set</code> is catchable as
406: * any of the exceptions in <code>members</code>, but not
407: * as any other of the exceptions ALL_TEST_THROWABLES.
408: *
409: * @param set <code>ThrowableSet</code> whose membership is
410: * being checked.
411: *
412: * @param members A {@link List} of {@link RefType} objects representing
413: * Throwable classes.
414: *
415: */
416: public boolean catchableOnlyAs(ThrowableSet set, List members) {
417: boolean result = true;
418: for (Iterator i = members.iterator(); i.hasNext();) {
419: RefType member = (RefType) i.next();
420: result = result && (set.catchableAs(member));
421: }
422: for (Iterator i = ALL_TEST_THROWABLES.iterator(); i.hasNext();) {
423: RefType e = (RefType) i.next();
424: if (!members.contains(e)) {
425: result = result && (!set.catchableAs(e));
426: }
427: }
428: return result;
429: }
430:
431: /**
432: * Returns a Set representation of the subset of ALL_TEST_THROWABLES
433: * which are catchable by the argument <code>ThrowableSet</code>
434: * (for use in assertions about the catchable exceptions.
435: *
436: * @param thrownSet <code>ThrowableSet</code> representing some
437: * set of possible exceptions.
438: */
439: public Set catchableSubset(ThrowableSet thrownSet) {
440: Set result = new ExceptionHashSet(ALL_TEST_THROWABLES.size());
441: for (Iterator i = ALL_TEST_THROWABLES.iterator(); i.hasNext();) {
442: RefType e = (RefType) i.next();
443: if (thrownSet.catchableAs(e)) {
444: result.add(e);
445: }
446: }
447: return result;
448: }
449:
450: /**
451: * Checks that the internal representation of the exceptions
452: * in an argument {@link ThrowableSet} matches expectations.
453: *
454: * @param thrownSet {@link ThrowableSet} whose contents are being
455: * checked.
456: *
457: * @param expectedIncludes contains the collection of {@link
458: * RefType} and {@link AnySubType} objects that are expected to be
459: * included in <code>thrownSet</code>.
460: *
461: * @param expectedExcludes contains the collection of {@link
462: * RefType} and {@link AnySubType} objects that are expected to be
463: * excluded from <code>thrownSet</code>.
464: *
465: * @return <code>true</code> if <code>thrownSet</code> and
466: * <code>expected</code> have the same members.
467: */
468: public static boolean sameMembers(Set expectedIncluded,
469: Set expectedExcluded, ThrowableSet thrownSet) {
470: if ((expectedIncluded.size() != thrownSet.typesIncluded()
471: .size())
472: || (expectedExcluded.size() != thrownSet
473: .typesExcluded().size())
474: || (!expectedIncluded.containsAll(thrownSet
475: .typesIncluded()))
476: || (!expectedExcluded.containsAll(thrownSet
477: .typesExcluded()))) {
478: System.out.println("\nExpected included:"
479: + expectedIncluded.toString()
480: + "\nExpected excluded:"
481: + expectedExcluded.toString() + "\nActual:\n"
482: + thrownSet.toString());
483: return false;
484: } else {
485: return true;
486: }
487: }
488:
489: public static class ExceptionHashSet extends HashSet {
490: // The only difference between this and a standard HashSet is that
491: // we override the toString() method to make ExceptionHashSets
492: // easier to compare when they appear in JUnit assertion failure
493: // messages.
494:
495: ExceptionHashSet() {
496: super ();
497: }
498:
499: ExceptionHashSet(Collection c) {
500: super (c);
501: }
502:
503: ExceptionHashSet(int initialCapacity) {
504: super (initialCapacity);
505: }
506:
507: public String toString() {
508: StringBuffer result = new StringBuffer();
509: Object[] contents = (Object[]) this .toArray();
510: Comparator comparator = new Comparator() {
511: public int compare(Object o1, Object o2) {
512: // The order doesn't matter, so long as it is consistent.
513: return o1.toString().compareTo(o2.toString());
514: }
515: };
516: Arrays.sort(contents, comparator);
517: result.append("\nExceptionHashSet<");
518: for (int i = 0; i < contents.length; i++) {
519: result.append("\n\t");
520: result.append(contents[i].toString());
521: result.append("<");
522: result.append(Integer.toHexString(contents[i]
523: .hashCode()));
524: result.append(">");
525: }
526: result.append("\n>ExceptionHashSet");
527: return result.toString();
528: }
529: }
530: }
|