gt: 		return resource.isStreamOpen(basicBlock, handle, cpg, frame);
context: /*
   * FindBugs - Find bugs in Java programs
   * Copyright (C) 2003,2004 University of Maryland
   * 
   * 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 edu.umd.cs.findbugs.detect;
  
  import edu.umd.cs.findbugs.ResourceCollection;
  import edu.umd.cs.findbugs.annotations.SuppressWarnings;
  import edu.umd.cs.findbugs.ba.*;
  import java.util.*;
  import org.apache.bcel.generic.*;
  
  /**
   * Resource tracker which determines where streams are created,
   * and how they are used within the method.
   *
   * @author David Hovemeyer
   */
  public class StreamResourceTracker implements ResourceTracker<Stream> {
  	private StreamFactory[] streamFactoryList;
  	private RepositoryLookupFailureCallback lookupFailureCallback;
  	private ResourceCollection<Stream> resourceCollection;
  
  	/**
  	 * Map of locations where streams are opened to the actual
  	 * Stream objects.
  	 */
  	private Map<Location, Stream> streamOpenLocationMap;
  
  	/**
  	 * Set of all open locations and escapes of uninteresting streams.
  	 */
  	//private HashSet<Location> uninterestingStreamEscapeSet;
  	private HashSet<Stream> uninterestingStreamEscapeSet;
  
  	/**
  	 * Set of all (potential) stream escapes.
  	 */
  	private TreeSet<StreamEscape> streamEscapeSet;
  
  	/**
  	 * Map of individual streams to equivalence classes.
  	 * Any time a stream "A" is wrapped with a stream "B",
  	 * "A" and "B" belong to the same equivalence class.
  	 * If any stream in an equivalence class is closed,
  	 * then we consider all of the streams in the equivalence
  	 * class as having been closed.
  	 */
  	private Map<Stream, StreamEquivalenceClass> streamEquivalenceMap;
  
  	/**
  	 * Constructor.
  	 *
  	 * @param streamFactoryList     array of StreamFactory objects which determine
  	 *                              where streams are created
  	 * @param lookupFailureCallback used when class hierarchy lookups fail
  	 */
  	@SuppressWarnings("EI2")
  	public StreamResourceTracker(StreamFactory[] streamFactoryList,
  	                             RepositoryLookupFailureCallback lookupFailureCallback) {
  
  		this.streamFactoryList = streamFactoryList;
  		this.lookupFailureCallback = lookupFailureCallback;
  		this.streamOpenLocationMap = new HashMap<Location, Stream>();
  		this.uninterestingStreamEscapeSet = new HashSet<Stream>();
  		this.streamEscapeSet = new TreeSet<StreamEscape>();
  		this.streamEquivalenceMap = new HashMap<Stream, StreamEquivalenceClass>();
  	}
  
  	/**
  	 * Set the precomputed ResourceCollection for the method.
  	 */
  	public void setResourceCollection(ResourceCollection<Stream> resourceCollection) {
  		this.resourceCollection = resourceCollection;
  	}
  
  	/**
  	 * Indicate that a stream escapes at the given target Location.
  	 *
  	 * @param source the Stream that is escaping
  	 * @param target the target Location (where the stream escapes)
  	 */
  	public void addStreamEscape(Stream source, Location target) {
  		StreamEscape streamEscape = new StreamEscape(source, target);
  		streamEscapeSet.add(streamEscape);
  		if (FindOpenStream.DEBUG)
  			System.out.println("Adding potential stream escape " + streamEscape);
  	}
  
  	/**
  	 * Transitively mark all streams into which uninteresting streams
  	 * (such as System.out) escape.  This handles the rule that
  	 * wrapping an uninteresting stream makes the wrapper uninteresting
  	 * as well.
  	 */
  	public void markTransitiveUninterestingStreamEscapes() {
  		// Eliminate all stream escapes where the target isn't really
  		// a stream open location point.
  		for (Iterator<StreamEscape> i = streamEscapeSet.iterator(); i.hasNext();) {
  			StreamEscape streamEscape = i.next();
  			if (!isStreamOpenLocation(streamEscape.target)) {
  				if (FindOpenStream.DEBUG)
  					System.out.println("Eliminating false stream escape " + streamEscape);
  				i.remove();
  			}
  		}
  
  		// Build initial stream equivalence classes.
  		// Each stream starts out in its own separate
  		// equivalence class.
  		for (Iterator<Stream> i = resourceCollection.resourceIterator(); i.hasNext();) {
  			Stream stream = i.next();
  			StreamEquivalenceClass equivalenceClass = new StreamEquivalenceClass();
  			equivalenceClass.addMember(stream);
  			streamEquivalenceMap.put(stream, equivalenceClass);
  		}
  
  		// Starting with the set of uninteresting stream open location points,
  		// propagate all uninteresting stream escapes.  Iterate until there
  		// is no change.  This also builds the map of stream equivalence classes.
  		HashSet<Stream> orig = new HashSet<Stream>();
  		do {
  			orig.clear();
  			orig.addAll(uninterestingStreamEscapeSet);
  
  			for (Iterator<StreamEscape> i = streamEscapeSet.iterator(); i.hasNext();) {
  				StreamEscape streamEscape = i.next();
  				if (isUninterestingStreamEscape(streamEscape.source)) {
  					if (FindOpenStream.DEBUG)
  						System.out.println("Propagating stream escape " + streamEscape);
  					Stream target = streamOpenLocationMap.get(streamEscape.target);
  					if (target == null)
  						throw new IllegalStateException();
  					uninterestingStreamEscapeSet.add(target);
  
  					// Combine equivalence classes for source and target
  					StreamEquivalenceClass sourceClass = streamEquivalenceMap.get(streamEscape.source);
  					StreamEquivalenceClass targetClass = streamEquivalenceMap.get(target);
  					if (sourceClass != targetClass) {
  						sourceClass.addAll(targetClass);
  						for (Iterator<Stream> j = targetClass.memberIterator(); j.hasNext();) {
  							Stream stream = j.next();
  							streamEquivalenceMap.put(stream, sourceClass);
  						}
  					}
  				}
  			}
  		} while (!orig.equals(uninterestingStreamEscapeSet));
  	}
  
  	/**
  	 * Determine if an uninteresting stream escapes at given location.
  	 * markTransitiveUninterestingStreamEscapes() should be called first.
  	 *
  	 * @param stream the stream
  	 * @return true if an uninteresting stream escapes at the location
  	 */
  	public boolean isUninterestingStreamEscape(Stream stream) {
  		return uninterestingStreamEscapeSet.contains(stream);
  	}
  
  	/**
  	 * Indicate that a stream is constructed at this Location.
  	 *
  	 * @param streamOpenLocation the Location
  	 * @param stream             the Stream opened at this Location
  	 */
  	public void addStreamOpenLocation(Location streamOpenLocation, Stream stream) {
  		if (FindOpenStream.DEBUG)
  			System.out.println("Stream open location at " + streamOpenLocation);
  		streamOpenLocationMap.put(streamOpenLocation, stream);
  		if (stream.isUninteresting())
  			uninterestingStreamEscapeSet.add(stream);
  	}
  
  	/**
  	 * Get the equivalence class for given stream.
  	 * May only be called if markTransitiveUninterestingStreamEscapes()
  	 * has been called.
  	 *
  	 * @param stream the stream
  	 * @return the set containing the equivalence class for the given stream
  	 */
  	public StreamEquivalenceClass getStreamEquivalenceClass(Stream stream) {
  		return streamEquivalenceMap.get(stream);
  	}
  
  	/**
  	 * Determine if given Location is a stream open location point.
  	 *
  	 * @param location the Location
  	 */
  	private boolean isStreamOpenLocation(Location location) {
  		return streamOpenLocationMap.get(location) != null;
  	}
  
  	public Stream isResourceCreation(BasicBlock basicBlock, InstructionHandle handle,
  	                                 ConstantPoolGen cpg) {
  
  		// Use precomputed map of Locations to Stream creations,
  		// if present.  Note that we don't care about preexisting
  		// resources here.
  		if (resourceCollection != null)
  			return resourceCollection.getCreatedResource(new Location(handle, basicBlock));
  
  		Instruction ins = handle.getInstruction();
  		if (!(ins instanceof TypedInstruction))
  			return null;
  
  		Type type = ((TypedInstruction) ins).getType(cpg);
  		if (!(type instanceof ObjectType))
  			return null;
  
  		Location location = new Location(handle, basicBlock);
  
  		// All StreamFactories are given an opportunity to
  		// look at the location and possibly identify a created stream.
  		for (int i = 0; i < streamFactoryList.length; ++i) {
  			Stream stream = streamFactoryList[i].createStream(location, (ObjectType) type,
  			        cpg, lookupFailureCallback);
  			if (stream != null)
  				return stream;
  		}
  
  		return null;
  	}
  
  	public boolean isResourceOpen(BasicBlock basicBlock, InstructionHandle handle,
  	                              ConstantPoolGen cpg, Stream resource, ResourceValueFrame frame) {
  