Source Code Cross Referenced for BugInstance.java in  » Code-Analyzer » findbugs » edu » umd » cs » findbugs » 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 » findbugs » edu.umd.cs.findbugs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * FindBugs - Find bugs in Java programs
0003:         * Copyright (C) 2003-2005 University of Maryland
0004:         * 
0005:         * This library is free software; you can redistribute it and/or
0006:         * modify it under the terms of the GNU Lesser General Public
0007:         * License as published by the Free Software Foundation; either
0008:         * version 2.1 of the License, or (at your option) any later version.
0009:         * 
0010:         * This library is distributed in the hope that it will be useful,
0011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013:         * Lesser General Public License for more details.
0014:         * 
0015:         * You should have received a copy of the GNU Lesser General Public
0016:         * License along with this library; if not, write to the Free Software
0017:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0018:         */
0019:
0020:        package edu.umd.cs.findbugs;
0021:
0022:        import java.io.IOException;
0023:        import java.io.Serializable;
0024:        import java.math.BigInteger;
0025:        import java.security.MessageDigest;
0026:        import java.util.ArrayList;
0027:        import java.util.Collection;
0028:        import java.util.Collections;
0029:        import java.util.HashSet;
0030:        import java.util.Iterator;
0031:        import java.util.NoSuchElementException;
0032:        import java.util.Set;
0033:        import java.util.StringTokenizer;
0034:
0035:        import org.apache.bcel.Constants;
0036:        import org.apache.bcel.classfile.JavaClass;
0037:        import org.apache.bcel.classfile.Method;
0038:        import org.apache.bcel.generic.ConstantPoolGen;
0039:        import org.apache.bcel.generic.InstructionHandle;
0040:        import org.apache.bcel.generic.InvokeInstruction;
0041:        import org.apache.bcel.generic.MethodGen;
0042:        import org.objectweb.asm.tree.ClassNode;
0043:
0044:        import edu.umd.cs.findbugs.annotations.CheckForNull;
0045:        import edu.umd.cs.findbugs.annotations.NonNull;
0046:        import edu.umd.cs.findbugs.annotations.Nullable;
0047:        import edu.umd.cs.findbugs.ba.AnalysisContext;
0048:        import edu.umd.cs.findbugs.ba.ClassContext;
0049:        import edu.umd.cs.findbugs.ba.JavaClassAndMethod;
0050:        import edu.umd.cs.findbugs.ba.Location;
0051:        import edu.umd.cs.findbugs.ba.XFactory;
0052:        import edu.umd.cs.findbugs.ba.XField;
0053:        import edu.umd.cs.findbugs.ba.XMethod;
0054:        import edu.umd.cs.findbugs.ba.bcp.FieldVariable;
0055:        import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
0056:        import edu.umd.cs.findbugs.classfile.ClassDescriptor;
0057:        import edu.umd.cs.findbugs.classfile.FieldDescriptor;
0058:        import edu.umd.cs.findbugs.classfile.Global;
0059:        import edu.umd.cs.findbugs.classfile.IAnalysisCache;
0060:        import edu.umd.cs.findbugs.classfile.MethodDescriptor;
0061:        import edu.umd.cs.findbugs.util.ClassName;
0062:        import edu.umd.cs.findbugs.visitclass.DismantleBytecode;
0063:        import edu.umd.cs.findbugs.visitclass.PreorderVisitor;
0064:        import edu.umd.cs.findbugs.xml.XMLAttributeList;
0065:        import edu.umd.cs.findbugs.xml.XMLOutput;
0066:
0067:        /**
0068:         * An instance of a bug pattern.
0069:         * A BugInstance consists of several parts:
0070:         * <p/>
0071:         * <ul>
0072:         * <li> the type, which is a string indicating what kind of bug it is;
0073:         * used as a key for the FindBugsMessages resource bundle
0074:         * <li> the priority; how likely this instance is to actually be a bug
0075:         * <li> a list of <em>annotations</em>
0076:         * </ul>
0077:         * <p/>
0078:         * The annotations describe classes, methods, fields, source locations,
0079:         * and other relevant context information about the bug instance.
0080:         * Every BugInstance must have at least one ClassAnnotation, which
0081:         * describes the class in which the instance was found.  This is the
0082:         * "primary class annotation".
0083:         * <p/>
0084:         * <p> BugInstance objects are built up by calling a string of <code>add</code>
0085:         * methods.  (These methods all "return this", so they can be chained).
0086:         * Some of the add methods are specialized to get information automatically from
0087:         * a BetterVisitor or DismantleBytecode object.
0088:         *
0089:         * @author David Hovemeyer
0090:         * @see BugAnnotation
0091:         */
0092:        public class BugInstance implements  Comparable<BugInstance>,
0093:                XMLWriteableWithMessages, Serializable, Cloneable {
0094:            private static final long serialVersionUID = 1L;
0095:
0096:            private String type;
0097:            private int priority;
0098:            private ArrayList<BugAnnotation> annotationList;
0099:            private int cachedHashCode;
0100:            private @CheckForNull
0101:            BugDesignation userDesignation;
0102:            private BugProperty propertyListHead, propertyListTail;
0103:            private String uniqueId;
0104:            private String oldInstanceHash;
0105:            private String instanceHash;
0106:            private int instanceOccurrenceNum;
0107:            private int instanceOccurrenceMax;
0108:
0109:            /*
0110:             * The following fields are used for tracking Bug instances across multiple versions of software.
0111:             * They are meaningless in a BugCollection for just one version of software. 
0112:             */
0113:            private long firstVersion = 0;
0114:            private long lastVersion = -1;
0115:            private boolean introducedByChangeOfExistingClass;
0116:            private boolean removedByChangeOfPersistingClass;
0117:
0118:            /**
0119:             * This value is used to indicate that the cached hashcode
0120:             * is invalid, and should be recomputed.
0121:             */
0122:            private static final int INVALID_HASH_CODE = 0;
0123:
0124:            /**
0125:             * This value is used to indicate whether BugInstances should be reprioritized very low,
0126:             * when the BugPattern is marked as experimental
0127:             */
0128:            private static boolean adjustExperimental = false;
0129:
0130:            private static Set<String> bugTypes = Collections
0131:                    .synchronizedSet(new HashSet<String>());
0132:
0133:            /**
0134:             * Constructor.
0135:             *
0136:             * @param type     the bug type
0137:             * @param priority the bug priority
0138:             */
0139:            public BugInstance(String type, int priority) {
0140:                this .type = type;
0141:                this .priority = priority;
0142:                annotationList = new ArrayList<BugAnnotation>(4);
0143:                cachedHashCode = INVALID_HASH_CODE;
0144:
0145:                if (bugTypes.add(type)) {
0146:                    BugPattern p = I18N.instance().lookupBugPattern(type);
0147:                    if (p == null) {
0148:                        String msg = "Can't find definition of bug type "
0149:                                + type;
0150:                        AnalysisContext.logError(msg,
0151:                                new IllegalArgumentException(msg));
0152:                    }
0153:                }
0154:                if (adjustExperimental && isExperimental())
0155:                    this .priority = Detector.EXP_PRIORITY;
0156:                boundPriority();
0157:            }
0158:
0159:            private void boundPriority() {
0160:                priority = boundedPriority(priority);
0161:            }
0162:
0163:            @Override
0164:            public Object clone() {
0165:                BugInstance dup;
0166:
0167:                try {
0168:                    dup = (BugInstance) super .clone();
0169:
0170:                    // Do deep copying of mutable objects
0171:                    for (int i = 0; i < dup.annotationList.size(); ++i) {
0172:                        dup.annotationList.set(i,
0173:                                (BugAnnotation) dup.annotationList.get(i)
0174:                                        .clone());
0175:                    }
0176:                    dup.propertyListHead = dup.propertyListTail = null;
0177:                    for (Iterator<BugProperty> i = propertyIterator(); i
0178:                            .hasNext();) {
0179:                        dup.addProperty((BugProperty) i.next().clone());
0180:                    }
0181:
0182:                    return dup;
0183:                } catch (CloneNotSupportedException e) {
0184:                    throw new AssertionError(e);
0185:                }
0186:            }
0187:
0188:            /**
0189:             * Create a new BugInstance.
0190:             * This is the constructor that should be used by Detectors.
0191:             * 
0192:             * @param detector the Detector that is reporting the BugInstance
0193:             * @param type     the bug type
0194:             * @param priority the bug priority
0195:             */
0196:            public BugInstance(Detector detector, String type, int priority) {
0197:                this (type, priority);
0198:
0199:                if (detector != null) {
0200:                    // Adjust priority if required
0201:                    DetectorFactory factory = DetectorFactoryCollection
0202:                            .instance().getFactoryByClassName(
0203:                                    detector.getClass().getName());
0204:                    if (factory != null) {
0205:                        this .priority += factory.getPriorityAdjustment();
0206:                        boundPriority();
0207:                    }
0208:                }
0209:
0210:            }
0211:
0212:            /**
0213:             * Create a new BugInstance.
0214:             * This is the constructor that should be used by Detectors.
0215:             * 
0216:             * @param detector the Detector2 that is reporting the BugInstance
0217:             * @param type     the bug type
0218:             * @param priority the bug priority
0219:             */
0220:            public BugInstance(Detector2 detector, String type, int priority) {
0221:                this (type, priority);
0222:
0223:                if (detector != null) {
0224:                    // Adjust priority if required
0225:                    DetectorFactory factory = DetectorFactoryCollection
0226:                            .instance().getFactoryByClassName(
0227:                                    detector.getDetectorClassName());
0228:                    if (factory != null) {
0229:                        this .priority += factory.getPriorityAdjustment();
0230:                        boundPriority();
0231:                    }
0232:                }
0233:
0234:            }
0235:
0236:            public static void setAdjustExperimental(boolean adjust) {
0237:                adjustExperimental = adjust;
0238:            }
0239:
0240:            /* ----------------------------------------------------------------------
0241:             * Accessors
0242:             * ---------------------------------------------------------------------- */
0243:
0244:            /**
0245:             * Get the bug type.
0246:             */
0247:            public String getType() {
0248:                return type;
0249:            }
0250:
0251:            /**
0252:             * Get the BugPattern.
0253:             */
0254:            public @NonNull
0255:            BugPattern getBugPattern() {
0256:                BugPattern result = I18N.instance().lookupBugPattern(getType());
0257:                if (result != null)
0258:                    return result;
0259:                AnalysisContext
0260:                        .logError("Unable to find description of bug pattern "
0261:                                + getType());
0262:                result = I18N.instance().lookupBugPattern("UNKNOWN");
0263:                if (result != null)
0264:                    return result;
0265:                return BugPattern.REALLY_UNKNOWN;
0266:            }
0267:
0268:            /**
0269:             * Get the bug priority.
0270:             */
0271:            public int getPriority() {
0272:                return priority;
0273:            }
0274:
0275:            /**
0276:             * Get a string describing the bug priority and type.
0277:             * e.g. "High Priority Correctness"
0278:             * @return a string describing the bug priority and type
0279:             */
0280:            public String getPriorityTypeString() {
0281:                String priorityString = getPriorityString();
0282:                BugPattern bugPattern = this .getBugPattern();
0283:                //then get the category and put everything together
0284:                String categoryString;
0285:                if (bugPattern == null)
0286:                    categoryString = "Unknown category for " + getType();
0287:                else
0288:                    categoryString = I18N.instance().getBugCategoryDescription(
0289:                            bugPattern.getCategory());
0290:                return priorityString + " Priority " + categoryString;
0291:                //TODO: internationalize the word "Priority"
0292:            }
0293:
0294:            public String getPriorityTypeAbbreviation() {
0295:                String priorityString = getPriorityAbbreviation();
0296:                return priorityString + " " + getCategoryAbbrev();
0297:            }
0298:
0299:            public String getCategoryAbbrev() {
0300:                BugPattern bugPattern = getBugPattern();
0301:                if (bugPattern == null)
0302:                    return "?";
0303:                return bugPattern.getCategoryAbbrev();
0304:            }
0305:
0306:            public String getPriorityString() {
0307:                //first, get the priority
0308:                int value = this .getPriority();
0309:                String priorityString;
0310:                if (value == Detector.HIGH_PRIORITY)
0311:                    priorityString = edu.umd.cs.findbugs.L10N.getLocalString(
0312:                            "sort.priority_high", "High");
0313:                else if (value == Detector.NORMAL_PRIORITY)
0314:                    priorityString = edu.umd.cs.findbugs.L10N.getLocalString(
0315:                            "sort.priority_normal", "Medium");
0316:                else if (value == Detector.LOW_PRIORITY)
0317:                    priorityString = edu.umd.cs.findbugs.L10N.getLocalString(
0318:                            "sort.priority_low", "Low");
0319:                else if (value == Detector.EXP_PRIORITY)
0320:                    priorityString = edu.umd.cs.findbugs.L10N.getLocalString(
0321:                            "sort.priority_experimental", "Experimental");
0322:                else
0323:                    priorityString = edu.umd.cs.findbugs.L10N.getLocalString(
0324:                            "sort.priority_ignore", "Ignore"); // This probably shouldn't ever happen, but what the hell, let's be complete
0325:                return priorityString;
0326:            }
0327:
0328:            public String getPriorityAbbreviation() {
0329:                return getPriorityString().substring(0, 1);
0330:            }
0331:
0332:            /**
0333:             * Set the bug priority.
0334:             */
0335:            public void setPriority(int p) {
0336:                priority = boundedPriority(p);
0337:            }
0338:
0339:            private int boundedPriority(int p) {
0340:                return Math.max(Detector.HIGH_PRIORITY, Math.min(
0341:                        Detector.IGNORE_PRIORITY, p));
0342:            }
0343:
0344:            public void raisePriority() {
0345:                priority = boundedPriority(priority - 1);
0346:
0347:            }
0348:
0349:            public void lowerPriority() {
0350:                priority = boundedPriority(priority + 1);
0351:            }
0352:
0353:            public void lowerPriorityALot() {
0354:                priority = boundedPriority(priority + 2);
0355:            }
0356:
0357:            /**
0358:             * Is this bug instance the result of an experimental detector?
0359:             */
0360:            public boolean isExperimental() {
0361:                BugPattern pattern = getBugPattern();
0362:                return (pattern != null) && pattern.isExperimental();
0363:            }
0364:
0365:            /**
0366:             * Get the primary class annotation, which indicates where the bug occurs.
0367:             */
0368:            public ClassAnnotation getPrimaryClass() {
0369:                return findAnnotationOfType(ClassAnnotation.class);
0370:            }
0371:
0372:            /**
0373:             * Get the primary method annotation, which indicates where the bug occurs.
0374:             */
0375:            public MethodAnnotation getPrimaryMethod() {
0376:                return findAnnotationOfType(MethodAnnotation.class);
0377:            }
0378:
0379:            /**
0380:             * Get the primary method annotation, which indicates where the bug occurs.
0381:             */
0382:            public FieldAnnotation getPrimaryField() {
0383:                return findAnnotationOfType(FieldAnnotation.class);
0384:            }
0385:
0386:            public BugInstance lowerPriorityIfDeprecated() {
0387:                MethodAnnotation m = getPrimaryMethod();
0388:                if (m != null && XFactory.createXMethod(m).isDeprecated())
0389:                    lowerPriority();
0390:                FieldAnnotation f = getPrimaryField();
0391:                if (f != null && XFactory.createXField(f).isDeprecated())
0392:                    lowerPriority();
0393:                return this ;
0394:            }
0395:
0396:            /**
0397:             * Find the first BugAnnotation in the list of annotations
0398:             * that is the same type or a subtype as the given Class parameter.
0399:             * 
0400:             * @param cls the Class parameter
0401:             * @return the first matching BugAnnotation of the given type,
0402:             *         or null if there is no such BugAnnotation
0403:             */
0404:            private <T extends BugAnnotation> T findAnnotationOfType(
0405:                    Class<T> cls) {
0406:                for (Iterator<BugAnnotation> i = annotationIterator(); i
0407:                        .hasNext();) {
0408:                    BugAnnotation annotation = i.next();
0409:                    if (cls.isAssignableFrom(annotation.getClass()))
0410:                        return (T) annotation;
0411:                }
0412:                return null;
0413:            }
0414:
0415:            public LocalVariableAnnotation getPrimaryLocalVariableAnnotation() {
0416:                for (BugAnnotation annotation : annotationList)
0417:                    if (annotation instanceof  LocalVariableAnnotation)
0418:                        return (LocalVariableAnnotation) annotation;
0419:                return null;
0420:            }
0421:
0422:            /**
0423:             * Get the primary source line annotation.
0424:             * There is guaranteed to be one (unless some Detector constructed
0425:             * an invalid BugInstance).
0426:             *
0427:             * @return the source line annotation
0428:             */
0429:            public SourceLineAnnotation getPrimarySourceLineAnnotation() {
0430:                // Highest priority: return the first top level source line annotation
0431:                for (BugAnnotation annotation : annotationList) {
0432:                    if (annotation instanceof  SourceLineAnnotation)
0433:                        return (SourceLineAnnotation) annotation;
0434:                }
0435:
0436:                // Next: Try primary method, primary field, primary class
0437:                SourceLineAnnotation srcLine;
0438:                if ((srcLine = inspectPackageMemberSourceLines(getPrimaryMethod())) != null)
0439:                    return srcLine;
0440:                if ((srcLine = inspectPackageMemberSourceLines(getPrimaryField())) != null)
0441:                    return srcLine;
0442:                if ((srcLine = inspectPackageMemberSourceLines(getPrimaryClass())) != null)
0443:                    return srcLine;
0444:
0445:                // Last resort: throw exception
0446:                throw new IllegalStateException(
0447:                        "BugInstance must contain at least one class, method, or field annotation");
0448:            }
0449:
0450:            public String getInstanceKey() {
0451:                StringBuffer buf = new StringBuffer(type);
0452:                for (BugAnnotation annotation : annotationList) {
0453:                    if (annotation instanceof  SourceLineAnnotation
0454:                            || annotation instanceof  MethodAnnotation
0455:                            && !annotation.isSignificant()) {
0456:                        // do nothing
0457:                    } else {
0458:                        buf.append(":");
0459:                        buf.append(annotation.format("hash", null));
0460:                    }
0461:                }
0462:                return buf.toString();
0463:            }
0464:
0465:            /**
0466:             * If given PackageMemberAnnotation is non-null, return its
0467:             * SourceLineAnnotation.
0468:             * 
0469:             * @param packageMember
0470:             *            a PackageMemberAnnotation
0471:             * @return the PackageMemberAnnotation's SourceLineAnnotation, or null if
0472:             *         there is no SourceLineAnnotation
0473:             */
0474:            private SourceLineAnnotation inspectPackageMemberSourceLines(
0475:                    PackageMemberAnnotation packageMember) {
0476:                return (packageMember != null) ? packageMember.getSourceLines()
0477:                        : null;
0478:            }
0479:
0480:            /**
0481:             * Get an Iterator over all bug annotations.
0482:             */
0483:            public Iterator<BugAnnotation> annotationIterator() {
0484:                return annotationList.iterator();
0485:            }
0486:
0487:            /**
0488:             * Get the abbreviation of this bug instance's BugPattern.
0489:             * This is the same abbreviation used by the BugCode which
0490:             * the BugPattern is a particular species of.
0491:             */
0492:            public String getAbbrev() {
0493:                BugPattern pattern = getBugPattern();
0494:                return pattern != null ? pattern.getAbbrev()
0495:                        : "<unknown bug pattern>";
0496:            }
0497:
0498:            /** set the user designation object. This will clobber any
0499:             *  existing annotationText (or any other BugDesignation field). */
0500:            public void setUserDesignation(BugDesignation bd) {
0501:                userDesignation = bd;
0502:            }
0503:
0504:            /** return the user designation object, which may be null.
0505:             * 
0506:             *  A previous calls to getSafeUserDesignation(), setAnnotationText(),
0507:             *  or setUserDesignation() will ensure it will be non-null
0508:             *  [barring an intervening setUserDesignation(null)].
0509:             *  @see #getNonnullUserDesignation() */
0510:            @Nullable
0511:            public BugDesignation getUserDesignation() {
0512:                return userDesignation;
0513:            }
0514:
0515:            /** return the user designation object, creating one if
0516:             *  necessary. So calling
0517:             *  <code>getSafeUserDesignation().setDesignation("HARMLESS")</code>
0518:             *  will always work without the possibility of a NullPointerException.
0519:             *  @see #getUserDesignation() */
0520:            @NonNull
0521:            public BugDesignation getNonnullUserDesignation() {
0522:                if (userDesignation == null)
0523:                    userDesignation = new BugDesignation();
0524:                return userDesignation;
0525:            }
0526:
0527:            /** Get the user designation key.
0528:             *  E.g., "MOSTLY_HARMLESS", "CRITICAL", "NOT_A_BUG", etc.
0529:             *
0530:             *  If the user designation object is null,returns UNCLASSIFIED.
0531:             *
0532:             *  To set the user designation key, call
0533:             *  <code>getSafeUserDesignation().setDesignation("HARMLESS")</code>.
0534:             * 
0535:             *  @see I18N#getUserDesignation(String key)
0536:             *  @return the user designation key
0537:             */
0538:            @NonNull
0539:            public String getUserDesignationKey() {
0540:                BugDesignation userDesignation = this .userDesignation;
0541:                if (userDesignation == null)
0542:                    return BugDesignation.UNCLASSIFIED;
0543:                return userDesignation.getDesignationKey();
0544:            }
0545:
0546:            /**
0547:             * Set the user annotation text.
0548:             *
0549:             * @param annotationText the user annotation text
0550:             */
0551:            public void setAnnotationText(String annotationText) {
0552:                getNonnullUserDesignation().setAnnotationText(annotationText);
0553:            }
0554:
0555:            /**
0556:             * Get the user annotation text.
0557:             *
0558:             * @return the user annotation text
0559:             */
0560:            @NonNull
0561:            public String getAnnotationText() {
0562:                BugDesignation userDesignation = this .userDesignation;
0563:                if (userDesignation == null)
0564:                    return "";
0565:                String s = userDesignation.getAnnotationText();
0566:                if (s == null)
0567:                    return "";
0568:                return s;
0569:            }
0570:
0571:            /**
0572:             * Determine whether or not the annotation text contains
0573:             * the given word.
0574:             *
0575:             * @param word the word
0576:             * @return true if the annotation text contains the word, false otherwise
0577:             */
0578:            public boolean annotationTextContainsWord(String word) {
0579:                return getTextAnnotationWords().contains(word);
0580:            }
0581:
0582:            /**
0583:             * Get set of words in the text annotation.
0584:             */
0585:            public Set<String> getTextAnnotationWords() {
0586:                HashSet<String> result = new HashSet<String>();
0587:
0588:                StringTokenizer tok = new StringTokenizer(getAnnotationText(),
0589:                        " \t\r\n\f.,:;-");
0590:                while (tok.hasMoreTokens()) {
0591:                    result.add(tok.nextToken());
0592:                }
0593:                return result;
0594:            }
0595:
0596:            /**
0597:             * Get the BugInstance's unique id.
0598:             * 
0599:             * @return the unique id, or null if no unique id has been assigned
0600:             * 
0601:             * Deprecated, since it isn't persistent
0602:             */
0603:            @Deprecated
0604:            public String getUniqueId() {
0605:                return uniqueId;
0606:            }
0607:
0608:            /**
0609:             * Set the unique id of the BugInstance.
0610:             * 
0611:             * @param uniqueId the unique id
0612:             * 
0613:             *   * Deprecated, since it isn't persistent
0614:             */
0615:            @Deprecated
0616:            void setUniqueId(String uniqueId) {
0617:                this .uniqueId = uniqueId;
0618:            }
0619:
0620:            /* ----------------------------------------------------------------------
0621:             * Property accessors
0622:             * ---------------------------------------------------------------------- */
0623:
0624:            private class BugPropertyIterator implements  Iterator<BugProperty> {
0625:                private BugProperty prev, cur;
0626:                private boolean removed;
0627:
0628:                /* (non-Javadoc)
0629:                 * @see java.util.Iterator#hasNext()
0630:                 */
0631:                public boolean hasNext() {
0632:                    return findNext() != null;
0633:                }
0634:
0635:                /* (non-Javadoc)
0636:                 * @see java.util.Iterator#next()
0637:                 */
0638:                public BugProperty next() {
0639:                    BugProperty next = findNext();
0640:                    if (next == null)
0641:                        throw new NoSuchElementException();
0642:                    prev = cur;
0643:                    cur = next;
0644:                    removed = false;
0645:                    return cur;
0646:                }
0647:
0648:                /* (non-Javadoc)
0649:                 * @see java.util.Iterator#remove()
0650:                 */
0651:                public void remove() {
0652:                    if (cur == null || removed)
0653:                        throw new IllegalStateException();
0654:                    if (prev == null) {
0655:                        propertyListHead = cur.getNext();
0656:                    } else {
0657:                        prev.setNext(cur.getNext());
0658:                    }
0659:                    if (cur == propertyListTail) {
0660:                        propertyListTail = prev;
0661:                    }
0662:                    removed = true;
0663:                }
0664:
0665:                private BugProperty findNext() {
0666:                    return cur == null ? propertyListHead : cur.getNext();
0667:                }
0668:
0669:            }
0670:
0671:            /**
0672:             * Get value of given property.
0673:             * 
0674:             * @param name name of the property to get
0675:             * @return the value of the named property, or null if
0676:             *         the property has not been set
0677:             */
0678:            public String getProperty(String name) {
0679:                BugProperty prop = lookupProperty(name);
0680:                return prop != null ? prop.getValue() : null;
0681:            }
0682:
0683:            /**
0684:             * Get value of given property, returning given default
0685:             * value if the property has not been set.
0686:             * 
0687:             * @param name         name of the property to get
0688:             * @param defaultValue default value to return if propery is not set
0689:             * @return the value of the named property, or the default
0690:             *         value if the property has not been set
0691:             */
0692:            public String getProperty(String name, String defaultValue) {
0693:                String value = getProperty(name);
0694:                return value != null ? value : defaultValue;
0695:            }
0696:
0697:            /**
0698:             * Get an Iterator over the properties defined in this BugInstance.
0699:             * 
0700:             * @return Iterator over properties
0701:             */
0702:            public Iterator<BugProperty> propertyIterator() {
0703:                return new BugPropertyIterator();
0704:            }
0705:
0706:            /**
0707:             * Set value of given property.
0708:             * 
0709:             * @param name  name of the property to set
0710:             * @param value the value of the property
0711:             * @return this object, so calls can be chained
0712:             */
0713:            public BugInstance setProperty(String name, String value) {
0714:                BugProperty prop = lookupProperty(name);
0715:                if (prop != null) {
0716:                    prop.setValue(value);
0717:                } else {
0718:                    prop = new BugProperty(name, value);
0719:                    addProperty(prop);
0720:                }
0721:                return this ;
0722:            }
0723:
0724:            /**
0725:             * Look up a property by name.
0726:             * 
0727:             * @param name name of the property to look for
0728:             * @return the BugProperty with the given name,
0729:             *         or null if the property has not been set
0730:             */
0731:            public BugProperty lookupProperty(String name) {
0732:                BugProperty prop = propertyListHead;
0733:
0734:                while (prop != null) {
0735:                    if (prop.getName().equals(name))
0736:                        break;
0737:                    prop = prop.getNext();
0738:                }
0739:
0740:                return prop;
0741:            }
0742:
0743:            /**
0744:             * Delete property with given name.
0745:             * 
0746:             * @param name name of the property to delete
0747:             * @return true if a property with that name was deleted,
0748:             *         or false if there is no such property
0749:             */
0750:            public boolean deleteProperty(String name) {
0751:                BugProperty prev = null;
0752:                BugProperty prop = propertyListHead;
0753:
0754:                while (prop != null) {
0755:                    if (prop.getName().equals(name))
0756:                        break;
0757:                    prev = prop;
0758:                    prop = prop.getNext();
0759:                }
0760:
0761:                if (prop != null) {
0762:                    if (prev != null) {
0763:                        // Deleted node in interior or at tail of list
0764:                        prev.setNext(prop.getNext());
0765:                    } else {
0766:                        // Deleted node at head of list
0767:                        propertyListHead = prop.getNext();
0768:                    }
0769:
0770:                    if (prop.getNext() == null) {
0771:                        // Deleted node at end of list
0772:                        propertyListTail = prev;
0773:                    }
0774:
0775:                    return true;
0776:                } else {
0777:                    // No such property
0778:                    return false;
0779:                }
0780:            }
0781:
0782:            private void addProperty(BugProperty prop) {
0783:                if (propertyListTail != null) {
0784:                    propertyListTail.setNext(prop);
0785:                    propertyListTail = prop;
0786:                } else {
0787:                    propertyListHead = propertyListTail = prop;
0788:                }
0789:                prop.setNext(null);
0790:            }
0791:
0792:            /* ----------------------------------------------------------------------
0793:             * Generic BugAnnotation adders
0794:             * ---------------------------------------------------------------------- */
0795:
0796:            /**
0797:             * Add a Collection of BugAnnotations.
0798:             * 
0799:             * @param annotationCollection Collection of BugAnnotations
0800:             */
0801:            public BugInstance addAnnotations(
0802:                    Collection<? extends BugAnnotation> annotationCollection) {
0803:                for (BugAnnotation annotation : annotationCollection) {
0804:                    add(annotation);
0805:                }
0806:                return this ;
0807:            }
0808:
0809:            /* ----------------------------------------------------------------------
0810:             * Combined annotation adders
0811:             * ---------------------------------------------------------------------- */
0812:
0813:            public BugInstance addClassAndMethod(
0814:                    MethodDescriptor methodDescriptor) {
0815:                addClass(methodDescriptor.getSlashedClassName());
0816:                add(MethodAnnotation.fromMethodDescriptor(methodDescriptor));
0817:                return this ;
0818:            }
0819:
0820:            /**
0821:             * Add a class annotation and a method annotation for the class and method
0822:             * which the given visitor is currently visiting.
0823:             *
0824:             * @param visitor the BetterVisitor
0825:             * @return this object
0826:             */
0827:            public BugInstance addClassAndMethod(PreorderVisitor visitor) {
0828:                addClass(visitor);
0829:                addMethod(visitor);
0830:                return this ;
0831:            }
0832:
0833:            /**
0834:             * Add class and method annotations for given method.
0835:             *
0836:             * @param methodAnnotation  the method
0837:             * @return this object
0838:             */
0839:            public BugInstance addClassAndMethod(
0840:                    MethodAnnotation methodAnnotation) {
0841:                addClass(methodAnnotation.getClassName());
0842:                addMethod(methodAnnotation);
0843:                return this ;
0844:            }
0845:
0846:            /**
0847:             * Add class and method annotations for given method.
0848:             *
0849:             * @param methodGen  the method
0850:             * @param sourceFile source file the method is defined in
0851:             * @return this object
0852:             */
0853:            public BugInstance addClassAndMethod(MethodGen methodGen,
0854:                    String sourceFile) {
0855:                addClass(methodGen.getClassName());
0856:                addMethod(methodGen, sourceFile);
0857:                return this ;
0858:            }
0859:
0860:            /**
0861:             * Add class and method annotations for given class and method.
0862:             *  
0863:             * @param javaClass the class
0864:             * @param method    the method
0865:             * @return this object
0866:             */
0867:            public BugInstance addClassAndMethod(JavaClass javaClass,
0868:                    Method method) {
0869:                addClass(javaClass.getClassName());
0870:                addMethod(javaClass, method);
0871:                return this ;
0872:            }
0873:
0874:            /* ----------------------------------------------------------------------
0875:             * Class annotation adders
0876:             * ---------------------------------------------------------------------- */
0877:
0878:            /**
0879:             * Add a class annotation.  If this is the first class annotation added,
0880:             * it becomes the primary class annotation.
0881:             *
0882:             * @param className the name of the class
0883:             * @param sourceFileName the source file of the class
0884:             * @return this object
0885:             * @deprecated use addClass(String) instead
0886:             */
0887:            public BugInstance addClass(String className, String sourceFileName) {
0888:                ClassAnnotation classAnnotation = new ClassAnnotation(className);
0889:                add(classAnnotation);
0890:                return this ;
0891:            }
0892:
0893:            /**
0894:             * Add a class annotation.  If this is the first class annotation added,
0895:             * it becomes the primary class annotation.
0896:             *
0897:             * @param className the name of the class
0898:             * @return this object
0899:             */
0900:            public BugInstance addClass(String className) {
0901:                className = ClassName.toDottedClassName(className);
0902:                ClassAnnotation classAnnotation = new ClassAnnotation(className);
0903:                add(classAnnotation);
0904:                return this ;
0905:            }
0906:
0907:            /**
0908:             * Add a class annotation for the classNode.
0909:             *
0910:             * @param classNode the ASM visitor
0911:             * @return this object
0912:             */
0913:            public BugInstance addClass(ClassNode classNode) {
0914:                ClassAnnotation classAnnotation = new ClassAnnotation(
0915:                        classNode.name);
0916:                add(classAnnotation);
0917:                return this ;
0918:            }
0919:
0920:            /**
0921:             * Add a class annotation.  If this is the first class annotation added,
0922:             * it becomes the primary class annotation.
0923:             * 
0924:             * @param classDescriptor the class to add
0925:             * @return this object
0926:             */
0927:            public BugInstance addClass(ClassDescriptor classDescriptor) {
0928:                add(ClassAnnotation.fromClassDescriptor(classDescriptor));
0929:                return this ;
0930:            }
0931:
0932:            /**
0933:             * Add a class annotation.  If this is the first class annotation added,
0934:             * it becomes the primary class annotation.
0935:             *
0936:             * @param jclass the JavaClass object for the class
0937:             * @return this object
0938:             */
0939:            public BugInstance addClass(JavaClass jclass) {
0940:                addClass(jclass.getClassName());
0941:                return this ;
0942:            }
0943:
0944:            /**
0945:             * Add a class annotation for the class that the visitor is currently visiting.
0946:             *
0947:             * @param visitor the BetterVisitor
0948:             * @return this object
0949:             */
0950:            public BugInstance addClass(PreorderVisitor visitor) {
0951:                String className = visitor.getDottedClassName();
0952:                addClass(className);
0953:                return this ;
0954:            }
0955:
0956:            /**
0957:             * Add a class annotation for the superclass of the class the visitor
0958:             * is currently visiting.
0959:             *
0960:             * @param visitor the BetterVisitor
0961:             * @return this object
0962:             */
0963:            public BugInstance addSuperclass(PreorderVisitor visitor) {
0964:                String className = visitor.getSuperclassName();
0965:                addClass(className);
0966:                return this ;
0967:            }
0968:
0969:            /* ----------------------------------------------------------------------
0970:             * Type annotation adders
0971:             * ---------------------------------------------------------------------- */
0972:
0973:            /**
0974:             * Add a type annotation. Handy for referring to array types.
0975:             *
0976:             * <p>For information on type descriptors,
0977:             * <br>see http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#14152
0978:             * <br>or  http://www.murrayc.com/learning/java/java_classfileformat.shtml#TypeDescriptors
0979:             * 
0980:             * @param typeDescriptor a jvm type descriptor, such as "[I"
0981:             * @return this object
0982:             */
0983:            public BugInstance addType(String typeDescriptor) {
0984:                TypeAnnotation typeAnnotation = new TypeAnnotation(
0985:                        typeDescriptor);
0986:                add(typeAnnotation);
0987:                return this ;
0988:            }
0989:
0990:            public BugInstance addFoundAndExpectedType(String foundType,
0991:                    String expectedType) {
0992:                add(new TypeAnnotation(foundType)).describe(
0993:                        TypeAnnotation.FOUND_ROLE);
0994:                add(new TypeAnnotation(expectedType)).describe(
0995:                        TypeAnnotation.EXPECTED_ROLE);
0996:                return this ;
0997:            }
0998:
0999:            public BugInstance addTypeOfNamedClass(String typeName) {
1000:                TypeAnnotation typeAnnotation = new TypeAnnotation("L"
1001:                        + typeName.replace('.', '/') + ";");
1002:                add(typeAnnotation);
1003:                return this ;
1004:            }
1005:
1006:            /* ----------------------------------------------------------------------
1007:             * Field annotation adders
1008:             * ---------------------------------------------------------------------- */
1009:
1010:            /**
1011:             * Add a field annotation.
1012:             *
1013:             * @param className name of the class containing the field
1014:             * @param fieldName the name of the field
1015:             * @param fieldSig  type signature of the field
1016:             * @param isStatic  whether or not the field is static
1017:             * @return this object
1018:             */
1019:            public BugInstance addField(String className, String fieldName,
1020:                    String fieldSig, boolean isStatic) {
1021:                addField(new FieldAnnotation(className, fieldName, fieldSig,
1022:                        isStatic));
1023:                return this ;
1024:            }
1025:
1026:            /**
1027:             * Add a field annotation.
1028:             *
1029:             * @param className name of the class containing the field
1030:             * @param fieldName the name of the field
1031:             * @param fieldSig  type signature of the field
1032:             * @param isStatic  whether or not the field is static
1033:             * @return this object
1034:             */
1035:            public BugInstance addField(String className, String fieldName,
1036:                    String fieldSig, int accessFlags) {
1037:                addField(new FieldAnnotation(className, fieldName, fieldSig,
1038:                        accessFlags));
1039:                return this ;
1040:            }
1041:
1042:            public BugInstance addField(PreorderVisitor visitor) {
1043:                FieldAnnotation fieldAnnotation = FieldAnnotation
1044:                        .fromVisitedField(visitor);
1045:                return addField(fieldAnnotation);
1046:            }
1047:
1048:            /**
1049:             * Add a field annotation
1050:             *
1051:             * @param fieldAnnotation the field annotation
1052:             * @return this object
1053:             */
1054:            public BugInstance addField(FieldAnnotation fieldAnnotation) {
1055:                add(fieldAnnotation);
1056:                return this ;
1057:            }
1058:
1059:            /**
1060:             * Add a field annotation for a FieldVariable matched in a ByteCodePattern.
1061:             *
1062:             * @param field the FieldVariable
1063:             * @return this object
1064:             */
1065:            public BugInstance addField(FieldVariable field) {
1066:                return addField(field.getClassName(), field.getFieldName(),
1067:                        field.getFieldSig(), field.isStatic());
1068:            }
1069:
1070:            /**
1071:             * Add a field annotation for an XField.
1072:             *
1073:             * @param xfield the XField
1074:             * @return this object
1075:             */
1076:            public BugInstance addOptionalField(@CheckForNull
1077:            XField xfield) {
1078:                if (xfield == null)
1079:                    return this ;
1080:                return addField(xfield.getClassName(), xfield.getName(), xfield
1081:                        .getSignature(), xfield.isStatic());
1082:            }
1083:
1084:            /**
1085:             * Add a field annotation for an XField.
1086:             *
1087:             * @param xfield the XField
1088:             * @return this object
1089:             */
1090:            public BugInstance addField(XField xfield) {
1091:                return addField(xfield.getClassName(), xfield.getName(), xfield
1092:                        .getSignature(), xfield.isStatic());
1093:            }
1094:
1095:            /**
1096:             * Add a field annotation for a FieldDescriptor.
1097:             * 
1098:             * @param fieldDescriptor the FieldDescriptor
1099:             * @return this object
1100:             */
1101:            public BugInstance addField(FieldDescriptor fieldDescriptor) {
1102:                FieldAnnotation fieldAnnotation = FieldAnnotation
1103:                        .fromFieldDescriptor(fieldDescriptor);
1104:                add(fieldAnnotation);
1105:                return this ;
1106:            }
1107:
1108:            /**
1109:             * Add a field annotation for the field which has just been accessed
1110:             * by the method currently being visited by given visitor.
1111:             * Assumes that a getfield/putfield or getstatic/putstatic
1112:             * has just been seen.
1113:             *
1114:             * @param visitor the DismantleBytecode object
1115:             * @return this object
1116:             */
1117:            public BugInstance addReferencedField(DismantleBytecode visitor) {
1118:                FieldAnnotation f = FieldAnnotation
1119:                        .fromReferencedField(visitor);
1120:                addField(f);
1121:                return this ;
1122:            }
1123:
1124:            /**
1125:             * Add a field annotation for the field referenced by the FieldAnnotation parameter
1126:             */
1127:            public BugInstance addReferencedField(FieldAnnotation fa) {
1128:                addField(fa);
1129:                return this ;
1130:            }
1131:
1132:            /**
1133:             * Add a field annotation for the field which is being visited by
1134:             * given visitor.
1135:             *
1136:             * @param visitor the visitor
1137:             * @return this object
1138:             */
1139:            public BugInstance addVisitedField(PreorderVisitor visitor) {
1140:                FieldAnnotation f = FieldAnnotation.fromVisitedField(visitor);
1141:                addField(f);
1142:                return this ;
1143:            }
1144:
1145:            /* ----------------------------------------------------------------------
1146:             * Method annotation adders
1147:             * ---------------------------------------------------------------------- */
1148:
1149:            /**
1150:             * Add a method annotation.  If this is the first method annotation added,
1151:             * it becomes the primary method annotation.
1152:             *
1153:             * @param className  name of the class containing the method
1154:             * @param methodName name of the method
1155:             * @param methodSig  type signature of the method
1156:             * @param isStatic   true if the method is static, false otherwise
1157:             * @return this object
1158:             */
1159:            public BugInstance addMethod(String className, String methodName,
1160:                    String methodSig, boolean isStatic) {
1161:                addMethod(MethodAnnotation.fromForeignMethod(className,
1162:                        methodName, methodSig, isStatic));
1163:                return this ;
1164:            }
1165:
1166:            /**
1167:             * Add a method annotation.  If this is the first method annotation added,
1168:             * it becomes the primary method annotation.
1169:             *
1170:             * @param className  name of the class containing the method
1171:             * @param methodName name of the method
1172:             * @param methodSig  type signature of the method
1173:             * @param accessFlags   accessFlags for the method
1174:             * @return this object
1175:             */
1176:            public BugInstance addMethod(String className, String methodName,
1177:                    String methodSig, int accessFlags) {
1178:                addMethod(MethodAnnotation.fromForeignMethod(className,
1179:                        methodName, methodSig, accessFlags));
1180:                return this ;
1181:            }
1182:
1183:            /**
1184:             * Add a method annotation.  If this is the first method annotation added,
1185:             * it becomes the primary method annotation.
1186:             * If the method has source line information, then a SourceLineAnnotation
1187:             * is added to the method.
1188:             *
1189:             * @param methodGen  the MethodGen object for the method
1190:             * @param sourceFile source file method is defined in
1191:             * @return this object
1192:             */
1193:            public BugInstance addMethod(MethodGen methodGen, String sourceFile) {
1194:                String className = methodGen.getClassName();
1195:                MethodAnnotation methodAnnotation = new MethodAnnotation(
1196:                        className, methodGen.getName(), methodGen
1197:                                .getSignature(), methodGen.isStatic());
1198:                addMethod(methodAnnotation);
1199:                addSourceLinesForMethod(methodAnnotation, SourceLineAnnotation
1200:                        .fromVisitedMethod(methodGen, sourceFile));
1201:                return this ;
1202:            }
1203:
1204:            /**
1205:             * Add a method annotation.  If this is the first method annotation added,
1206:             * it becomes the primary method annotation.
1207:             * If the method has source line information, then a SourceLineAnnotation
1208:             * is added to the method.
1209:             *
1210:             * @param javaClass the class the method is defined in
1211:             * @param method    the method
1212:             * @return this object
1213:             */
1214:            public BugInstance addMethod(JavaClass javaClass, Method method) {
1215:                MethodAnnotation methodAnnotation = new MethodAnnotation(
1216:                        javaClass.getClassName(), method.getName(), method
1217:                                .getSignature(), method.isStatic());
1218:                SourceLineAnnotation methodSourceLines = SourceLineAnnotation
1219:                        .forEntireMethod(javaClass, method);
1220:                methodAnnotation.setSourceLines(methodSourceLines);
1221:                addMethod(methodAnnotation);
1222:                return this ;
1223:            }
1224:
1225:            /**
1226:             * Add a method annotation.  If this is the first method annotation added,
1227:             * it becomes the primary method annotation.
1228:             * If the method has source line information, then a SourceLineAnnotation
1229:             * is added to the method.
1230:             *
1231:             * @param classAndMethod JavaClassAndMethod identifying the method to add
1232:             * @return this object
1233:             */
1234:            public BugInstance addMethod(JavaClassAndMethod classAndMethod) {
1235:                return addMethod(classAndMethod.getJavaClass(), classAndMethod
1236:                        .getMethod());
1237:            }
1238:
1239:            /**
1240:             * Add a method annotation for the method which the given visitor is currently visiting.
1241:             * If the method has source line information, then a SourceLineAnnotation
1242:             * is added to the method.
1243:             *
1244:             * @param visitor the BetterVisitor
1245:             * @return this object
1246:             */
1247:            public BugInstance addMethod(PreorderVisitor visitor) {
1248:                MethodAnnotation methodAnnotation = MethodAnnotation
1249:                        .fromVisitedMethod(visitor);
1250:                addMethod(methodAnnotation);
1251:                addSourceLinesForMethod(methodAnnotation, SourceLineAnnotation
1252:                        .fromVisitedMethod(visitor));
1253:                return this ;
1254:            }
1255:
1256:            /**
1257:             * Add a method annotation for the method which has been called
1258:             * by the method currently being visited by given visitor.
1259:             * Assumes that the visitor has just looked at an invoke instruction
1260:             * of some kind.
1261:             *
1262:             * @param visitor the DismantleBytecode object
1263:             * @return this object
1264:             */
1265:            public BugInstance addCalledMethod(DismantleBytecode visitor) {
1266:                return addMethod(MethodAnnotation.fromCalledMethod(visitor))
1267:                        .describe("METHOD_CALLED");
1268:            }
1269:
1270:            /**
1271:             * Add a method annotation.
1272:             *
1273:             * @param className  name of class containing called method
1274:             * @param methodName name of called method
1275:             * @param methodSig  signature of called method
1276:             * @param isStatic   true if called method is static, false if not
1277:             * @return this object
1278:             */
1279:            public BugInstance addCalledMethod(String className,
1280:                    String methodName, String methodSig, boolean isStatic) {
1281:                return addMethod(
1282:                        MethodAnnotation.fromCalledMethod(className,
1283:                                methodName, methodSig, isStatic)).describe(
1284:                        "METHOD_CALLED");
1285:            }
1286:
1287:            /**
1288:             * Add a method annotation for the method which is called by given
1289:             * instruction.
1290:             *
1291:             * @param methodGen the method containing the call
1292:             * @param inv       the InvokeInstruction
1293:             * @return this object
1294:             */
1295:            public BugInstance addCalledMethod(MethodGen methodGen,
1296:                    InvokeInstruction inv) {
1297:                ConstantPoolGen cpg = methodGen.getConstantPool();
1298:                String className = inv.getClassName(cpg);
1299:                String methodName = inv.getMethodName(cpg);
1300:                String methodSig = inv.getSignature(cpg);
1301:                addMethod(className, methodName, methodSig,
1302:                        inv.getOpcode() == Constants.INVOKESTATIC);
1303:                describe("METHOD_CALLED");
1304:                return this ;
1305:            }
1306:
1307:            /**
1308:             * Add a MethodAnnotation from an XMethod.
1309:             * 
1310:             * @param xmethod the XMethod
1311:             * @return this object
1312:             */
1313:            public BugInstance addMethod(XMethod xmethod) {
1314:                addMethod(MethodAnnotation.fromXMethod(xmethod));
1315:                return this ;
1316:            }
1317:
1318:            /**
1319:             * Add a method annotation.  If this is the first method annotation added,
1320:             * it becomes the primary method annotation.
1321:             *
1322:             * @param methodAnnotation the method annotation
1323:             * @return this object
1324:             */
1325:            public BugInstance addMethod(MethodAnnotation methodAnnotation) {
1326:                add(methodAnnotation);
1327:                return this ;
1328:            }
1329:
1330:            /* ----------------------------------------------------------------------
1331:             * Integer annotation adders
1332:             * ---------------------------------------------------------------------- */
1333:
1334:            /**
1335:             * Add an integer annotation.
1336:             *
1337:             * @param value the integer value
1338:             * @return this object
1339:             */
1340:            public BugInstance addInt(int value) {
1341:                add(new IntAnnotation(value));
1342:                return this ;
1343:            }
1344:
1345:            /**
1346:             * Add a String annotation.
1347:             *
1348:             * @param value the String value
1349:             * @return this object
1350:             */
1351:            public BugInstance addString(String value) {
1352:                add(new StringAnnotation(value));
1353:                return this ;
1354:            }
1355:
1356:            /* ----------------------------------------------------------------------
1357:             * Source line annotation adders
1358:             * ---------------------------------------------------------------------- */
1359:
1360:            /**
1361:             * Add a source line annotation.
1362:             *
1363:             * @param sourceLine the source line annotation
1364:             * @return this object
1365:             */
1366:            public BugInstance addSourceLine(SourceLineAnnotation sourceLine) {
1367:                add(sourceLine);
1368:                return this ;
1369:            }
1370:
1371:            /**
1372:             * Add a source line annotation for instruction whose PC is given
1373:             * in the method that the given visitor is currently visiting.
1374:             * Note that if the method does not have line number information, then
1375:             * no source line annotation will be added.
1376:             *
1377:             * @param visitor a BytecodeScanningDetector that is currently visiting the method
1378:             * @param pc      bytecode offset of the instruction
1379:             * @return this object
1380:             */
1381:            public BugInstance addSourceLine(BytecodeScanningDetector visitor,
1382:                    int pc) {
1383:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1384:                        .fromVisitedInstruction(visitor.getClassContext(),
1385:                                visitor, pc);
1386:                if (sourceLineAnnotation != null)
1387:                    add(sourceLineAnnotation);
1388:                return this ;
1389:            }
1390:
1391:            /**
1392:             * Add a source line annotation for instruction whose PC is given
1393:             * in the method that the given visitor is currently visiting.
1394:             * Note that if the method does not have line number information, then
1395:             * no source line annotation will be added.
1396:             *
1397:             * @param classContext the ClassContext
1398:             * @param visitor a PreorderVisitor that is currently visiting the method
1399:             * @param pc      bytecode offset of the instruction
1400:             * @return this object
1401:             */
1402:            public BugInstance addSourceLine(ClassContext classContext,
1403:                    PreorderVisitor visitor, int pc) {
1404:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1405:                        .fromVisitedInstruction(classContext, visitor, pc);
1406:                if (sourceLineAnnotation != null)
1407:                    add(sourceLineAnnotation);
1408:                return this ;
1409:            }
1410:
1411:            /**
1412:             * Add a source line annotation for the given instruction in the given method.
1413:             * Note that if the method does not have line number information, then
1414:             * no source line annotation will be added.
1415:             *
1416:             * @param classContext the ClassContext
1417:             * @param methodGen  the method being visited
1418:             * @param sourceFile source file the method is defined in
1419:             * @param handle     the InstructionHandle containing the visited instruction
1420:             * @return this object
1421:             */
1422:            public BugInstance addSourceLine(ClassContext classContext,
1423:                    MethodGen methodGen, String sourceFile, @NonNull
1424:                    InstructionHandle handle) {
1425:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1426:                        .fromVisitedInstruction(classContext, methodGen,
1427:                                sourceFile, handle);
1428:                if (sourceLineAnnotation != null)
1429:                    add(sourceLineAnnotation);
1430:                return this ;
1431:            }
1432:
1433:            /**
1434:             * Add a source line annotation describing a range of instructions.
1435:             *
1436:             * @param classContext the ClassContext
1437:             * @param methodGen  the method
1438:             * @param sourceFile source file the method is defined in
1439:             * @param start      the start instruction in the range
1440:             * @param end        the end instruction in the range (inclusive)
1441:             * @return this object
1442:             */
1443:            public BugInstance addSourceLine(ClassContext classContext,
1444:                    MethodGen methodGen, String sourceFile,
1445:                    InstructionHandle start, InstructionHandle end) {
1446:                // Make sure start and end are really in the right order.
1447:                if (start.getPosition() > end.getPosition()) {
1448:                    InstructionHandle tmp = start;
1449:                    start = end;
1450:                    end = tmp;
1451:                }
1452:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1453:                        .fromVisitedInstructionRange(classContext, methodGen,
1454:                                sourceFile, start, end);
1455:                if (sourceLineAnnotation != null)
1456:                    add(sourceLineAnnotation);
1457:                return this ;
1458:            }
1459:
1460:            /**
1461:             * Add source line annotation for given Location in a method. 
1462:             * 
1463:             * @param classContext the ClassContext
1464:             * @param method       the Method
1465:             * @param location     the Location in the method
1466:             * @return this BugInstance
1467:             */
1468:            public BugInstance addSourceLine(ClassContext classContext,
1469:                    Method method, Location location) {
1470:                return addSourceLine(classContext, method, location.getHandle());
1471:            }
1472:
1473:            /**
1474:             * Add source line annotation for given Location in a method.
1475:             * 
1476:             * @param methodDescriptor the method
1477:             * @param location         the Location in the method
1478:             * @return this BugInstance
1479:             */
1480:            public BugInstance addSourceLine(MethodDescriptor methodDescriptor,
1481:                    Location location) {
1482:                try {
1483:                    IAnalysisCache analysisCache = Global.getAnalysisCache();
1484:                    ClassContext classContext = analysisCache.getClassAnalysis(
1485:                            ClassContext.class, methodDescriptor
1486:                                    .getClassDescriptor());
1487:                    Method method = analysisCache.getMethodAnalysis(
1488:                            Method.class, methodDescriptor);
1489:                    return addSourceLine(classContext, method, location);
1490:                } catch (CheckedAnalysisException e) {
1491:                    return addSourceLine(SourceLineAnnotation
1492:                            .createReallyUnknown(methodDescriptor
1493:                                    .getClassDescriptor().toDottedClassName()));
1494:                }
1495:            }
1496:
1497:            /**
1498:             * Add source line annotation for given Location in a method. 
1499:             * 
1500:             * @param classContext the ClassContext
1501:             * @param method       the Method
1502:             * @param handle       InstructionHandle of an instruction in the method
1503:             * @return this BugInstance
1504:             */
1505:            public BugInstance addSourceLine(ClassContext classContext,
1506:                    Method method, InstructionHandle handle) {
1507:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1508:                        .fromVisitedInstruction(classContext, method, handle
1509:                                .getPosition());
1510:                if (sourceLineAnnotation != null)
1511:                    add(sourceLineAnnotation);
1512:                return this ;
1513:            }
1514:
1515:            /**
1516:             * Add a source line annotation describing the
1517:             * source line numbers for a range of instructions in the method being
1518:             * visited by the given visitor.
1519:             * Note that if the method does not have line number information, then
1520:             * no source line annotation will be added.
1521:             *
1522:             * @param visitor a BetterVisitor which is visiting the method
1523:             * @param startPC the bytecode offset of the start instruction in the range
1524:             * @param endPC   the bytecode offset of the end instruction in the range
1525:             * @return this object
1526:             */
1527:            public BugInstance addSourceLineRange(
1528:                    BytecodeScanningDetector visitor, int startPC, int endPC) {
1529:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1530:                        .fromVisitedInstructionRange(visitor.getClassContext(),
1531:                                visitor, startPC, endPC);
1532:                if (sourceLineAnnotation != null)
1533:                    add(sourceLineAnnotation);
1534:                return this ;
1535:            }
1536:
1537:            /**
1538:             * Add a source line annotation describing the
1539:             * source line numbers for a range of instructions in the method being
1540:             * visited by the given visitor.
1541:             * Note that if the method does not have line number information, then
1542:             * no source line annotation will be added.
1543:             *
1544:             * @param classContext the ClassContext
1545:             * @param visitor a BetterVisitor which is visiting the method
1546:             * @param startPC the bytecode offset of the start instruction in the range
1547:             * @param endPC   the bytecode offset of the end instruction in the range
1548:             * @return this object
1549:             */
1550:            public BugInstance addSourceLineRange(ClassContext classContext,
1551:                    PreorderVisitor visitor, int startPC, int endPC) {
1552:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1553:                        .fromVisitedInstructionRange(classContext, visitor,
1554:                                startPC, endPC);
1555:                if (sourceLineAnnotation != null)
1556:                    add(sourceLineAnnotation);
1557:                return this ;
1558:            }
1559:
1560:            /**
1561:             * Add a source line annotation for instruction currently being visited
1562:             * by given visitor.
1563:             * Note that if the method does not have line number information, then
1564:             * no source line annotation will be added.
1565:             *
1566:             * @param visitor a BytecodeScanningDetector visitor that is currently visiting the instruction
1567:             * @return this object
1568:             */
1569:            public BugInstance addSourceLine(BytecodeScanningDetector visitor) {
1570:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1571:                        .fromVisitedInstruction(visitor);
1572:                if (sourceLineAnnotation != null)
1573:                    add(sourceLineAnnotation);
1574:                return this ;
1575:            }
1576:
1577:            /**
1578:             * Add a non-specific source line annotation.
1579:             * This will result in the entire source file being displayed.
1580:             *
1581:             * @param className  the class name
1582:             * @param sourceFile the source file name
1583:             * @return this object
1584:             */
1585:            public BugInstance addUnknownSourceLine(String className,
1586:                    String sourceFile) {
1587:                SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation
1588:                        .createUnknown(className, sourceFile);
1589:                if (sourceLineAnnotation != null)
1590:                    add(sourceLineAnnotation);
1591:                return this ;
1592:            }
1593:
1594:            /* ----------------------------------------------------------------------
1595:             * Formatting support
1596:             * ---------------------------------------------------------------------- */
1597:
1598:            /**
1599:             * Format a string describing this bug instance.
1600:             *
1601:             * @return the description
1602:             */
1603:            public String getMessageWithoutPrefix() {
1604:                BugPattern bugPattern = getBugPattern();
1605:                String pattern, shortPattern;
1606:
1607:                pattern = getLongDescription();
1608:                shortPattern = bugPattern.getShortDescription();
1609:                try {
1610:                    FindBugsMessageFormat format = new FindBugsMessageFormat(
1611:                            pattern);
1612:                    return format.format(annotationList
1613:                            .toArray(new BugAnnotation[annotationList.size()]),
1614:                            getPrimaryClass());
1615:                } catch (RuntimeException e) {
1616:                    AnalysisContext.logError("Error generating bug msg ", e);
1617:                    return shortPattern
1618:                            + " [Error generating customized description]";
1619:                }
1620:            }
1621:
1622:            String getLongDescription() {
1623:                return getBugPattern().getLongDescription().replaceAll(
1624:                        "BUG_PATTERN", type);
1625:            }
1626:
1627:            public String getAbridgedMessage() {
1628:                BugPattern bugPattern = getBugPattern();
1629:                String pattern, shortPattern;
1630:                if (bugPattern == null)
1631:                    shortPattern = pattern = "Error2: missing bug pattern for key "
1632:                            + type;
1633:                else {
1634:                    pattern = getLongDescription()
1635:                            .replaceAll(" in \\{1\\}", "");
1636:                    shortPattern = bugPattern.getShortDescription();
1637:                }
1638:                try {
1639:                    FindBugsMessageFormat format = new FindBugsMessageFormat(
1640:                            pattern);
1641:                    return format.format(annotationList
1642:                            .toArray(new BugAnnotation[annotationList.size()]),
1643:                            getPrimaryClass());
1644:                } catch (RuntimeException e) {
1645:                    AnalysisContext.logError("Error generating bug msg ", e);
1646:                    return shortPattern
1647:                            + " [Error3 generating customized description]";
1648:                }
1649:            }
1650:
1651:            /**
1652:             * Format a string describing this bug instance.
1653:             *
1654:             * @return the description
1655:             */
1656:            public String getMessage() {
1657:                BugPattern bugPattern = getBugPattern();
1658:                String pattern = bugPattern.getAbbrev() + ": "
1659:                        + getLongDescription();
1660:                FindBugsMessageFormat format = new FindBugsMessageFormat(
1661:                        pattern);
1662:                try {
1663:                    return format.format(annotationList
1664:                            .toArray(new BugAnnotation[annotationList.size()]),
1665:                            getPrimaryClass());
1666:                } catch (RuntimeException e) {
1667:                    AnalysisContext.logError("Error generating bug msg ", e);
1668:                    return bugPattern.getShortDescription()
1669:                            + " [Error generating customized description]";
1670:                }
1671:            }
1672:
1673:            /**
1674:             * Format a string describing this bug pattern, with the priority and type at the beginning.
1675:             * e.g. "(High Priority Correctness) Guaranteed null pointer dereference..."
1676:             */
1677:            public String getMessageWithPriorityType() {
1678:                return "(" + this .getPriorityTypeString() + ") "
1679:                        + this .getMessage();
1680:            }
1681:
1682:            public String getMessageWithPriorityTypeAbbreviation() {
1683:                return this .getPriorityTypeAbbreviation() + " "
1684:                        + this .getMessage();
1685:            }
1686:
1687:            /**
1688:             * Add a description to the most recently added bug annotation.
1689:             *
1690:             * @param description the description to add
1691:             * @return this object
1692:             */
1693:            public BugInstance describe(String description) {
1694:                annotationList.get(annotationList.size() - 1).setDescription(
1695:                        description);
1696:                return this ;
1697:            }
1698:
1699:            /**
1700:             * Convert to String.
1701:             * This method returns the "short" message describing the bug,
1702:             * as opposed to the longer format returned by getMessage().
1703:             * The short format is appropriate for the tree view in a GUI,
1704:             * where the annotations are listed separately as part of the overall
1705:             * bug instance.
1706:             */
1707:            @Override
1708:            public String toString() {
1709:                return I18N.instance().getShortMessage(type);
1710:            }
1711:
1712:            /* ----------------------------------------------------------------------
1713:             * XML Conversion support
1714:             * ---------------------------------------------------------------------- */
1715:
1716:            public void writeXML(XMLOutput xmlOutput) throws IOException {
1717:                writeXML(xmlOutput, false);
1718:            }
1719:
1720:            public void writeXML(XMLOutput xmlOutput, boolean addMessages)
1721:                    throws IOException {
1722:                XMLAttributeList attributeList = new XMLAttributeList()
1723:                        .addAttribute("type", type).addAttribute("priority",
1724:                                String.valueOf(priority));
1725:
1726:                BugPattern pattern = getBugPattern();
1727:                if (pattern != null) {
1728:                    // The bug abbreviation and pattern category are
1729:                    // emitted into the XML for informational purposes only.
1730:                    // (The information is redundant, but might be useful
1731:                    // for processing tools that want to make sense of
1732:                    // bug instances without looking at the plugin descriptor.)
1733:                    attributeList.addAttribute("abbrev", pattern.getAbbrev());
1734:                    attributeList.addAttribute("category", pattern
1735:                            .getCategory());
1736:                }
1737:
1738:                if (addMessages) {
1739:                    //		Add a uid attribute, if we have a unique id.
1740:                    if (getUniqueId() != null) {
1741:                        attributeList.addAttribute("uid", getUniqueId());
1742:                    }
1743:                    attributeList.addAttribute("instanceHash",
1744:                            getInstanceHash());
1745:                    attributeList.addAttribute("instanceOccurrenceNum", Integer
1746:                            .toString(getInstanceOccurrenceNum()));
1747:                    attributeList.addAttribute("instanceOccurrenceMax", Integer
1748:                            .toString(getInstanceOccurrenceMax()));
1749:
1750:                }
1751:                if (firstVersion > 0)
1752:                    attributeList.addAttribute("first", Long
1753:                            .toString(firstVersion));
1754:                if (lastVersion >= 0)
1755:                    attributeList.addAttribute("last", Long
1756:                            .toString(lastVersion));
1757:                if (introducedByChangeOfExistingClass)
1758:                    attributeList.addAttribute("introducedByChange", "true");
1759:                if (removedByChangeOfPersistingClass)
1760:                    attributeList.addAttribute("removedByChange", "true");
1761:
1762:                xmlOutput.openTag(ELEMENT_NAME, attributeList);
1763:
1764:                if (userDesignation != null) {
1765:                    userDesignation.writeXML(xmlOutput);
1766:                }
1767:
1768:                if (addMessages) {
1769:                    BugPattern bugPattern = getBugPattern();
1770:
1771:                    xmlOutput.openTag("ShortMessage");
1772:                    xmlOutput.writeText(bugPattern != null ? bugPattern
1773:                            .getShortDescription() : this .toString());
1774:                    xmlOutput.closeTag("ShortMessage");
1775:
1776:                    xmlOutput.openTag("LongMessage");
1777:                    if (FindBugsDisplayFeatures.isAbridgedMessages())
1778:                        xmlOutput.writeText(this .getAbridgedMessage());
1779:                    else
1780:                        xmlOutput.writeText(this .getMessageWithoutPrefix());
1781:                    xmlOutput.closeTag("LongMessage");
1782:                }
1783:
1784:                boolean foundSourceAnnotation = false;
1785:                for (BugAnnotation annotation : annotationList) {
1786:                    if (annotation instanceof  SourceLineAnnotation)
1787:                        foundSourceAnnotation = true;
1788:                    annotation.writeXML(xmlOutput, addMessages);
1789:                }
1790:                if (!foundSourceAnnotation && addMessages) {
1791:                    SourceLineAnnotation synth = getPrimarySourceLineAnnotation();
1792:                    if (synth != null) {
1793:                        synth.setSynthetic(true);
1794:                        synth.writeXML(xmlOutput, addMessages);
1795:                    }
1796:                }
1797:
1798:                if (propertyListHead != null) {
1799:                    BugProperty prop = propertyListHead;
1800:                    while (prop != null) {
1801:                        prop.writeXML(xmlOutput);
1802:                        prop = prop.getNext();
1803:                    }
1804:                }
1805:
1806:                xmlOutput.closeTag(ELEMENT_NAME);
1807:            }
1808:
1809:            private static final String ELEMENT_NAME = "BugInstance";
1810:            private static final String USER_ANNOTATION_ELEMENT_NAME = "UserAnnotation";
1811:
1812:            /* ----------------------------------------------------------------------
1813:             * Implementation
1814:             * ---------------------------------------------------------------------- */
1815:
1816:            public BugInstance addOptionalAnnotation(@CheckForNull
1817:            BugAnnotation annotation) {
1818:                if (annotation == null)
1819:                    return this ;
1820:                return add(annotation);
1821:            }
1822:
1823:            public BugInstance add(BugAnnotation annotation) {
1824:                if (annotation == null)
1825:                    throw new IllegalStateException("Missing BugAnnotation!");
1826:
1827:                // Add to list
1828:                annotationList.add(annotation);
1829:
1830:                // This object is being modified, so the cached hashcode
1831:                // must be invalidated
1832:                cachedHashCode = INVALID_HASH_CODE;
1833:                return this ;
1834:            }
1835:
1836:            private void addSourceLinesForMethod(
1837:                    MethodAnnotation methodAnnotation,
1838:                    SourceLineAnnotation sourceLineAnnotation) {
1839:                if (sourceLineAnnotation != null) {
1840:                    // Note: we don't add the source line annotation directly to
1841:                    // the bug instance.  Instead, we stash it in the MethodAnnotation.
1842:                    // It is much more useful there, and it would just be distracting
1843:                    // if it were displayed in the UI, since it would compete for attention
1844:                    // with the actual bug location source line annotation (which is much
1845:                    // more important and interesting).
1846:                    methodAnnotation.setSourceLines(sourceLineAnnotation);
1847:                }
1848:            }
1849:
1850:            @Override
1851:            public int hashCode() {
1852:                if (cachedHashCode == INVALID_HASH_CODE) {
1853:                    int hashcode = type.hashCode() + priority;
1854:                    Iterator<BugAnnotation> i = annotationIterator();
1855:                    while (i.hasNext())
1856:                        hashcode += i.next().hashCode();
1857:                    if (hashcode == INVALID_HASH_CODE)
1858:                        hashcode = INVALID_HASH_CODE + 1;
1859:                    cachedHashCode = hashcode;
1860:                }
1861:
1862:                return cachedHashCode;
1863:            }
1864:
1865:            @Override
1866:            public boolean equals(Object o) {
1867:                if (!(o instanceof  BugInstance))
1868:                    return false;
1869:                BugInstance other = (BugInstance) o;
1870:                if (!type.equals(other.type) || priority != other.priority)
1871:                    return false;
1872:                if (annotationList.size() != other.annotationList.size())
1873:                    return false;
1874:                int numAnnotations = annotationList.size();
1875:                for (int i = 0; i < numAnnotations; ++i) {
1876:                    BugAnnotation lhs = annotationList.get(i);
1877:                    BugAnnotation rhs = other.annotationList.get(i);
1878:                    if (!lhs.equals(rhs))
1879:                        return false;
1880:                }
1881:
1882:                return true;
1883:            }
1884:
1885:            public int compareTo(BugInstance other) {
1886:                int cmp;
1887:                cmp = type.compareTo(other.type);
1888:                if (cmp != 0)
1889:                    return cmp;
1890:                cmp = priority - other.priority;
1891:                if (cmp != 0)
1892:                    return cmp;
1893:
1894:                // Compare BugAnnotations lexicographically
1895:                int pfxLen = Math.min(annotationList.size(),
1896:                        other.annotationList.size());
1897:                for (int i = 0; i < pfxLen; ++i) {
1898:                    BugAnnotation lhs = annotationList.get(i);
1899:                    BugAnnotation rhs = other.annotationList.get(i);
1900:                    cmp = lhs.compareTo(rhs);
1901:                    if (cmp != 0)
1902:                        return cmp;
1903:                }
1904:
1905:                // All elements in prefix were the same,
1906:                // so use number of elements to decide
1907:                return annotationList.size() - other.annotationList.size();
1908:            }
1909:
1910:            /**
1911:             * @param firstVersion The firstVersion to set.
1912:             */
1913:            public void setFirstVersion(long firstVersion) {
1914:                this .firstVersion = firstVersion;
1915:                if (lastVersion >= 0 && firstVersion > lastVersion)
1916:                    throw new IllegalArgumentException(firstVersion + ".."
1917:                            + lastVersion);
1918:            }
1919:
1920:            /**
1921:             * @return Returns the firstVersion.
1922:             */
1923:            public long getFirstVersion() {
1924:                return firstVersion;
1925:            }
1926:
1927:            /**
1928:             * @param lastVersion The lastVersion to set.
1929:             */
1930:            public void setLastVersion(long lastVersion) {
1931:                if (lastVersion >= 0 && firstVersion > lastVersion)
1932:                    throw new IllegalArgumentException(firstVersion + ".."
1933:                            + lastVersion);
1934:                this .lastVersion = lastVersion;
1935:            }
1936:
1937:            /**
1938:             * @return Returns the lastVersion.
1939:             */
1940:            public long getLastVersion() {
1941:                return lastVersion;
1942:            }
1943:
1944:            /**
1945:             * @param introducedByChangeOfExistingClass The introducedByChangeOfExistingClass to set.
1946:             */
1947:            public void setIntroducedByChangeOfExistingClass(
1948:                    boolean introducedByChangeOfExistingClass) {
1949:                this .introducedByChangeOfExistingClass = introducedByChangeOfExistingClass;
1950:            }
1951:
1952:            /**
1953:             * @return Returns the introducedByChangeOfExistingClass.
1954:             */
1955:            public boolean isIntroducedByChangeOfExistingClass() {
1956:                return introducedByChangeOfExistingClass;
1957:            }
1958:
1959:            /**
1960:             * @param removedByChangeOfPersistingClass The removedByChangeOfPersistingClass to set.
1961:             */
1962:            public void setRemovedByChangeOfPersistingClass(
1963:                    boolean removedByChangeOfPersistingClass) {
1964:                this .removedByChangeOfPersistingClass = removedByChangeOfPersistingClass;
1965:            }
1966:
1967:            /**
1968:             * @return Returns the removedByChangeOfPersistingClass.
1969:             */
1970:            public boolean isRemovedByChangeOfPersistingClass() {
1971:                return removedByChangeOfPersistingClass;
1972:            }
1973:
1974:            /**
1975:             * @param instanceHash The instanceHash to set.
1976:             */
1977:            public void setInstanceHash(String instanceHash) {
1978:                this .instanceHash = instanceHash;
1979:            }
1980:
1981:            /**
1982:             * @param oldInstanceHash The oldInstanceHash to set.
1983:             */
1984:            public void setOldInstanceHash(String oldInstanceHash) {
1985:                this .oldInstanceHash = oldInstanceHash;
1986:            }
1987:
1988:            private static final boolean DONT_HASH = SystemProperties
1989:                    .getBoolean("findbugs.dontHash");
1990:
1991:            /**
1992:             * @return Returns the instanceHash.
1993:             */
1994:            public String getInstanceHash() {
1995:                if (instanceHash != null)
1996:                    return instanceHash;
1997:                MessageDigest digest = null;
1998:                try {
1999:                    digest = MessageDigest.getInstance("MD5");
2000:                } catch (Exception e2) {
2001:                    // OK, we won't digest
2002:                }
2003:                instanceHash = getInstanceKey();
2004:                if (digest != null && !DONT_HASH) {
2005:                    byte[] data = digest.digest(instanceHash.getBytes());
2006:                    String tmp = new BigInteger(1, data).toString(16);
2007:                    instanceHash = tmp;
2008:                }
2009:                return instanceHash;
2010:            }
2011:
2012:            public boolean isInstanceHashConsistent() {
2013:                return oldInstanceHash == null
2014:                        || instanceHash.equals(oldInstanceHash);
2015:            }
2016:
2017:            /**
2018:             * @param instanceOccurrenceNum The instanceOccurrenceNum to set.
2019:             */
2020:            public void setInstanceOccurrenceNum(int instanceOccurrenceNum) {
2021:                this .instanceOccurrenceNum = instanceOccurrenceNum;
2022:            }
2023:
2024:            /**
2025:             * @return Returns the instanceOccurrenceNum.
2026:             */
2027:            public int getInstanceOccurrenceNum() {
2028:                return instanceOccurrenceNum;
2029:            }
2030:
2031:            /**
2032:             * @param instanceOccurrenceMax The instanceOccurrenceMax to set.
2033:             */
2034:            public void setInstanceOccurrenceMax(int instanceOccurrenceMax) {
2035:                this .instanceOccurrenceMax = instanceOccurrenceMax;
2036:            }
2037:
2038:            /**
2039:             * @return Returns the instanceOccurrenceMax.
2040:             */
2041:            public int getInstanceOccurrenceMax() {
2042:                return instanceOccurrenceMax;
2043:            }
2044:        }
2045:
2046:        // vim:ts=4
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.