Source Code Cross Referenced for ThrowableSet.java in  » Code-Analyzer » soot » soot » toolkits » exceptions » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Code Analyzer » soot » soot.toolkits.exceptions 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Soot - a J*va Optimization Framework
0002:         * Copyright (C) 2003 John Jorgensen
0003:         *
0004:         * This library is free software; you can redistribute it and/or
0005:         * modify it under the terms of the GNU Library General Public
0006:         * License as published by the Free Software Foundation; either
0007:         * version 2 of the License, or (at your option) any later version.
0008:         *
0009:         * This library is distributed in the hope that it will be useful,
0010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012:         * Library General Public License for more details.
0013:         *
0014:         * You should have received a copy of the GNU Library General Public
0015:         * License along with this library; if not, write to the
0016:         * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
0017:         * Boston, MA 02111-1307, USA.
0018:         */
0019:
0020:        package soot.toolkits.exceptions;
0021:
0022:        import soot.*;
0023:        import soot.options.Options;
0024:
0025:        import java.util.*;
0026:
0027:        /**
0028:         * <p>A class for representing the set of exceptions that an
0029:         * instruction may throw.</p>
0030:         *
0031:         * <p> <code>ThrowableSet</code> does not implement the 
0032:         * {@link java.util.Set} interface, so perhaps it is misnamed.
0033:         * Instead, it provides only the operations that we require for
0034:         * determining whether a given statement might throw an exception that
0035:         * would be caught by a given handler.</p>
0036:         *
0037:         * <p>There is a limitation on the combinations of operations
0038:         * permitted on a <code>ThrowableSet</code>.  The
0039:         * <code>ThrowableSet</code>s returned by {@link
0040:         * #whichCatchableAs(RefType)} cannot be involved in subsequent
0041:         * <code>add()</code> or <code>whichCatchableAs()</code> operations.
0042:         * That is, given
0043:         *
0044:         * <blockquote>
0045:         * <code>p = s.whichCatchableAs(r)</code>
0046:         * </blockquote>
0047:         *
0048:         * for any <code>ThrowableSet</code> <code>s</code> and 
0049:         * {@link soot.RefType RefType} <code>r</code>, and 
0050:         *
0051:         * <blockquote>
0052:         * <code>t == p.getUncaught()</code> or 
0053:         * <code>t == p.getCaught()</code>
0054:         * </blockquote>
0055:         *
0056:         * then calls to 
0057:         * <code>t.add(r)</code>, <code>t.add(a)</code>, and <code>s.add(t)</code>,
0058:         * will throw an {@link ThrowableSet.AlreadyHasExclusionsException}, for any 
0059:         * <code>RefType</code> <code>r</code>, {@link AnySubType} <code>a</code>, 
0060:         * and <code>ThrowableSet</code> <code>t</code>.</p>
0061:         *
0062:         * <p> Actually the restrictions implemented are not quite so strict
0063:         * (there are some combinations of <code>whichCatchableAs()</code>
0064:         * followed by <code>add()</code> which will not raise an exception),
0065:         * but a more accurate description would require reference to the
0066:         * internals of the current implementation. The restrictions should
0067:         * not be too onerous for <code>ThrowableSet</code>'s anticipated
0068:         * uses: we expect <code>ThrowableSet</code>s to grow by accumulating
0069:         * all the exception types that a given {@link Unit} may throw, then,
0070:         * shrink as the types caught by different exception handlers are
0071:         * removed to yield the sets representing exceptions which escape
0072:         * those handlers.</p>
0073:         * 
0074:         * <p> The <code>ThrowableSet</code> class is intended to be immutable
0075:         * (hence the <code>final</code> modifier on its declaration).  It
0076:         * does not take the step of guaranteeing immutability by cloning the
0077:         * <code>RefLikeType</code> objects it contains, though, because we trust
0078:         * {@link Scene} to enforce the existence of only one 
0079:         * <code>RefLikeType</code> instance with a given name.</p>
0080:         */
0081:
0082:        public final class ThrowableSet {
0083:
0084:            private static final boolean INSTRUMENTING = true;
0085:
0086:            /**
0087:             * Singleton class for fields and initializers common to all
0088:             * ThrowableSet objects (i.e., these would be static fields and
0089:             * initializers, in the absence of soot's {@link G} and {@link
0090:             * Singletons} classes).
0091:             */
0092:            public static class Manager {
0093:
0094:                /**
0095:                 * Map from {@link Integer}s representing set size to all
0096:                 * <code>ThrowableSet</code>s of that size.
0097:                 */
0098:                private final Map<Integer, List> sizeToSets = new HashMap<Integer, List>();
0099:
0100:                /**
0101:                 * <code>ThrowableSet</code> containing no exception classes.
0102:                 */
0103:                public final ThrowableSet EMPTY;
0104:
0105:                /**
0106:                 * <code>ThrowableSet</code> representing all possible
0107:                 * Throwables.
0108:                 */
0109:                final ThrowableSet ALL_THROWABLES;
0110:
0111:                /**
0112:                 * <code>ThrowableSet</code> containing all the asynchronous
0113:                 * and virtual machine errors, which may be thrown by any
0114:                 * bytecode instruction at any point in the computation.
0115:                 */
0116:                final ThrowableSet VM_ERRORS;
0117:
0118:                /**
0119:                 * <code>ThrowableSet</code> containing all the exceptions
0120:                 * that may be thrown in the course of resolving a reference
0121:                 * to another class, including the process of loading, preparing,
0122:                 * and verifying the referenced class.
0123:                 */
0124:                final ThrowableSet RESOLVE_CLASS_ERRORS;
0125:
0126:                /**
0127:                 * <code>ThrowableSet</code> containing all the exceptions
0128:                 * that may be thrown in the course of resolving a reference
0129:                 * to a field.
0130:                 */
0131:                final ThrowableSet RESOLVE_FIELD_ERRORS;
0132:
0133:                /**
0134:                 * <code>ThrowableSet</code> containing all the exceptions
0135:                 * that may be thrown in the course of resolving a reference
0136:                 * to a non-static method.
0137:                 */
0138:                final ThrowableSet RESOLVE_METHOD_ERRORS;
0139:
0140:                /**
0141:                 * <code>ThrowableSet</code> containing all the exceptions
0142:                 * which may be thrown by instructions that have the potential
0143:                 * to cause a new class to be loaded and initialized (including
0144:                 * UnsatisfiedLinkError, which is raised at runtime rather than
0145:                 * linking type).
0146:                 */
0147:                final ThrowableSet INITIALIZATION_ERRORS;
0148:
0149:                final RefType RUNTIME_EXCEPTION;
0150:                final RefType ARITHMETIC_EXCEPTION;
0151:                final RefType ARRAY_STORE_EXCEPTION;
0152:                final RefType CLASS_CAST_EXCEPTION;
0153:                final RefType ILLEGAL_MONITOR_STATE_EXCEPTION;
0154:                final RefType INDEX_OUT_OF_BOUNDS_EXCEPTION;
0155:                final RefType ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION;
0156:                final RefType NEGATIVE_ARRAY_SIZE_EXCEPTION;
0157:                final RefType NULL_POINTER_EXCEPTION;
0158:                final RefType INSTANTIATION_ERROR;
0159:
0160:                // counts for instrumenting:
0161:                private int registeredSets = 0;
0162:                private int addsOfRefType = 0;
0163:                private int addsOfAnySubType = 0;
0164:                private int addsOfSet = 0;
0165:                private int addsInclusionFromMap = 0;
0166:                private int addsInclusionFromMemo = 0;
0167:                private int addsInclusionFromSearch = 0;
0168:                private int addsInclusionInterrupted = 0;
0169:                private int addsExclusionWithSearch = 0;
0170:                private int addsExclusionWithoutSearch = 0;
0171:                private int removesOfAnySubType = 0;
0172:                private final int removesFromMap = 0;
0173:                private final int removesFromMemo = 0;
0174:                private int removesFromSearch = 0;
0175:                private int registrationCalls = 0;
0176:                private int catchableAsQueries = 0;
0177:                private int catchableAsFromMap = 0;
0178:                private int catchableAsFromSearch = 0;
0179:
0180:                /**
0181:                 * Constructs a <code>ThrowableSet.Manager</code> for inclusion in 
0182:                 * Soot's global variable manager, {@link G}.
0183:                 *
0184:                 * @param g guarantees that the constructor may only be called 
0185:                 * from {@link Singletons}.
0186:                 */
0187:                public Manager(Singletons.Global g) {
0188:                    // First ensure the Exception classes are represented in Soot.
0189:
0190:                    // Runtime errors:
0191:                    RUNTIME_EXCEPTION = Scene.v().getRefType(
0192:                            "java.lang.RuntimeException");
0193:                    ARITHMETIC_EXCEPTION = Scene.v().getRefType(
0194:                            "java.lang.ArithmeticException");
0195:                    ARRAY_STORE_EXCEPTION = Scene.v().getRefType(
0196:                            "java.lang.ArrayStoreException");
0197:                    CLASS_CAST_EXCEPTION = Scene.v().getRefType(
0198:                            "java.lang.ClassCastException");
0199:                    ILLEGAL_MONITOR_STATE_EXCEPTION = Scene.v().getRefType(
0200:                            "java.lang.IllegalMonitorStateException");
0201:                    INDEX_OUT_OF_BOUNDS_EXCEPTION = Scene.v().getRefType(
0202:                            "java.lang.IndexOutOfBoundsException");
0203:                    ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = Scene.v().getRefType(
0204:                            "java.lang.ArrayIndexOutOfBoundsException");
0205:                    NEGATIVE_ARRAY_SIZE_EXCEPTION = Scene.v().getRefType(
0206:                            "java.lang.NegativeArraySizeException");
0207:                    NULL_POINTER_EXCEPTION = Scene.v().getRefType(
0208:                            "java.lang.NullPointerException");
0209:
0210:                    INSTANTIATION_ERROR = Scene.v().getRefType(
0211:                            "java.lang.InstantiationError");
0212:
0213:                    EMPTY = registerSetIfNew(null, null);
0214:
0215:                    Set allThrowablesSet = new HashSet();
0216:                    allThrowablesSet.add(AnySubType.v(Scene.v().getRefType(
0217:                            "java.lang.Throwable")));
0218:                    ALL_THROWABLES = registerSetIfNew(allThrowablesSet, null);
0219:
0220:                    Set vmErrorSet = new HashSet();
0221:                    vmErrorSet.add(Scene.v().getRefType(
0222:                            "java.lang.InternalError"));
0223:                    vmErrorSet.add(Scene.v().getRefType(
0224:                            "java.lang.OutOfMemoryError"));
0225:                    vmErrorSet.add(Scene.v().getRefType(
0226:                            "java.lang.StackOverflowError"));
0227:                    vmErrorSet.add(Scene.v().getRefType(
0228:                            "java.lang.UnknownError"));
0229:
0230:                    // The Java library's deprecated Thread.stop(Throwable) method
0231:                    // would actually allow _any_ Throwable to be delivered
0232:                    // asynchronously, not just java.lang.ThreadDeath.
0233:                    vmErrorSet.add(Scene.v()
0234:                            .getRefType("java.lang.ThreadDeath"));
0235:
0236:                    VM_ERRORS = registerSetIfNew(vmErrorSet, null);
0237:
0238:                    Set resolveClassErrorSet = new HashSet();
0239:                    resolveClassErrorSet.add(Scene.v().getRefType(
0240:                            "java.lang.ClassCircularityError"));
0241:                    // We add AnySubType(ClassFormatError) so that we can
0242:                    // avoid adding its subclass,
0243:                    // UnsupportedClassVersionError, explicitly.  This is a
0244:                    // hack to allow Soot to analyze older class libraries 
0245:                    // (UnsupportedClassVersionError was added in JDK 1.2).
0246:                    if (!Options.v().j2me())
0247:                        resolveClassErrorSet.add(AnySubType.v(Scene.v()
0248:                                .getRefType("java.lang.ClassFormatError")));
0249:                    resolveClassErrorSet.add(Scene.v().getRefType(
0250:                            "java.lang.IllegalAccessError"));
0251:                    resolveClassErrorSet.add(Scene.v().getRefType(
0252:                            "java.lang.IncompatibleClassChangeError"));
0253:                    resolveClassErrorSet.add(Scene.v().getRefType(
0254:                            "java.lang.LinkageError"));
0255:                    resolveClassErrorSet.add(Scene.v().getRefType(
0256:                            "java.lang.NoClassDefFoundError"));
0257:                    resolveClassErrorSet.add(Scene.v().getRefType(
0258:                            "java.lang.VerifyError"));
0259:                    RESOLVE_CLASS_ERRORS = registerSetIfNew(
0260:                            resolveClassErrorSet, null);
0261:
0262:                    Set resolveFieldErrorSet = new HashSet(resolveClassErrorSet);
0263:                    resolveFieldErrorSet.add(Scene.v().getRefType(
0264:                            "java.lang.NoSuchFieldError"));
0265:                    RESOLVE_FIELD_ERRORS = registerSetIfNew(
0266:                            resolveFieldErrorSet, null);
0267:
0268:                    Set resolveMethodErrorSet = new HashSet(
0269:                            resolveClassErrorSet);
0270:                    resolveMethodErrorSet.add(Scene.v().getRefType(
0271:                            "java.lang.AbstractMethodError"));
0272:                    resolveMethodErrorSet.add(Scene.v().getRefType(
0273:                            "java.lang.NoSuchMethodError"));
0274:                    resolveMethodErrorSet.add(Scene.v().getRefType(
0275:                            "java.lang.UnsatisfiedLinkError"));
0276:                    RESOLVE_METHOD_ERRORS = registerSetIfNew(
0277:                            resolveMethodErrorSet, null);
0278:
0279:                    // The static initializers of a newly loaded class might
0280:                    // throw any Error (if they threw an Exception---even a
0281:                    // RuntimeException---it would be replaced by an
0282:                    // ExceptionInInitializerError):
0283:                    //
0284:                    Set initializationErrorSet = new HashSet();
0285:                    initializationErrorSet.add(AnySubType.v(Scene.v()
0286:                            .getRefType("java.lang.Error")));
0287:                    INITIALIZATION_ERRORS = registerSetIfNew(
0288:                            initializationErrorSet, null);
0289:                }
0290:
0291:                /**
0292:                 * Returns the single instance of <code>ThrowableSet.Manager</code>.
0293:                 *
0294:                 * @return Soot's <code>ThrowableSet.Manager</code>.
0295:                 */
0296:                public static Manager v() {
0297:                    return G.v()
0298:                            .soot_toolkits_exceptions_ThrowableSet_Manager();
0299:                }
0300:
0301:                /**
0302:                 * <p>Returns a <code>ThrowableSet</code> representing the set of
0303:                 * exceptions included in <code>include</code> minus the set
0304:                 * of exceptions included in <code>exclude</code>. Creates a
0305:                 * new <code>ThrowableSet</code> only if there was not already
0306:                 * one whose contents correspond to <code>include</code> -
0307:                 * <code>exclude</code>.</p>
0308:                 *
0309:                 * @param include  A set of {@link RefLikeType}
0310:                 * objects representing exception types included in the result; may
0311:                 * be <code>null</code> if there are no included types.
0312:                 *
0313:                 * @param exclude  A set of {@link AnySubType}
0314:                 * objects representing exception types excluded from the result; may
0315:                 * be <code>null</code> if there are no excluded types.
0316:                 *
0317:                 * @return a <code>ThrowableSet</code> representing the set of
0318:                 * exceptions corresponding to <code>include</code> -
0319:                 * <code>exclude</code>.
0320:                 */
0321:                private ThrowableSet registerSetIfNew(Set include, Set exclude) {
0322:                    if (INSTRUMENTING) {
0323:                        registrationCalls++;
0324:                    }
0325:                    if (include == null) {
0326:                        include = Collections.EMPTY_SET;
0327:                    }
0328:                    if (exclude == null) {
0329:                        exclude = Collections.EMPTY_SET;
0330:                    }
0331:                    int size = include.size() + exclude.size();
0332:                    Integer sizeKey = new Integer(size);
0333:
0334:                    List<ThrowableSet> sizeList = sizeToSets.get(sizeKey);
0335:                    if (sizeList == null) {
0336:                        sizeList = new LinkedList<ThrowableSet>();
0337:                        sizeToSets.put(sizeKey, sizeList);
0338:                    }
0339:                    for (ThrowableSet set : sizeList) {
0340:                        if (set.exceptionsIncluded.equals(include)
0341:                                && set.exceptionsExcluded.equals(exclude)) {
0342:                            return set;
0343:                        }
0344:                    }
0345:                    if (INSTRUMENTING) {
0346:                        registeredSets++;
0347:                    }
0348:                    ThrowableSet result = new ThrowableSet(include, exclude);
0349:                    sizeList.add(result);
0350:                    return result;
0351:                }
0352:
0353:                /**
0354:                 * Report the counts collected by instrumentation (for now, at
0355:                 * least, there is no need to provide access to the individual
0356:                 * values as numbers).
0357:                 *
0358:                 * @return a string listing the counts.
0359:                 */
0360:                public String reportInstrumentation() {
0361:                    int setCount = 0;
0362:                    for (List sizeList : sizeToSets.values()) {
0363:                        setCount += sizeList.size();
0364:                    }
0365:                    if (setCount != registeredSets) {
0366:                        throw new IllegalStateException(
0367:                                "ThrowableSet.reportInstrumentation() assertion failure: registeredSets != list count");
0368:                    }
0369:                    StringBuffer buf = new StringBuffer("registeredSets: ")
0370:                            .append(setCount).append("\naddsOfRefType: ")
0371:                            .append(addsOfRefType).append(
0372:                                    "\naddsOfAnySubType: ").append(
0373:                                    addsOfAnySubType).append("\naddsOfSet: ")
0374:                            .append(addsOfSet).append(
0375:                                    "\naddsInclusionFromMap: ").append(
0376:                                    addsInclusionFromMap).append(
0377:                                    "\naddsInclusionFromMemo: ").append(
0378:                                    addsInclusionFromMemo).append(
0379:                                    "\naddsInclusionFromSearch: ").append(
0380:                                    addsInclusionFromSearch).append(
0381:                                    "\naddsInclusionInterrupted: ").append(
0382:                                    addsInclusionInterrupted).append(
0383:                                    "\naddsExclusionWithoutSearch: ").append(
0384:                                    addsExclusionWithoutSearch).append(
0385:                                    "\naddsExclusionWithSearch: ").append(
0386:                                    addsExclusionWithSearch).append(
0387:                                    "\nremovesOfAnySubType: ").append(
0388:                                    removesOfAnySubType).append(
0389:                                    "\nremovesFromMap: ")
0390:                            .append(removesFromMap).append(
0391:                                    "\nremovesFromMemo: ").append(
0392:                                    removesFromMemo).append(
0393:                                    "\nremovesFromSearch: ").append(
0394:                                    removesFromSearch).append(
0395:                                    "\nregistrationCalls: ").append(
0396:                                    registrationCalls).append(
0397:                                    "\ncatchableAsQueries: ").append(
0398:                                    catchableAsQueries).append(
0399:                                    "\ncatchableAsFromMap: ").append(
0400:                                    catchableAsFromMap).append(
0401:                                    "\ncatchableAsFromSearch: ").append(
0402:                                    catchableAsFromSearch).append('\n');
0403:                    return buf.toString();
0404:                }
0405:
0406:                /**
0407:                 * A package-private method to provide unit tests with access
0408:                 * to the collection of ThrowableSets.   
0409:                 */
0410:                Map<Integer, List> getSizeToSets() {
0411:                    return Manager.v().sizeToSets;
0412:                }
0413:            }
0414:
0415:            public static class AlreadyHasExclusionsException extends
0416:                    IllegalStateException {
0417:                public AlreadyHasExclusionsException(String s) {
0418:                    super (s);
0419:                }
0420:            }
0421:
0422:            /**
0423:             * Set of exception types included within the set.
0424:             */
0425:            private final Set exceptionsIncluded;
0426:
0427:            /**
0428:             * Set of exception types which, though members of
0429:             * exceptionsIncluded, are to be excluded from the types
0430:             * represented by this <code>ThrowableSet</code>.  To simplify
0431:             * the implementation, once a <code>ThrowableSet</code> has
0432:             * any excluded types, the various <code>add()</code> methods of
0433:             * this class must bar additions of subtypes of those
0434:             * excluded types.
0435:             */
0436:            private final Set exceptionsExcluded;
0437:
0438:            /**
0439:             * A map from 
0440:             * ({@link RefLikeType} \\union <code>ThrowableSet</code>) 
0441:     * to <code>ThrowableSet</code>.  If the mapping (k,v) is in
0442:     * <code>memoizedAdds</code> and k is a
0443:     * <code>ThrowableSet</code>, then v is the set that
0444:     * results from adding all elements in k to <code>this</code>.  If
0445:     * (k,v) is in <code>memoizedAdds</code> and k is a
0446:     * {@link RefLikeType}, then v is the set that results from adding
0447:     * k to <code>this</code>.
0448:     */
0449:            private Map<Object, ThrowableSet> memoizedAdds;
0450:
0451:            private ThrowableSet getMemoizedAdds(Object key) {
0452:                if (memoizedAdds == null) {
0453:                    memoizedAdds = new HashMap();
0454:                }
0455:                return memoizedAdds.get(key);
0456:            }
0457:
0458:            /**
0459:             * Constructs a <code>ThrowableSet</code> which contains the
0460:             * exception types represented in <code>include</code>, except for
0461:             * those which are also in <code>exclude</code>. The constructor
0462:             * is private to ensure that the only way to get a new
0463:             * <code>ThrowableSet</code> is by adding elements to or removing
0464:             * them from an existing set.
0465:             *
0466:             * @param include The set of {@link RefType} and {@link AnySubType} 
0467:             *                objects representing the types to be included in the set.
0468:             * @param exclude The set of {@link AnySubType} 
0469:             *                objects representing the types to be excluded 
0470:             *                from the set.  
0471:             */
0472:            private ThrowableSet(Set include, Set exclude) {
0473:                exceptionsIncluded = Collections.unmodifiableSet(include);
0474:                exceptionsExcluded = Collections.unmodifiableSet(exclude);
0475:                // We don't need to clone include and exclude to guarantee
0476:                // immutability since ThrowableSet(Set,Set) is private to this
0477:                // class, where it is only called (via
0478:                // Manager.v().registerSetIfNew()) with arguments which the
0479:                // callers do not subsequently modify.
0480:            }
0481:
0482:            /**
0483:             * Returns a <code>ThrowableSet</code> which contains
0484:             * <code>e</code> in addition to the exceptions in
0485:             * this <code>ThrowableSet</code>. 
0486:             *
0487:             * <p>Add <code>e</code> as a {@link RefType} when
0488:             * you know that the run-time class of the exception you are representing is
0489:             * necessarily <code>e</code> and cannot be a subclass of
0490:             * <code>e</code>.  
0491:             *
0492:             * <p>For example, if you were 
0493:             * recording the type of the exception thrown by
0494:             *
0495:             * <pre>
0496:             * throw new IOException("Permission denied");
0497:             * </pre>
0498:             *
0499:             * you would call
0500:             *
0501:             * <pre>
0502:             * <code>add(Scene.v().getRefType("java.lang.Exception.IOException"))</code>
0503:             * </pre>
0504:             *
0505:             * since the class of the exception is necessarily
0506:             * <code>IOException</code>.
0507:             *
0508:             * @param e	the exception class
0509:             *
0510:             * @return a set containing <code>e</code> as well as the
0511:             * exceptions in this set.
0512:             *
0513:             * @throws {@link ThrowableSet.IllegalStateException} if this
0514:             * <code>ThrowableSet</code> is the result of a {@link
0515:             * #whichCatchableAs(RefType)} operation and, thus, unable to
0516:             * represent the addition of <code>e</code>.
0517:             */
0518:            public ThrowableSet add(RefType e)
0519:                    throws ThrowableSet.AlreadyHasExclusionsException {
0520:                if (INSTRUMENTING) {
0521:                    Manager.v().addsOfRefType++;
0522:                }
0523:                if (this .exceptionsIncluded.contains(e)) {
0524:                    if (INSTRUMENTING) {
0525:                        Manager.v().addsInclusionFromMap++;
0526:                        Manager.v().addsExclusionWithoutSearch++;
0527:                    }
0528:                    return this ;
0529:                } else {
0530:                    ThrowableSet result = getMemoizedAdds(e);
0531:                    if (result != null) {
0532:                        if (INSTRUMENTING) {
0533:                            Manager.v().addsInclusionFromMemo++;
0534:                            Manager.v().addsExclusionWithoutSearch++;
0535:                        }
0536:                        return result;
0537:                    } else {
0538:                        if (INSTRUMENTING) {
0539:                            Manager.v().addsInclusionFromSearch++;
0540:                            if (exceptionsExcluded.size() != 0) {
0541:                                Manager.v().addsExclusionWithSearch++;
0542:                            } else {
0543:                                Manager.v().addsExclusionWithoutSearch++;
0544:                            }
0545:                        }
0546:                        FastHierarchy hierarchy = Scene.v()
0547:                                .getOrMakeFastHierarchy();
0548:
0549:                        for (Iterator i = exceptionsExcluded.iterator(); i
0550:                                .hasNext();) {
0551:                            RefType exclusionBase = ((AnySubType) i.next())
0552:                                    .getBase();
0553:                            if (hierarchy.canStoreType(e, exclusionBase)) {
0554:                                throw new AlreadyHasExclusionsException(
0555:                                        "ThrowableSet.add(RefType): adding"
0556:                                                + e.toString()
0557:                                                + " to the set [ "
0558:                                                + this .toString() + "] where "
0559:                                                + exclusionBase.toString()
0560:                                                + " is excluded.");
0561:                            }
0562:                        }
0563:
0564:                        for (Iterator i = exceptionsIncluded.iterator(); i
0565:                                .hasNext();) {
0566:                            RefLikeType incumbent = (RefLikeType) i.next();
0567:                            if (incumbent instanceof  AnySubType) {
0568:                                // Need to use incumbent.getBase() because
0569:                                // hierarchy.canStoreType() assumes that parent
0570:                                // is not an AnySubType.
0571:                                RefType incumbentBase = ((AnySubType) incumbent)
0572:                                        .getBase();
0573:                                if (hierarchy.canStoreType(e, incumbentBase)) {
0574:                                    memoizedAdds.put(e, this );
0575:                                    return this ;
0576:                                }
0577:                            } else if (!(incumbent instanceof  RefType)) {
0578:                                // assertion failure.
0579:                                throw new IllegalStateException(
0580:                                        "ThrowableSet.add(RefType): Set element "
0581:                                                + incumbent.toString()
0582:                                                + " is neither a RefType nor an AnySubType.");
0583:                            }
0584:                        }
0585:                        Set resultSet = new HashSet(this .exceptionsIncluded);
0586:                        resultSet.add(e);
0587:                        result = Manager.v().registerSetIfNew(resultSet,
0588:                                this .exceptionsExcluded);
0589:                        memoizedAdds.put(e, result);
0590:                        return result;
0591:                    }
0592:                }
0593:            }
0594:
0595:            /**
0596:             * Returns a <code>ThrowableSet</code> which contains
0597:             * <code>e</code> and all of its subclasses as well as the
0598:             * exceptions in this set.
0599:             *
0600:             * <p><code>e</code> should be an instance of {@link AnySubType} 
0601:             * if you know that the
0602:             * compile-time type of the exception you are representing is
0603:             * <code>e</code>, but the exception may be instantiated at run-time
0604:             * by a subclass of
0605:             * <code>e</code>.  
0606:             *
0607:             * <p>For example, if you were recording the type of
0608:             * the exception thrown by
0609:             *
0610:             * <pre>
0611:             * catch (IOException e) {
0612:             *    throw e;
0613:             * }
0614:             * </pre>
0615:             *
0616:             * you would call 
0617:             *
0618:             * <pre>
0619:             * <code>add(AnySubtype.v(Scene.v().getRefType("java.lang.Exception.IOException")))</code>
0620:             * </pre>
0621:             *
0622:             * since the handler might rethrow any subclass of
0623:             * <code>IOException</code>.  
0624:             *
0625:             * @param e represents a subtree of the exception class hierarchy
0626:             * to add to this set.
0627:             *
0628:             * @return a set containing <code>e</code> and all its subclasses,
0629:             * as well as the exceptions represented by this set.
0630:             *
0631:             * @throws ThrowableSet.AlreadyHasExclusionsException if this
0632:             * <code>ThrowableSet</code> is the result of a {@link
0633:             * #whichCatchableAs(RefType)} operation and, thus, unable to
0634:             * represent the addition of <code>e</code>.
0635:             */
0636:            public ThrowableSet add(AnySubType e)
0637:                    throws ThrowableSet.AlreadyHasExclusionsException {
0638:                if (INSTRUMENTING) {
0639:                    Manager.v().addsOfAnySubType++;
0640:                }
0641:
0642:                ThrowableSet result = getMemoizedAdds(e);
0643:                if (result != null) {
0644:                    if (INSTRUMENTING) {
0645:                        Manager.v().addsInclusionFromMemo++;
0646:                        Manager.v().addsExclusionWithoutSearch++;
0647:                    }
0648:                    return result;
0649:                } else {
0650:                    FastHierarchy hierarchy = Scene.v()
0651:                            .getOrMakeFastHierarchy();
0652:                    RefType newBase = e.getBase();
0653:
0654:                    if (INSTRUMENTING) {
0655:                        if (exceptionsExcluded.size() != 0) {
0656:                            Manager.v().addsExclusionWithSearch++;
0657:                        } else {
0658:                            Manager.v().addsExclusionWithoutSearch++;
0659:                        }
0660:                    }
0661:                    for (Iterator i = exceptionsExcluded.iterator(); i
0662:                            .hasNext();) {
0663:                        RefType exclusionBase = ((AnySubType) i.next())
0664:                                .getBase();
0665:                        if (hierarchy.canStoreType(newBase, exclusionBase)
0666:                                || hierarchy.canStoreType(exclusionBase,
0667:                                        newBase)) {
0668:                            if (INSTRUMENTING) {
0669:                                // To ensure that the subcategories total properly:
0670:                                Manager.v().addsInclusionInterrupted++;
0671:                            }
0672:                            throw new AlreadyHasExclusionsException(
0673:                                    "ThrowableSet.add(" + e.toString()
0674:                                            + ") to the set [ "
0675:                                            + this .toString() + "] where "
0676:                                            + exclusionBase.toString()
0677:                                            + " is excluded.");
0678:                        }
0679:                    }
0680:
0681:                    if (this .exceptionsIncluded.contains(e)) {
0682:                        if (INSTRUMENTING) {
0683:                            Manager.v().addsInclusionFromMap++;
0684:                        }
0685:                        return this ;
0686:
0687:                    } else {
0688:                        if (INSTRUMENTING) {
0689:                            Manager.v().addsInclusionFromSearch++;
0690:                        }
0691:
0692:                        int changes = 0;
0693:                        boolean addNewException = true;
0694:                        Set resultSet = new HashSet();
0695:
0696:                        for (Iterator i = this .exceptionsIncluded.iterator(); i
0697:                                .hasNext();) {
0698:                            RefLikeType incumbent = (RefLikeType) i.next();
0699:                            if (incumbent instanceof  RefType) {
0700:                                if (hierarchy.canStoreType(incumbent, newBase)) {
0701:                                    // Omit incumbent from result.
0702:                                    changes++;
0703:                                } else {
0704:                                    resultSet.add(incumbent);
0705:                                }
0706:                            } else if (incumbent instanceof  AnySubType) {
0707:                                RefType incumbentBase = ((AnySubType) incumbent)
0708:                                        .getBase();
0709:                                // We have to use the base types in these hierarchy calls
0710:                                // because we want to know if _all_ possible
0711:                                // types represented by e can be represented by
0712:                                // the incumbent, or vice versa.
0713:                                if (hierarchy.canStoreType(newBase,
0714:                                        incumbentBase)) {
0715:                                    addNewException = false;
0716:                                    resultSet.add(incumbent);
0717:                                } else if (hierarchy.canStoreType(
0718:                                        incumbentBase, newBase)) {
0719:                                    // Omit incumbent from result;
0720:                                    changes++;
0721:                                } else {
0722:                                    resultSet.add(incumbent);
0723:                                }
0724:                            } else { // assertion failure.
0725:                                throw new IllegalStateException(
0726:                                        "ThrowableSet.add(AnySubType): Set element "
0727:                                                + incumbent.toString()
0728:                                                + " is neither a RefType nor an AnySubType.");
0729:                            }
0730:                        }
0731:                        if (addNewException) {
0732:                            resultSet.add(e);
0733:                            changes++;
0734:                        }
0735:                        if (changes > 0) {
0736:                            result = Manager.v().registerSetIfNew(resultSet,
0737:                                    this .exceptionsExcluded);
0738:                        } else {
0739:                            result = this ;
0740:                        }
0741:                        memoizedAdds.put(e, result);
0742:                        return result;
0743:                    }
0744:                }
0745:            }
0746:
0747:            /**
0748:             * Returns a <code>ThrowableSet</code> which contains
0749:             * all the exceptions in <code>s</code> in addition to those in
0750:             * this <code>ThrowableSet</code>.
0751:             *
0752:             * @param s	set of exceptions to add to this set.
0753:             *
0754:             * @return the union of this set with <code>s</code>
0755:             *
0756:             * @throws ThrowableSet.AlreadyHasExclusionsException if this 
0757:             * <code>ThrowableSet</code> or <code>s</code> is the
0758:             * result of a {@link #whichCatchableAs(RefType)} operation, so that
0759:             * it is not possible to represent the addition of <code>s</code> to
0760:             * this <code>ThrowableSet</code>.
0761:             */
0762:            public ThrowableSet add(ThrowableSet s)
0763:                    throws ThrowableSet.AlreadyHasExclusionsException {
0764:                if (INSTRUMENTING) {
0765:                    Manager.v().addsOfSet++;
0766:                }
0767:                if (exceptionsExcluded.size() > 0
0768:                        || s.exceptionsExcluded.size() > 0) {
0769:                    throw new AlreadyHasExclusionsException(
0770:                            "ThrowableSet.Add(ThrowableSet): attempt to add to ["
0771:                                    + this .toString()
0772:                                    + "] after removals recorded.");
0773:                }
0774:                ThrowableSet result = getMemoizedAdds(s);
0775:                if (result == null) {
0776:                    if (INSTRUMENTING) {
0777:                        Manager.v().addsInclusionFromSearch++;
0778:                        Manager.v().addsExclusionWithoutSearch++;
0779:                    }
0780:                    result = this .add(s.exceptionsIncluded);
0781:                    memoizedAdds.put(s, result);
0782:                } else if (INSTRUMENTING) {
0783:                    Manager.v().addsInclusionFromMemo++;
0784:                    Manager.v().addsExclusionWithoutSearch++;
0785:                }
0786:                return result;
0787:            }
0788:
0789:            /**
0790:             * Returns a <code>ThrowableSet</code> which contains all
0791:             * the exceptions in <code>addedExceptions</code> in addition to those
0792:             * in this <code>ThrowableSet</code>. 
0793:             *
0794:             * @param addedExceptions a set of {@link RefLikeType} and 
0795:             * {@link AnySubType} objects to be added to the types included in this
0796:             * <code>ThrowableSet</code>.
0797:             *
0798:             * @return a set containing all the <code>addedExceptions</code> as well
0799:             * as the exceptions in this set.
0800:             */
0801:            private ThrowableSet add(Set addedExceptions) {
0802:                Set resultSet = new HashSet(this .exceptionsIncluded);
0803:                int changes = 0;
0804:                FastHierarchy hierarchy = Scene.v().getOrMakeFastHierarchy();
0805:
0806:                // This algorithm is O(n m), where n and m are the sizes of the
0807:                // two sets, so hope that the sets are small.
0808:
0809:                for (Iterator i = addedExceptions.iterator(); i.hasNext();) {
0810:                    RefLikeType newType = (RefLikeType) i.next();
0811:                    if (!resultSet.contains(newType)) {
0812:                        boolean addNewType = true;
0813:                        if (newType instanceof  RefType) {
0814:                            for (Iterator j = resultSet.iterator(); j.hasNext();) {
0815:                                RefLikeType incumbentType = (RefLikeType) j
0816:                                        .next();
0817:                                if (incumbentType instanceof  RefType) {
0818:                                    if (newType == incumbentType) {
0819:                                        // assertion failure.
0820:                                        throw new IllegalStateException(
0821:                                                "ThrowableSet.add(Set): resultSet.contains() failed to screen duplicate RefType "
0822:                                                        + newType);
0823:                                    }
0824:                                } else if (incumbentType instanceof  AnySubType) {
0825:                                    RefType incumbentBase = ((AnySubType) incumbentType)
0826:                                            .getBase();
0827:                                    if (hierarchy.canStoreType(newType,
0828:                                            incumbentBase)) {
0829:                                        // No need to add this class.
0830:                                        addNewType = false;
0831:                                    }
0832:                                } else { // assertion failure.
0833:                                    throw new IllegalStateException(
0834:                                            "ThrowableSet.add(Set): incumbent Set element "
0835:                                                    + incumbentType
0836:                                                    + " is neither a RefType nor an AnySubType.");
0837:                                }
0838:                            }
0839:                        } else if (newType instanceof  AnySubType) {
0840:                            RefType newBase = ((AnySubType) newType).getBase();
0841:                            for (Iterator j = resultSet.iterator(); j.hasNext();) {
0842:                                RefLikeType incumbentType = (RefLikeType) j
0843:                                        .next();
0844:                                if (incumbentType instanceof  RefType) {
0845:                                    RefType incumbentBase = (RefType) incumbentType;
0846:                                    if (hierarchy.canStoreType(incumbentBase,
0847:                                            newBase)) {
0848:                                        j.remove();
0849:                                        changes++;
0850:                                    }
0851:                                } else if (incumbentType instanceof  AnySubType) {
0852:                                    RefType incumbentBase = ((AnySubType) incumbentType)
0853:                                            .getBase();
0854:                                    if (newBase == incumbentBase) {
0855:                                        // assertion failure.
0856:                                        throw new IllegalStateException(
0857:                                                "ThrowableSet.add(Set): resultSet.contains() failed to screen duplicate AnySubType "
0858:                                                        + newBase);
0859:                                    } else if (hierarchy.canStoreType(
0860:                                            incumbentBase, newBase)) {
0861:                                        j.remove();
0862:                                        changes++;
0863:                                    } else if (hierarchy.canStoreType(newBase,
0864:                                            incumbentBase)) {
0865:                                        // No need to add this class.
0866:                                        addNewType = false;
0867:                                    }
0868:                                } else { // assertion failure.
0869:                                    throw new IllegalStateException(
0870:                                            "ThrowableSet.add(Set): old Set element "
0871:                                                    + incumbentType
0872:                                                    + " is neither a RefType nor an AnySubType.");
0873:                                }
0874:                            }
0875:                        } else { // assertion failure.
0876:                            throw new IllegalArgumentException(
0877:                                    "ThrowableSet.add(Set): new Set element "
0878:                                            + newType
0879:                                            + " is neither a RefType nor an AnySubType.");
0880:                        }
0881:                        if (addNewType) {
0882:                            changes++;
0883:                            resultSet.add(newType);
0884:                        }
0885:                    }
0886:                }
0887:
0888:                ThrowableSet result = null;
0889:                if (changes > 0) {
0890:                    result = Manager.v().registerSetIfNew(resultSet,
0891:                            this .exceptionsExcluded);
0892:                } else {
0893:                    result = this ;
0894:                }
0895:                return result;
0896:            }
0897:
0898:            /**
0899:             * Indicates whether this ThrowableSet includes some 
0900:             * exception that might be caught by a handler argument of the
0901:             * type <code>catcher</code>.  
0902:             *
0903:             * @param catcher type of the handler parameter to be tested.
0904:             *
0905:             * @return <code>true</code> if this set contains an exception type
0906:             *                           that might be caught by <code>catcher</code>, 
0907:             *                           false if it does not.
0908:             */
0909:            public boolean catchableAs(RefType catcher) {
0910:                if (INSTRUMENTING) {
0911:                    Manager.v().catchableAsQueries++;
0912:                }
0913:
0914:                FastHierarchy h = Scene.v().getOrMakeFastHierarchy();
0915:
0916:                if (exceptionsExcluded.size() > 0) {
0917:                    if (INSTRUMENTING) {
0918:                        Manager.v().catchableAsFromSearch++;
0919:                    }
0920:                    for (Iterator i = exceptionsExcluded.iterator(); i
0921:                            .hasNext();) {
0922:                        AnySubType exclusion = (AnySubType) i.next();
0923:                        if (h.canStoreType(catcher, exclusion.getBase())) {
0924:                            return false;
0925:                        }
0926:                    }
0927:                }
0928:
0929:                if (exceptionsIncluded.contains(catcher)) {
0930:                    if (INSTRUMENTING) {
0931:                        if (exceptionsExcluded.size() == 0) {
0932:                            Manager.v().catchableAsFromMap++;
0933:                        } else {
0934:                            Manager.v().catchableAsFromSearch++;
0935:                        }
0936:                    }
0937:                    return true;
0938:                } else {
0939:                    if (INSTRUMENTING) {
0940:                        if (exceptionsExcluded.size() == 0) {
0941:                            Manager.v().catchableAsFromSearch++;
0942:                        }
0943:                    }
0944:                    for (Iterator i = exceptionsIncluded.iterator(); i
0945:                            .hasNext();) {
0946:                        RefLikeType thrownType = (RefLikeType) i.next();
0947:                        if (thrownType instanceof  RefType) {
0948:                            if (thrownType == catcher) {
0949:                                // assertion failure.
0950:                                throw new IllegalStateException(
0951:                                        "ThrowableSet.catchableAs(RefType): exceptions.contains() failed to match contained RefType "
0952:                                                + catcher);
0953:                            } else if (h.canStoreType(thrownType, catcher)) {
0954:                                return true;
0955:                            }
0956:                        } else {
0957:                            RefType thrownBase = ((AnySubType) thrownType)
0958:                                    .getBase();
0959:                            // At runtime, thrownType might be instantiated by any
0960:                            // of thrownBase's subtypes, so:
0961:                            if (h.canStoreType(thrownBase, catcher)
0962:                                    || h.canStoreType(catcher, thrownBase)) {
0963:                                return true;
0964:                            }
0965:                        }
0966:                    }
0967:                    return false;
0968:                }
0969:            }
0970:
0971:            /**
0972:             * Partitions the exceptions in this <code>ThrowableSet</code>
0973:             * into those which would be caught by a handler with the passed
0974:             * <code>catch</code> parameter type and those which would not.
0975:             *
0976:             * @param catcher type of the handler parameter to be tested.
0977:             *
0978:             * @return a pair of <code>ThrowableSet</code>s, one containing the
0979:             *         types in this <code>ThrowableSet</code> which would be
0980:             *         be caught as <code>catcher</code> and the other containing
0981:             *         the types in this <code>ThrowableSet</code> which would
0982:             *         not be caught as <code>catcher</code>.
0983:             */
0984:            public Pair whichCatchableAs(RefType catcher) {
0985:                if (INSTRUMENTING) {
0986:                    Manager.v().removesOfAnySubType++;
0987:                }
0988:
0989:                FastHierarchy h = Scene.v().getOrMakeFastHierarchy();
0990:                Set caughtIncluded = null;
0991:                Set caughtExcluded = null;
0992:                Set uncaughtIncluded = null;
0993:                Set uncaughtExcluded = null;
0994:
0995:                if (INSTRUMENTING) {
0996:                    Manager.v().removesFromSearch++;
0997:                }
0998:
0999:                for (Iterator i = exceptionsExcluded.iterator(); i.hasNext();) {
1000:                    AnySubType exclusion = (AnySubType) i.next();
1001:                    RefType exclusionBase = exclusion.getBase();
1002:                    if (h.canStoreType(catcher, exclusionBase)) {
1003:                        // Because the add() operations ban additions to sets
1004:                        // with exclusions, we can be sure no types in this are
1005:                        // caught by catcher.
1006:                        return new Pair(ThrowableSet.Manager.v().EMPTY, this );
1007:                    } else if (h.canStoreType(exclusionBase, catcher)) {
1008:                        // exclusion wouldn't be in exceptionsExcluded if one
1009:                        // of its supertypes were not in exceptionsIncluded,
1010:                        // so we know the next loop will add either that supertype 
1011:                        // or catcher to caughtIncluded.  Thus:
1012:                        caughtExcluded = addExceptionToSet(exclusion,
1013:                                caughtExcluded);
1014:                    } else {
1015:                        uncaughtExcluded = addExceptionToSet(exclusion,
1016:                                uncaughtExcluded);
1017:                    }
1018:                }
1019:
1020:                for (Iterator i = exceptionsIncluded.iterator(); i.hasNext();) {
1021:                    RefLikeType inclusion = (RefLikeType) i.next();
1022:                    if (inclusion instanceof  RefType) {
1023:                        if (h.canStoreType(inclusion, catcher)) {
1024:                            caughtIncluded = addExceptionToSet(inclusion,
1025:                                    caughtIncluded);
1026:                        } else {
1027:                            uncaughtIncluded = addExceptionToSet(inclusion,
1028:                                    uncaughtIncluded);
1029:                        }
1030:                    } else {
1031:                        RefType base = ((AnySubType) inclusion).getBase();
1032:                        if (h.canStoreType(base, catcher)) {
1033:                            // All subtypes of base will be caught.  Any exclusions
1034:                            // will already have been copied to caughtExcluded by
1035:                            // the preceding loop.
1036:                            caughtIncluded = addExceptionToSet(inclusion,
1037:                                    caughtIncluded);
1038:                        } else if (h.canStoreType(catcher, base)) {
1039:                            // Some subtypes of base will be caught, and
1040:                            // we know that not all of those catchable subtypes
1041:                            // are among exceptionsExcluded, since in that case we
1042:                            // would already have returned from within the 
1043:                            // preceding loop.  So, remove AnySubType(catcher)
1044:                            // from the uncaught types.
1045:                            uncaughtIncluded = addExceptionToSet(inclusion,
1046:                                    uncaughtIncluded);
1047:                            uncaughtExcluded = addExceptionToSet(AnySubType
1048:                                    .v(catcher), uncaughtExcluded);
1049:                            caughtIncluded = addExceptionToSet(AnySubType
1050:                                    .v(catcher), caughtIncluded);
1051:                            // Any already excluded subtypes of inclusion
1052:                            // which are subtypes of catcher will have been
1053:                            // added to caughtExcluded by the previous loop.
1054:                        } else {
1055:                            uncaughtIncluded = addExceptionToSet(inclusion,
1056:                                    uncaughtIncluded);
1057:                        }
1058:                    }
1059:                }
1060:                ThrowableSet caughtSet = Manager.v().registerSetIfNew(
1061:                        caughtIncluded, caughtExcluded);
1062:                ThrowableSet uncaughtSet = Manager.v().registerSetIfNew(
1063:                        uncaughtIncluded, uncaughtExcluded);
1064:                return new Pair(caughtSet, uncaughtSet);
1065:            }
1066:
1067:            /**
1068:             * The return type for {@link ThrowableSet#whichCatchableAs(RefType)},
1069:             * consisting of a pair of ThrowableSets.
1070:             */
1071:            public static class Pair {
1072:                private ThrowableSet caught;
1073:                private ThrowableSet uncaught;
1074:
1075:                /** 
1076:                 * Constructs a <code>ThrowableSet.Pair</code>.
1077:                 *
1078:                 * @param caught The set of exceptions to be returned when 
1079:                 *               {@link #getCaught()} is called on the constructed
1080:                 *               <code>ThrowableSet.Pair</code>.
1081:                 *
1082:                 * @param uncaught The set of exceptions to be returned when
1083:                 *                 {@link #getUncaught()} is called on the 
1084:                 *                 constructed <code>ThrowableSet.Pair</code>.
1085:                 */
1086:                protected Pair(ThrowableSet caught, ThrowableSet uncaught) {
1087:                    this .caught = caught;
1088:                    this .uncaught = uncaught;
1089:                }
1090:
1091:                /**
1092:                 * @return the set of caught exceptions.
1093:                 */
1094:                public ThrowableSet getCaught() {
1095:                    return caught;
1096:                }
1097:
1098:                /**
1099:                 * @return the set of uncaught exceptions.
1100:                 */
1101:                public ThrowableSet getUncaught() {
1102:                    return uncaught;
1103:                }
1104:
1105:                /**
1106:                 * Indicates whether two {@link Object}s are
1107:                 * <code>ThrowableSet.Pair</code>s representing the same set of
1108:                 * caught and uncaught exception types.
1109:                 *
1110:                 * @param o the <code>Object</code> to compare to this
1111:                 * <code>ThrowableSet.Pair</code>.
1112:                 *
1113:                 * @return <code>true</code> if <code>o</code> is a
1114:                 * <code>ThrowableSet.Pair</code> representing the same set of
1115:                 * caught and uncaught types as this
1116:                 * <code>ThrowableSet.Pair</code>.
1117:                 */
1118:                public boolean equals(Object o) {
1119:                    if (o == this ) {
1120:                        return true;
1121:                    }
1122:                    if (!(o instanceof  Pair)) {
1123:                        return false;
1124:                    }
1125:                    Pair tsp = (Pair) o;
1126:                    if (this .caught.equals(tsp.caught)
1127:                            && this .uncaught.equals(tsp.uncaught)) {
1128:                        return true;
1129:                    }
1130:                    return false;
1131:                }
1132:
1133:                public int hashCode() {
1134:                    int result = 31;
1135:                    result = 37 * result + caught.hashCode();
1136:                    result = 37 * result + uncaught.hashCode();
1137:                    return result;
1138:                }
1139:            }
1140:
1141:            /**
1142:             * Utility method for building sets of exceptional types for a
1143:             * {@link Pair}.
1144:             *
1145:             * @param e The exceptional type to add to the set.
1146:             *
1147:             * @param set The <code>Set</code> to which to add the types, or 
1148:             *            <code>null</code> if no <code>Set</code> has yet been
1149:             *            allocated.
1150:             *
1151:             * @return A <code>Set</code> containing the elements in <code>set</code>
1152:             *         plus <code>e</code>.
1153:             */
1154:            private Set addExceptionToSet(RefLikeType e, Set set) {
1155:                if (set == null) {
1156:                    set = new HashSet();
1157:                }
1158:                set.add(e);
1159:                return set;
1160:            }
1161:
1162:            /**
1163:             * Returns a string representation of this <code>ThrowableSet</code>.
1164:             */
1165:            public String toString() {
1166:                StringBuffer buffer = new StringBuffer(this .toBriefString());
1167:                buffer.append(":\n  ");
1168:                for (Iterator i = exceptionsIncluded.iterator(); i.hasNext();) {
1169:                    buffer.append('+');
1170:                    Object o = i.next();
1171:                    buffer.append(o == null ? "null" : o.toString());
1172:                    // buffer.append(i.next().toString());
1173:                }
1174:                for (Iterator i = exceptionsExcluded.iterator(); i.hasNext();) {
1175:                    buffer.append('-');
1176:                    buffer.append(i.next().toString());
1177:                }
1178:                return buffer.toString();
1179:            }
1180:
1181:            /**
1182:             * Returns a cryptic identifier for this <code>ThrowableSet</code>,
1183:             * used to identify a set when it appears in a collection.
1184:             */
1185:            public String toBriefString() {
1186:                return super .toString();
1187:            }
1188:
1189:            /**
1190:             * Returns an {@link Iterator} over a {@link Collection} of
1191:             * Throwable types which iterates over its elements in a
1192:             * consistent order (maintaining an ordering that is consistent
1193:             * across different runs makes it easier to compare sets generated
1194:             * by different implementations of the CFG classes).
1195:             *
1196:             * @param coll The collection to iterate over.
1197:             *
1198:             * @return An iterator which presents the elements of <code>coll</code> 
1199:             * in order.
1200:             */
1201:            private static Iterator sortedThrowableIterator(Collection coll) {
1202:                if (coll.size() <= 1) {
1203:                    return coll.iterator();
1204:                } else {
1205:                    Object array[] = coll.toArray();
1206:                    Arrays.sort(array, new ThrowableComparator());
1207:                    return Arrays.asList(array).iterator();
1208:                }
1209:            }
1210:
1211:            /**
1212:             * Comparator used to implement sortedThrowableIterator().
1213:             * 
1214:             */
1215:            private static class ThrowableComparator implements 
1216:                    java.util.Comparator {
1217:
1218:                private static RefType baseType(Object o) {
1219:                    if (o instanceof  AnySubType) {
1220:                        return ((AnySubType) o).getBase();
1221:                    } else {
1222:                        return (RefType) o; // ClassCastException if o is not a RefType.
1223:                    }
1224:                }
1225:
1226:                public int compare(Object o1, Object o2) {
1227:                    RefType t1 = baseType(o1);
1228:                    RefType t2 = baseType(o2);
1229:                    if (t1.equals(t2)) {
1230:                        // There should never be both AnySubType(t) and
1231:                        // t in a ThrowableSet, but if it happens, put 
1232:                        // AnySubType(t) first:
1233:                        if (o1 instanceof  AnySubType) {
1234:                            if (o2 instanceof  AnySubType) {
1235:                                return 0;
1236:                            } else {
1237:                                return -1;
1238:                            }
1239:                        } else if (o2 instanceof  AnySubType) {
1240:                            return 1;
1241:                        } else {
1242:                            return 0;
1243:                        }
1244:                    } else {
1245:                        return t1.toString().compareTo(t2.toString());
1246:                    }
1247:                }
1248:
1249:                public boolean equal(Object o1, Object o2) {
1250:                    return (o1.equals(o2));
1251:                }
1252:            }
1253:
1254:            /**
1255:             * <p>Produce an abbreviated representation of this
1256:             * <code>ThrowableSet</code>, suitable for human consumption.  The
1257:             * abbreviations include:</p>
1258:             * 
1259:             * <ul> 
1260:             *
1261:             * <li>The strings &ldquo;<code>java.lang.</code>&rdquo; is
1262:             * stripped from the beginning of exception names.</li>
1263:             *
1264:             * <li>The string &ldquo;<code>Exception</code>&rdquo; is stripped from
1265:             * the ends of exception names.</li>
1266:             *
1267:             * <li>Instances of <code>AnySubType</code> are indicated by surrounding
1268:             * the base type name with parentheses, rather than with the string 
1269:             * &ldquo;<code>Any_subtype_of_</code>&rdquo;</li>
1270:             *
1271:             * <li>If this <code>ThrowableSet</code> includes all the elements
1272:             * of {@link ThrowableSet.Manager#VM_ERRORS VM_ERRORS}, they are
1273:             * abbreviated as &ldquo;<code>vmErrors</code>&rdquo; rather than
1274:             * listed individually.</li>
1275:             * 
1276:             * @return An abbreviated representation of the contents of this set.
1277:             */
1278:            public String toAbbreviatedString() {
1279:                return toAbbreviatedString(exceptionsIncluded, '+')
1280:                        + toAbbreviatedString(exceptionsExcluded, '-');
1281:            }
1282:
1283:            /**
1284:             * <p>Utility method which prints the abbreviations of the
1285:             * elements in a passed {@link Set} of exception types.</p>
1286:             * 
1287:             * @param s The exceptions to print.
1288:             *
1289:             * @param connector The character to insert between exceptions.
1290:             *
1291:             * @return An abbreviated representation of the exceptions.
1292:             */
1293:            private String toAbbreviatedString(Set s, char connector) {
1294:                final String JAVA_LANG = "java.lang.";
1295:                final int JAVA_LANG_LENGTH = JAVA_LANG.length();
1296:                final String EXCEPTION = "Exception";
1297:                final int EXCEPTION_LENGTH = EXCEPTION.length();
1298:
1299:                Collection vmErrorThrowables = ThrowableSet.Manager.v().VM_ERRORS.exceptionsIncluded;
1300:                boolean containsAllVmErrors = s.containsAll(vmErrorThrowables);
1301:                StringBuffer buf = new StringBuffer();
1302:
1303:                if (containsAllVmErrors) {
1304:                    buf.append(connector);
1305:                    buf.append("vmErrors");
1306:                }
1307:
1308:                for (Iterator it = sortedThrowableIterator(s); it.hasNext();) {
1309:                    RefLikeType reflikeType = (RefLikeType) it.next();
1310:                    RefType baseType = null;
1311:                    if (reflikeType instanceof  RefType) {
1312:                        baseType = (RefType) reflikeType;
1313:                        if (vmErrorThrowables.contains(baseType)
1314:                                && containsAllVmErrors) {
1315:                            continue; // Already accounted for vmErrors.
1316:                        } else {
1317:                            buf.append(connector);
1318:                        }
1319:                    } else if (reflikeType instanceof  AnySubType) {
1320:                        buf.append(connector);
1321:                        buf.append('(');
1322:                        baseType = ((AnySubType) reflikeType).getBase();
1323:                    }
1324:                    String typeName = baseType.toString();
1325:                    if (typeName.startsWith(JAVA_LANG)) {
1326:                        typeName = typeName.substring(JAVA_LANG_LENGTH);
1327:                    }
1328:                    if (typeName.length() > EXCEPTION_LENGTH
1329:                            && typeName.endsWith(EXCEPTION)) {
1330:                        typeName = typeName.substring(0, typeName.length()
1331:                                - EXCEPTION_LENGTH);
1332:                    }
1333:                    buf.append(typeName);
1334:                    if (reflikeType instanceof  AnySubType) {
1335:                        buf.append(')');
1336:                    }
1337:                }
1338:                return buf.toString();
1339:            }
1340:
1341:            /** 
1342:             * A package-private method to provide unit tests with access to
1343:             * the {@link RefLikeType} objects which represent the
1344:             * <code>Throwable</code> types included in this set.
1345:             *
1346:             * @return an unmodifiable collection view of the
1347:             * <code>Throwable</code> types in this set.
1348:             */
1349:            Collection<Object> typesIncluded() {
1350:                return new AbstractCollection() {
1351:
1352:                    public Iterator iterator() {
1353:                        return new Iterator() {
1354:                            private final Iterator i = exceptionsIncluded
1355:                                    .iterator();
1356:
1357:                            public boolean hasNext() {
1358:                                return i.hasNext();
1359:                            }
1360:
1361:                            public Object next() {
1362:                                return i.next();
1363:                            }
1364:
1365:                            public void remove() {
1366:                                throw new UnsupportedOperationException();
1367:                            }
1368:                        };
1369:                    }
1370:
1371:                    public int size() {
1372:                        return exceptionsIncluded.size();
1373:                    }
1374:                };
1375:            }
1376:
1377:            /** 
1378:             * A package-private method to provide unit tests with access to
1379:             * the {@link RefLikeType} objects which represent the
1380:             * <code>Throwable</code> types excluded from this set.
1381:             *
1382:             * @return an unmodifiable collection view of the
1383:             * <code>Throwable</code> types excluded from this set.
1384:             */
1385:            Collection<Object> typesExcluded() {
1386:                return new AbstractCollection() {
1387:
1388:                    public Iterator iterator() {
1389:                        return new Iterator() {
1390:                            private final Iterator i = exceptionsExcluded
1391:                                    .iterator();
1392:
1393:                            public boolean hasNext() {
1394:                                return i.hasNext();
1395:                            }
1396:
1397:                            public Object next() {
1398:                                return i.next();
1399:                            }
1400:
1401:                            public void remove() {
1402:                                throw new UnsupportedOperationException();
1403:                            }
1404:                        };
1405:                    }
1406:
1407:                    public int size() {
1408:                        return exceptionsExcluded.size();
1409:                    }
1410:                };
1411:            }
1412:
1413:            /**
1414:             * A package-private method to provide unit tests with access to
1415:             * ThrowableSet's internals.
1416:             */
1417:            Map getMemoizedAdds() {
1418:                if (memoizedAdds == null) {
1419:                    return Collections.EMPTY_MAP;
1420:                } else {
1421:                    return Collections.unmodifiableMap(memoizedAdds);
1422:                }
1423:            }
1424:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.