1 19 20 package edu.umd.cs.findbugs; 21 22 import java.io.IOException ; 23 24 import org.apache.bcel.classfile.Field; 25 import org.apache.bcel.generic.ConstantPoolGen; 26 import org.apache.bcel.generic.FieldInstruction; 27 import org.apache.bcel.generic.GETFIELD; 28 import org.apache.bcel.generic.GETSTATIC; 29 import org.apache.bcel.generic.Instruction; 30 import org.apache.bcel.generic.PUTFIELD; 31 import org.apache.bcel.generic.PUTSTATIC; 32 33 import edu.umd.cs.findbugs.ba.AnalysisContext; 34 import edu.umd.cs.findbugs.ba.SignatureConverter; 35 import edu.umd.cs.findbugs.ba.SourceInfoMap; 36 import edu.umd.cs.findbugs.ba.XField; 37 import edu.umd.cs.findbugs.classfile.FieldDescriptor; 38 import edu.umd.cs.findbugs.visitclass.DismantleBytecode; 39 import edu.umd.cs.findbugs.visitclass.PreorderVisitor; 40 import edu.umd.cs.findbugs.xml.XMLAttributeList; 41 import edu.umd.cs.findbugs.xml.XMLOutput; 42 43 49 public class FieldAnnotation extends PackageMemberAnnotation { 50 private static final long serialVersionUID = 1L; 51 52 private static final String DEFAULT_ROLE = "FIELD_DEFAULT"; 53 54 private String fieldName; 55 private String fieldSig; 56 private boolean isStatic; 57 58 65 public FieldAnnotation(String className, String fieldName, String fieldSig, boolean isStatic) { 66 super(className, DEFAULT_ROLE); 67 if (fieldSig.indexOf(".") >= 0) { 68 assert false : "signatures should not be dotted: " + fieldSig; 69 fieldSig = fieldSig.replace('.','/'); 70 } 71 this.fieldName = fieldName; 72 this.fieldSig = fieldSig; 73 this.isStatic = isStatic; 74 } 75 76 83 public static FieldAnnotation fromVisitedField(PreorderVisitor visitor) { 84 return new FieldAnnotation(visitor.getDottedClassName(), 85 visitor.getFieldName(), visitor.getFieldSig(), 86 visitor.getFieldIsStatic()); 87 } 88 89 97 public static FieldAnnotation fromReferencedField(DismantleBytecode visitor) { 98 String className = visitor.getDottedClassConstantOperand(); 99 return new FieldAnnotation(className, 100 visitor.getNameConstantOperand(), 101 visitor.getSigConstantOperand(), visitor.getRefFieldIsStatic()); 102 } 103 104 111 public static FieldAnnotation fromBCELField(String className, Field field) { 112 return new FieldAnnotation(className, field.getName(), field.getSignature(), field.isStatic()); 113 } 114 115 121 public static FieldAnnotation fromFieldDescriptor(FieldDescriptor fieldDescriptor) { 122 return new FieldAnnotation( 123 fieldDescriptor.getClassName(), 124 fieldDescriptor.getName(), 125 fieldDescriptor.getSignature(), 126 fieldDescriptor.isStatic()); 127 } 128 129 public static FieldAnnotation fromXField(XField fieldDescriptor) { 130 return new FieldAnnotation( 131 fieldDescriptor.getClassName(), 132 fieldDescriptor.getName(), 133 fieldDescriptor.getSignature(), 134 fieldDescriptor.isStatic()); 135 } 136 139 public String getFieldName() { 140 return fieldName; 141 } 142 143 146 public String getFieldSignature() { 147 return fieldSig; 148 } 149 150 153 public boolean isStatic() { 154 return isStatic; 155 } 156 157 164 public static FieldAnnotation isRead(Instruction ins, ConstantPoolGen cpg) { 165 if (ins instanceof GETFIELD || ins instanceof GETSTATIC) { 166 FieldInstruction fins = (FieldInstruction) ins; 167 String className = fins.getClassName(cpg); 168 return new FieldAnnotation(className, fins.getName(cpg), fins.getSignature(cpg), fins instanceof GETSTATIC); 169 } else 170 return null; 171 } 172 173 180 public static FieldAnnotation isWrite(Instruction ins, ConstantPoolGen cpg) { 181 if (ins instanceof PUTFIELD || ins instanceof PUTSTATIC) { 182 FieldInstruction fins = (FieldInstruction) ins; 183 String className = fins.getClassName(cpg); 184 return new FieldAnnotation(className, fins.getName(cpg), fins.getSignature(cpg), fins instanceof PUTSTATIC); 185 } else 186 return null; 187 } 188 189 public void accept(BugAnnotationVisitor visitor) { 190 visitor.visitFieldAnnotation(this); 191 } 192 193 @Override 194 protected String formatPackageMember(String key, ClassAnnotation primaryClass) { 195 if (key.equals("") || key.equals("hash")) 196 return className + "." + fieldName; 197 else if (key.equals("name")) 198 return fieldName; 199 else if (key.equals("fullField")) { 200 SignatureConverter converter = new SignatureConverter(fieldSig); 201 StringBuffer result = new StringBuffer (); 202 if (isStatic) 203 result.append("static "); 204 result.append(converter.parseNext()); 205 result.append(' '); 206 result.append(className); 207 result.append('.'); 208 result.append(fieldName); 209 return result.toString(); 210 } else 211 throw new IllegalArgumentException ("unknown key " + key); 212 } 213 214 @Override 215 public int hashCode() { 216 return className.hashCode() + fieldName.hashCode() + fieldSig.hashCode(); 217 } 218 219 @Override 220 public boolean equals(Object o) { 221 if (!(o instanceof FieldAnnotation)) 222 return false; 223 FieldAnnotation other = (FieldAnnotation) o; 224 return className.equals(other.className) 225 && fieldName.equals(other.fieldName) 226 && fieldSig.equals(other.fieldSig) 227 && isStatic == other.isStatic; 228 } 229 230 public int compareTo(BugAnnotation o) { 231 if (!(o instanceof FieldAnnotation)) return this.getClass().getName().compareTo(o.getClass().getName()); 233 FieldAnnotation other = (FieldAnnotation) o; 234 int cmp; 235 cmp = className.compareTo(other.className); 236 if (cmp != 0) 237 return cmp; 238 cmp = fieldName.compareTo(other.fieldName); 239 if (cmp != 0) 240 return cmp; 241 return fieldSig.compareTo(other.fieldSig); 242 } 243 244 247 @Override 248 public SourceLineAnnotation getSourceLines() { 249 if (sourceLines == null) { 250 AnalysisContext currentAnalysisContext = AnalysisContext.currentAnalysisContext(); 252 if (currentAnalysisContext == null) 253 sourceLines = new SourceLineAnnotation(className, sourceFileName, -1, -1, -1, -1); 254 else { 255 SourceInfoMap.SourceLineRange fieldLine = currentAnalysisContext 256 .getSourceInfoMap() 257 .getFieldLine(className, fieldName); 258 if (fieldLine == null) sourceLines = new SourceLineAnnotation( 259 className, sourceFileName, -1, -1, -1, -1); 260 else sourceLines = new SourceLineAnnotation( 261 className, sourceFileName, fieldLine.getStart(), fieldLine.getEnd(), -1, -1); 262 } 263 } 264 return sourceLines; 265 } 266 267 270 271 private static final String ELEMENT_NAME = "Field"; 272 273 public void writeXML(XMLOutput xmlOutput) throws IOException { 274 writeXML(xmlOutput, false); 275 } 276 277 public void writeXML(XMLOutput xmlOutput, boolean addMessages) throws IOException { 278 XMLAttributeList attributeList = new XMLAttributeList() 279 .addAttribute("classname", getClassName()) 280 .addAttribute("name", getFieldName()) 281 .addAttribute("signature", getFieldSignature()) 282 .addAttribute("isStatic", String.valueOf(isStatic())); 283 284 String role = getDescription(); 285 if (!role.equals(DEFAULT_ROLE)) 286 attributeList.addAttribute("role", role); 287 288 xmlOutput.openTag(ELEMENT_NAME, attributeList); 289 getSourceLines().writeXML(xmlOutput, addMessages); 290 if (addMessages) { 291 xmlOutput.openTag(BugAnnotation.MESSAGE_TAG); 292 xmlOutput.writeText(this.toString()); 293 xmlOutput.closeTag(BugAnnotation.MESSAGE_TAG); 294 } 295 xmlOutput.closeTag(ELEMENT_NAME); 296 } 297 } 298 299 | Popular Tags |