001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2005, University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.ba;
021:
022: import org.apache.bcel.Repository;
023: import org.apache.bcel.classfile.JavaClass;
024:
025: /**
026: * @author pugh
027: */
028: public class CheckReturnAnnotationDatabase extends
029: AnnotationDatabase<CheckReturnValueAnnotation> {
030:
031: private JavaClass throwableClass, threadClass;
032:
033: public CheckReturnAnnotationDatabase() {
034: setAddClassOnly(true);
035: loadAuxiliaryAnnotations();
036: setAddClassOnly(false);
037: }
038:
039: @Override
040: public void loadAuxiliaryAnnotations() {
041: if (IGNORE_BUILTIN_ANNOTATIONS)
042: return;
043: boolean missingClassWarningsSuppressed = AnalysisContext
044: .currentAnalysisContext()
045: .setMissingClassWarningsSuppressed(true);
046:
047: addMethodAnnotation("java.util.Iterator", "hasNext", "()Z",
048: false,
049: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW);
050: addMethodAnnotation(
051: "java.io.File",
052: "createNewFile",
053: "()Z",
054: false,
055: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
056: addMethodAnnotation(
057: "java.io.File",
058: "delete",
059: "()Z",
060: false,
061: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
062: addMethodAnnotation(
063: "java.io.File",
064: "mkdir",
065: "()Z",
066: false,
067: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
068: addMethodAnnotation(
069: "java.io.File",
070: "mkdirs",
071: "()Z",
072: false,
073: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
074: addMethodAnnotation(
075: "java.io.File",
076: "renameTo",
077: "(Ljava/io/File;)Z",
078: false,
079: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
080: addMethodAnnotation(
081: "java.io.File",
082: "setLastModified",
083: "(J)Z",
084: false,
085: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
086: addMethodAnnotation(
087: "java.io.File",
088: "setReadOnly",
089: "()Z",
090: false,
091: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
092: addMethodAnnotation(
093: "java.io.File",
094: "setWritable",
095: "(ZZ)Z",
096: false,
097: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
098: addMethodAnnotation("java.util.Enumeration", "hasMoreElements",
099: "()Z", false,
100: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
101: addMethodAnnotation("java.security.MessageDigest", "digest",
102: "([B)[B", false,
103: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
104:
105: addMethodAnnotation("java.util.concurrent.locks.ReadWriteLock",
106: "readLock", "()Ljava/util/concurrent/locks/Lock;",
107: false,
108: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
109: addMethodAnnotation("java.util.concurrent.locks.ReadWriteLock",
110: "writeLock", "()Ljava/util/concurrent/locks/Lock;",
111: false,
112: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
113: addMethodAnnotation(
114: "java.util.concurrent.locks.Condition",
115: "await",
116: "(JLjava/util/concurrent/TimeUnit;)Z",
117: false,
118: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
119: addMethodAnnotation(
120: "java.util.concurrent.locks.Condition",
121: "awaitUtil",
122: "(Ljava/util/Date;)Z",
123: false,
124: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
125: addMethodAnnotation(
126: "java.util.concurrent.locks.Condition",
127: "awaitNanos",
128: "(J)Z",
129: false,
130: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
131: addMethodAnnotation("java.util.concurrent.Semaphore",
132: "tryAcquire", "(JLjava/util/concurrent/TimeUnit;)Z",
133: false,
134: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
135: addMethodAnnotation("java.util.concurrent.Semaphore",
136: "tryAcquire", "()Z", false,
137: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
138: addMethodAnnotation("java.util.concurrent.locks.Lock",
139: "tryLock", "(JLjava/util/concurrent/TimeUnit;)Z",
140: false,
141: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
142: addMethodAnnotation("java.util.concurrent.locks.Lock",
143: "newCondition",
144: "()Ljava/util/concurrent/locks/Condition;", false,
145: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
146: addMethodAnnotation("java.util.concurrent.locks.Lock",
147: "tryLock", "()Z", false,
148: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
149: addMethodAnnotation(
150: "java.util.concurrent.BlockingQueue",
151: "offer",
152: "(Ljava/lang/Object;JLjava/util/concurrent/TimeUnit;)Z",
153: false,
154: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
155:
156: addMethodAnnotation("java.util.ConcurrentLinkedQueue", "offer",
157: "(Ljava/lang/Object;)Z", false,
158: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
159: addMethodAnnotation("java.util.DelayQueue", "offer",
160: "(Ljava/lang/Object;)Z", false,
161: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
162: addMethodAnnotation(
163: "java.util.LinkedBlockingQueue",
164: "offer",
165: "(Ljava/lang/Object;)Z",
166: false,
167: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW_BAD_PRACTICE);
168: addMethodAnnotation("java.util.LinkedList", "offer",
169: "(Ljava/lang/Object;)Z", false,
170: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
171: addMethodAnnotation(
172: "java.util.Queue",
173: "offer",
174: "(Ljava/lang/Object;)Z",
175: false,
176: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW_BAD_PRACTICE);
177: addMethodAnnotation(
178: "java.util.ArrayBlockingQueue",
179: "offer",
180: "(Ljava/lang/Object;)Z",
181: false,
182: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
183: addMethodAnnotation(
184: "java.util.SynchronousQueue",
185: "offer",
186: "(Ljava/lang/Object;)Z",
187: false,
188: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM_BAD_PRACTICE);
189: addMethodAnnotation("java.util.PriorityQueue", "offer",
190: "(Ljava/lang/Object;)Z", false,
191: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
192: addMethodAnnotation("java.util.PriorityBlockingQueue", "offer",
193: "(Ljava/lang/Object;)Z", false,
194: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
195:
196: addMethodAnnotation("java.util.concurrent.BlockingQueue",
197: "poll",
198: "(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;",
199: false,
200: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
201: addMethodAnnotation("java.util.Queue", "poll",
202: "()Ljava/lang/Object;", false,
203: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW);
204:
205: addDefaultMethodAnnotation("java.lang.String",
206: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
207: addMethodAnnotation("java.lang.String", "getBytes",
208: "(Ljava/lang/String;)[B", false,
209: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
210: addMethodAnnotation("java.lang.String", "charAt", "(I)C",
211: false,
212: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW);
213: addMethodAnnotation("java.lang.String", "length", "()I", false,
214: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW);
215: addMethodAnnotation("java.lang.String", "<init>",
216: "([BLjava/lang/String;)V", false,
217: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
218: addMethodAnnotation("java.lang.String", "<init>",
219: "(Ljava/lang/String;)V", false,
220: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW);
221: addMethodAnnotation("java.lang.String", "<init>", "()V", false,
222: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW);
223: addDefaultMethodAnnotation("java.math.BigDecimal",
224: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
225: addMethodAnnotation("java.math.BigDecimal", "inflate",
226: "()Ljava/math/BigDecimal;", false,
227: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
228: addDefaultMethodAnnotation("java.math.BigInteger",
229: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_HIGH);
230: addMethodAnnotation("java.math.BigInteger", "addOne",
231: "([IIII)I", true,
232: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
233: addMethodAnnotation("java.math.BigInteger", "subN", "([I[II)I",
234: true,
235: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
236: addDefaultMethodAnnotation("java.sql.Connection",
237: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
238: addDefaultMethodAnnotation("java.net.InetAddress",
239: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
240: addMethodAnnotation("java.util.InetAddress", "getByName",
241: "(Ljava/lang/String;)Ljava/util/InetAddress;", true,
242: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_IGNORE);
243: addMethodAnnotation("java.lang.ProcessBuilder",
244: "redirectErrorStream", "()Z", false,
245: CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM);
246:
247: AnalysisContext.currentAnalysisContext()
248: .setMissingClassWarningsSuppressed(
249: missingClassWarningsSuppressed);
250:
251: try {
252: throwableClass = Repository
253: .lookupClass("java.lang.Throwable");
254: } catch (ClassNotFoundException e) {
255: AnalysisContext.reportMissingClass(e);
256: }
257: try {
258: threadClass = Repository.lookupClass("java.lang.Thread");
259: } catch (ClassNotFoundException e) {
260: AnalysisContext.reportMissingClass(e);
261: }
262: }
263:
264: @Override
265: public CheckReturnValueAnnotation getResolvedAnnotation(Object o,
266: boolean getMinimal) {
267: if (!(o instanceof XMethod))
268: return null;
269: XMethod m = (XMethod) o;
270: if (m.getName().startsWith("access$"))
271: return null;
272: else if (m.getName().equals("<init>")) {
273: try {
274: if (throwableClass != null
275: && Repository.instanceOf(m.getClassName(),
276: throwableClass))
277: return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_VERY_HIGH;
278: } catch (ClassNotFoundException e) {
279: AnalysisContext.reportMissingClass(e);
280: }
281: if (m.getClassName().equals("java.lang.Thread"))
282: return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_VERY_HIGH;
283: try {
284:
285: if (threadClass != null
286: && Repository.instanceOf(m.getClassName(),
287: threadClass))
288: return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_LOW;
289: } catch (ClassNotFoundException e) {
290: AnalysisContext.reportMissingClass(e);
291: }
292: } else if (m.getName().equals("equals")
293: && m.getSignature().equals("(Ljava/lang/Object;)Z")
294: && !m.isStatic())
295: return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM;
296: else if (m.getSignature().endsWith(")Ljava/lang/String;")
297: && (m.getClassName().equals("java.lang.StringBuffer") || m
298: .getClassName().equals(
299: "java.lang.StringBuilder")))
300: return CheckReturnValueAnnotation.CHECK_RETURN_VALUE_MEDIUM;
301: return super.getResolvedAnnotation(o, getMinimal);
302: }
303:
304: }
|