1 19 20 package edu.umd.cs.findbugs.detect; 21 22 import java.util.HashMap ; 23 import java.util.HashSet ; 24 import java.util.Iterator ; 25 import java.util.Map ; 26 import java.util.Set ; 27 import java.util.TreeSet ; 28 29 import org.apache.bcel.generic.ConstantPoolGen; 30 import org.apache.bcel.generic.Instruction; 31 import org.apache.bcel.generic.InstructionHandle; 32 import org.apache.bcel.generic.ObjectType; 33 import org.apache.bcel.generic.Type; 34 import org.apache.bcel.generic.TypedInstruction; 35 36 import edu.umd.cs.findbugs.ResourceCollection; 37 import edu.umd.cs.findbugs.ba.BasicBlock; 38 import edu.umd.cs.findbugs.ba.Edge; 39 import edu.umd.cs.findbugs.ba.Location; 40 import edu.umd.cs.findbugs.ba.RepositoryLookupFailureCallback; 41 import edu.umd.cs.findbugs.ba.ResourceTracker; 42 import edu.umd.cs.findbugs.ba.ResourceValueFrame; 43 import edu.umd.cs.findbugs.ba.ResourceValueFrameModelingVisitor; 44 45 51 public class StreamResourceTracker implements ResourceTracker<Stream> { 52 private StreamFactory[] streamFactoryList; 53 private RepositoryLookupFailureCallback lookupFailureCallback; 54 private ResourceCollection<Stream> resourceCollection; 55 56 60 private Map <Location, Stream> streamOpenLocationMap; 61 62 65 private HashSet <Stream> uninterestingStreamEscapeSet; 67 68 71 private TreeSet <StreamEscape> streamEscapeSet; 72 73 81 private Map <Stream, StreamEquivalenceClass> streamEquivalenceMap; 82 83 90 public StreamResourceTracker(StreamFactory[] streamFactoryList, 92 RepositoryLookupFailureCallback lookupFailureCallback) { 93 94 this.streamFactoryList = streamFactoryList; 95 this.lookupFailureCallback = lookupFailureCallback; 96 this.streamOpenLocationMap = new HashMap <Location, Stream>(); 97 this.uninterestingStreamEscapeSet = new HashSet <Stream>(); 98 this.streamEscapeSet = new TreeSet <StreamEscape>(); 99 this.streamEquivalenceMap = new HashMap <Stream, StreamEquivalenceClass>(); 100 } 101 102 105 public void setResourceCollection(ResourceCollection<Stream> resourceCollection) { 106 this.resourceCollection = resourceCollection; 107 } 108 109 115 public void addStreamEscape(Stream source, Location target) { 116 StreamEscape streamEscape = new StreamEscape(source, target); 117 streamEscapeSet.add(streamEscape); 118 if (FindOpenStream.DEBUG) 119 System.out.println("Adding potential stream escape " + streamEscape); 120 } 121 122 128 public void markTransitiveUninterestingStreamEscapes() { 129 for (Iterator <StreamEscape> i = streamEscapeSet.iterator(); i.hasNext();) { 132 StreamEscape streamEscape = i.next(); 133 if (!isStreamOpenLocation(streamEscape.target)) { 134 if (FindOpenStream.DEBUG) 135 System.out.println("Eliminating false stream escape " + streamEscape); 136 i.remove(); 137 } 138 } 139 140 for (Iterator <Stream> i = resourceCollection.resourceIterator(); i.hasNext();) { 144 Stream stream = i.next(); 145 StreamEquivalenceClass equivalenceClass = new StreamEquivalenceClass(); 146 equivalenceClass.addMember(stream); 147 streamEquivalenceMap.put(stream, equivalenceClass); 148 } 149 150 Set <Stream> orig = new HashSet <Stream>(); 154 do { 155 orig.clear(); 156 orig.addAll(uninterestingStreamEscapeSet); 157 158 for (StreamEscape streamEscape : streamEscapeSet) { 159 if (isUninterestingStreamEscape(streamEscape.source)) { 160 if (FindOpenStream.DEBUG) 161 System.out.println("Propagating stream escape " + streamEscape); 162 Stream target = streamOpenLocationMap.get(streamEscape.target); 163 if (target == null) 164 throw new IllegalStateException (); 165 uninterestingStreamEscapeSet.add(target); 166 167 StreamEquivalenceClass sourceClass = streamEquivalenceMap.get(streamEscape.source); 169 StreamEquivalenceClass targetClass = streamEquivalenceMap.get(target); 170 if (sourceClass != targetClass) { 171 sourceClass.addAll(targetClass); 172 for (Iterator <Stream> j = targetClass.memberIterator(); j.hasNext();) { 173 Stream stream = j.next(); 174 streamEquivalenceMap.put(stream, sourceClass); 175 } 176 } 177 } 178 } 179 } while (!orig.equals(uninterestingStreamEscapeSet)); 180 } 181 182 189 public boolean isUninterestingStreamEscape(Stream stream) { 190 return uninterestingStreamEscapeSet.contains(stream); 191 } 192 193 199 public void addStreamOpenLocation(Location streamOpenLocation, Stream stream) { 200 if (FindOpenStream.DEBUG) 201 System.out.println("Stream open location at " + streamOpenLocation); 202 streamOpenLocationMap.put(streamOpenLocation, stream); 203 if (stream.isUninteresting()) 204 uninterestingStreamEscapeSet.add(stream); 205 } 206 207 215 public StreamEquivalenceClass getStreamEquivalenceClass(Stream stream) { 216 return streamEquivalenceMap.get(stream); 217 } 218 219 224 private boolean isStreamOpenLocation(Location location) { 225 return streamOpenLocationMap.get(location) != null; 226 } 227 228 public Stream isResourceCreation(BasicBlock basicBlock, InstructionHandle handle, 229 ConstantPoolGen cpg) { 230 231 if (resourceCollection != null) 235 return resourceCollection.getCreatedResource(new Location(handle, basicBlock)); 236 237 Instruction ins = handle.getInstruction(); 238 if (!(ins instanceof TypedInstruction)) 239 return null; 240 241 Type type = ((TypedInstruction) ins).getType(cpg); 242 if (!(type instanceof ObjectType)) 243 return null; 244 245 Location location = new Location(handle, basicBlock); 246 247 for (StreamFactory aStreamFactoryList : streamFactoryList) { 250 Stream stream = aStreamFactoryList.createStream(location, (ObjectType) type, 251 cpg, lookupFailureCallback); 252 if (stream != null) 253 return stream; 254 } 255 256 return null; 257 } 258 259 public boolean isResourceOpen(BasicBlock basicBlock, InstructionHandle handle, 260 ConstantPoolGen cpg, Stream resource, ResourceValueFrame frame) { 261 return resource.isStreamOpen(basicBlock, handle, cpg, frame); 262 } 263 264 public boolean isResourceClose(BasicBlock basicBlock, InstructionHandle handle, 265 ConstantPoolGen cpg, Stream resource, ResourceValueFrame frame) { 266 return resource.isStreamClose(basicBlock, handle, cpg, frame, lookupFailureCallback); 267 } 268 269 public ResourceValueFrameModelingVisitor createVisitor(Stream resource, ConstantPoolGen cpg) { 270 return new StreamFrameModelingVisitor(cpg, this, resource); 271 } 272 273 public boolean ignoreImplicitExceptions(Stream resource) { 274 return resource.ignoreImplicitExceptions(); 275 } 276 277 public boolean ignoreExceptionEdge(Edge edge, Stream resource, ConstantPoolGen cpg) { 278 return false; 279 } 280 281 public boolean isParamInstance(Stream resource, int slot) { 282 return resource.getInstanceParam() == slot; 283 } 284 } 285 286 | Popular Tags |