Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * fb-contrib - Auxiliary detectors for Java programs
   * Copyright (C) 2005-2014 Dave Brosius
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 package com.mebigfatguy.fbcontrib.detect;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import  org.apache.bcel.classfile.Code;
 import  org.apache.bcel.classfile.Field;
 import  org.apache.bcel.classfile.JavaClass;
 import  org.apache.bcel.generic.Type;
 
 
 
 public class WriteOnlyCollection extends BytecodeScanningDetector {
 
 	private static Set<StringcollectionClasses = new HashSet<String>();
 	static
 	{
         .add(EnumSet.class.getName());
         .add(EnumMap.class.getName());
         .add(HashSet.class.getName());
         .add(IdentityHashMap.class.getName());
 		/* these are java 6 classes */
         .add("java.util.Deque");
         .add("java.util.Queue");
         .add("java.util.ArrayDeque");
         .add("java.util.LinkedBlockingDeque");
         .add("java.util.NavigableMap");
         .add("java.util.concurrent.ConcurrentMap");
         .add("java.util.concurrent.ConcurrentNavigableMap");
         .add("java.util.concurrent.ConcurrentSkipListMap");
         .add("java.util.concurrent.ConcurrentHashMap");
         .add("java.util.concurrent.ConcurrentSkipListSet");
         .add("java.util.concurrent.CopyOnWriteArrayList");
 	}
 
 	private static Set<StringnonInformationalMethods = new HashSet<String>();
 	static
 	{
		.add("ensureCapacity");
		.add("insertElementAt");
		.add("removeElement");
		.add("removeElementAt");
	}
	private final BugReporter bugReporter;
	private OpcodeStack stack;
	private String clsSignature;
register to first allocation PC
fieldname to field sig
	private boolean sawTernary;
	private boolean isInnerClass;


constructs a WOC detector given the reporter to report bugs on

Parameters:
bugReporter the sync of bug reports
	public WriteOnlyCollection(BugReporter bugReporter) {
		this. = bugReporter;
	}
overrides the visitor to initialize and tear down the opcode stack

Parameters:
classContext the context object of the currently parsed class
	public void visitClassContext(ClassContext classContext) {
		try {
		    JavaClass clz = classContext.getJavaClass();
		     = clz.getClassName().contains("$");
		    
			 = "L" + clz.getClassName().replaceAll("\\.""/") + ";";
			 = new OpcodeStack();
			super.visitClassContext(classContext);
			if (! && (.size() > 0)) {
				String clsName = classContext.getJavaClass().getClassName();
					String fieldName = entry.getKey();
					String signature = entry.getValue();
					.reportBug(new BugInstance(this"WOC_WRITE_ONLY_COLLECTION_FIELD", NORMAL_PRIORITY)
								.addClass(this)
								.addField(clsNamefieldNamesignaturefalse));
				}
			}
finally {
			 = null;
		}
	}
	public void visitField(Field obj) {
		if (! && obj.isPrivate() && !obj.isSynthetic()) {
			String sig = obj.getSignature();
			if (sig.startsWith("L")) {
				String type = sig.substring(1, sig.length() - 1).replace('/''.');
					.put(obj.getName(), obj.getSignature());
				}
			}
		}
	}

overrides the visitor reset the stack

Parameters:
obj the context object of the currently parsed code block
	public void visitCode(Code obj) {
		 = false;
		super.visitCode(obj);
		for (Integer pc : .values()) {
			.reportBug(new BugInstance(this"WOC_WRITE_ONLY_COLLECTION_LOCAL", NORMAL_PRIORITY)
						.addClass(this)
						.addMethod(this)
						.addSourceLine(thispc.intValue()));
		}
	}

overrides the visitor to look for uses of collections where the only access to to the collection is to write to it

Parameters:
seen the opcode of the currently visited instruction
	public void sawOpcode(int seen) {
		Object userObject = null;
		// saving and restoring the userobject of the top item, works around a bug in Findbugs proper
		if (.getStackDepth() > 0) {
		    userObject = .getStackItem(0).getUserValue();
		}
		if (.getStackDepth() > 0) {
            .getStackItem(0).setUserValue(userObject);
            userObject = null;
        }
		try {
			switch (seen) {
				case INVOKESPECIAL:
					String methodName = getNameConstantOperand();
					if ("<init>".equals(methodName)) {
						String clsName = getClassConstantOperand().replace('/''.');
                        {
                            userObject = .;
                        }
					}
				break;
				case INVOKEINTERFACE:
				case INVOKEVIRTUAL: {
					int numParms = Type.getArgumentTypes(sig).length;
					if (.getStackDepth() > numParms) {
						OpcodeStack.Item item = .getStackItem(numParms);
						Object uo = item.getUserValue();
						if (uo != null) {
else if (!"clone".equals(name)) {
							    Type t = Type.getReturnType(sig);
							    if ((t != Type.VOID) && !nextOpIsPop()) {
							        clearUserValue(item);
							    }
							}
						}
					}
				}
				break;
				case INVOKESTATIC:
				break;
				case ARETURN:
					if (.getStackDepth() > 0) {
					}
				break;
				case ASTORE_0:
				case ASTORE_1:
				case ASTORE_2:
				case ASTORE_3:
				case ASTORE:
					if (.getStackDepth() > 0) {
						Object uo = item.getUserValue();
						if (uo != null) {
							if (uo instanceof Boolean) {
							    int reg = RegisterUtils.getAStoreReg(thisseen);
								.put(Integer.valueOf(reg), Integer.valueOf(getPC()));
	                            if (.getStackDepth() > 1) {
	                                //the astore was preceded by a dup
	                                item = .getStackItem(1);
	                                item.setUserValue(Integer.valueOf(reg));
	                            }
else {
							}
						}
					}
				break;
				case ALOAD_0:
				case ALOAD_1:
				case ALOAD_2:
				case ALOAD_3:
				case ALOAD:
					int reg = RegisterUtils.getALoadReg(thisseen);
					if (.containsKey(Integer.valueOf(reg))) {
						userObject = Integer.valueOf(reg);
					}
				break;
				case AASTORE:
				    if (.getStackDepth() >= 3) {
				        OpcodeStack.Item item = .getStackItem(0);
				        clearUserValue(item);
				    }
				break;
				case PUTFIELD:
					if (.getStackDepth() > 1) {
						Object uo = item.getUserValue();
						if ((uo != null) && !(uo instanceof Boolean)) {
						}
					}
				break;
				case GETFIELD:
					if (.getStackDepth() > 0) {
						String sig = item.getSignature();
						if ((item.getRegisterNumber() == 0) || ((sig != null) && sig.equals())) {
							if (field != null) {
								String fieldName = field.getName();
								if (.containsKey(fieldName)) {
									userObject = fieldName;
								}
							}
						}
					}
				break;
				case PUTSTATIC:
					if (.getStackDepth() > 0) {
						Object uo = item.getUserValue();
						if ((uo != null) && !(uo instanceof Boolean)) {
						}
					}
				break;
				case GETSTATIC:
					if (field != null) {
						String fieldName = field.getName();
						if (.containsKey(fieldName)) {
							userObject = fieldName;
						}
					}
				break;
				case GOTO:
                case IFNULL:
                case IFNONNULL:
                    if (.getStackDepth() > 0) {
						Object uo = item.getUserValue();
						if ((uo != null) && !(uo instanceof Boolean)) {
						}
	                     = true;
					}
				break;
			}
finally {
			TernaryPatcher.pre(seen);
			.sawOpcode(thisseen);
			TernaryPatcher.post(seen);
			if (userObject != null) {
				if (.getStackDepth() > 0) {
					item.setUserValue(userObject);
				}
			}
			if () {
			    if ((seen == GETFIELD) || (seen == ALOAD) || ((seen >= ALOAD_0) && (seen <= ALOAD_3))) {
			        if (.getStackDepth() > 0) {
			            OpcodeStack.Item item = .getStackItem(0);
			            clearUserValue(item);
			        }
			    }
			    /* check ALOAD_0, as if it's a field the statement after a GOTO will be loading 'this' */
			    if ((seen != GOTO) && (seen != IFNULL) && (seen != IFNONNULL) && (seen != ALOAD_0))
			         = false;
			}
		}
	}
	private boolean nextOpIsPop() {
		int nextPC = getNextPC();
		return getCode().getCode()[nextPC] == POP;
	}
	private void clearUserValue(OpcodeStack.Item item) {
		Object uo = item.getUserValue();
		if (uo instanceof Integer) {
else if (uo instanceof String) {
else if (uo instanceof Boolean) {
		}
		item.setUserValue(null);
	}
	private void processMethodParms() {
		int numParms = Type.getArgumentTypes(sig).length;
		if ((numParms > 0) && (.getStackDepth() >= numParms)) {
			for (int i = 0; i < numParmsi++) {
			}
		}
	}
New to GrepCode? Check out our FAQ X