class SimpleMethodLocalObjectsAnalysis extends SimpleMethodInfoFlowAnalysis {
  private static final Logger logger = LoggerFactory.getLogger(SimpleMethodLocalObjectsAnalysis.class);
  public static int mlocounter = 0;

  public SimpleMethodLocalObjectsAnalysis(UnitGraph g, ClassLocalObjectsAnalysis cloa, InfoFlowAnalysis dfa) {
    super(g, dfa, true, true); // special version doesn't run analysis yet

    mlocounter++;

    printMessages = false;

    SootMethod method = g.getBody().getMethod();

    AbstractDataSource sharedDataSource = new AbstractDataSource(new String("SHARED"));

    // Add a source for every parameter that is shared
    for (int i = 0; i < method.getParameterCount(); i++) // no need to worry about return value...
    {
      EquivalentValue paramEqVal = InfoFlowAnalysis.getNodeForParameterRef(method, i);
      if (!cloa.parameterIsLocal(method, paramEqVal)) {
        addToEntryInitialFlow(sharedDataSource, paramEqVal.getValue());
        addToNewInitialFlow(sharedDataSource, paramEqVal.getValue());
      }
    }

    for (SootField sf : cloa.getSharedFields()) {
      EquivalentValue fieldRefEqVal = InfoFlowAnalysis.getNodeForFieldRef(method, sf);
      addToEntryInitialFlow(sharedDataSource, fieldRefEqVal.getValue());
      addToNewInitialFlow(sharedDataSource, fieldRefEqVal.getValue());
    }

    if (printMessages) {
      logger.debug("----- STARTING SHARED/LOCAL ANALYSIS FOR " + g.getBody().getMethod() + " -----");
    }
    doFlowInsensitiveAnalysis();
    if (printMessages) {
      logger.debug("----- ENDING   SHARED/LOCAL ANALYSIS FOR " + g.getBody().getMethod() + " -----");
    }
  }

  public SimpleMethodLocalObjectsAnalysis(UnitGraph g, CallLocalityContext context, InfoFlowAnalysis dfa) {
    super(g, dfa, true, true); // special version doesn't run analysis yet

    mlocounter++;

    printMessages = false;

    SootMethod method = g.getBody().getMethod();

    AbstractDataSource sharedDataSource = new AbstractDataSource(new String("SHARED"));

    List<Object> sharedRefs = context.getSharedRefs();
    Iterator<Object> sharedRefEqValIt = sharedRefs.iterator(); // returns a list of (correctly structured) EquivalentValue
                                                               // wrapped refs that should be
                                                               // treated as shared
    while (sharedRefEqValIt.hasNext()) {
      EquivalentValue refEqVal = (EquivalentValue) sharedRefEqValIt.next();
      addToEntryInitialFlow(sharedDataSource, refEqVal.getValue());
      addToNewInitialFlow(sharedDataSource, refEqVal.getValue());
    }

    if (printMessages) {
      logger.debug("----- STARTING SHARED/LOCAL ANALYSIS FOR " + g.getBody().getMethod() + " -----");
      logger.debug("      " + context.toString().replaceAll("\n", "\n      "));
      logger.debug("found " + sharedRefs.size() + " shared refs in context.");
    }
    doFlowInsensitiveAnalysis();
    if (printMessages) {
      logger.debug("----- ENDING   SHARED/LOCAL ANALYSIS FOR " + g.getBody().getMethod() + " -----");
    }
  }

  // Interesting sources are summarized (and possibly printed)
  public boolean isInterestingSource(Value source) {
    return (source instanceof AbstractDataSource);
  }

  // Interesting sinks are possibly printed
  public boolean isInterestingSink(Value sink) {
    return true; // (sink instanceof Local); // we're interested in all values
  }

  //
  public boolean isObjectLocal(Value local) // to this analysis of this method (which depends on context)
  {<FILL_FUNCTION_BODY>}
}

    EquivalentValue source = new CachedEquivalentValue(new AbstractDataSource(new String("SHARED")));
    if (infoFlowGraph.containsNode(source)) {
      List sinks = infoFlowGraph.getSuccsOf(source);
      if (printMessages) {
        logger.debug("      Requested value " + local + " is "
            + (!sinks.contains(new CachedEquivalentValue(local)) ? "Local" : "Shared") + " in " + sm + " ");
      }
      return !sinks.contains(new CachedEquivalentValue(local));
    } else {
      if (printMessages) {
        logger.debug("      Requested value " + local + " is Local (LIKE ALL VALUES) in " + sm + " ");
      }
      return true; // no shared data in this method
    }
  
<methods>public void <init>(soot.toolkits.graph.UnitGraph, soot.jimple.toolkits.infoflow.InfoFlowAnalysis, boolean) ,public void addToEntryInitialFlow(soot.Value, soot.Value) ,public void addToNewInitialFlow(soot.Value, soot.Value) ,public void doFlowInsensitiveAnalysis() ,public MutableDirectedGraph<soot.EquivalentValue> getMethodInfoFlowSummary() ,public soot.Value getThisLocal() ,public boolean isInterestingSink(soot.Value) ,public boolean isInterestingSource(soot.Value) ,public boolean isTrackableSink(soot.Value) ,public boolean isTrackableSource(soot.Value) <variables>public static int counter,soot.jimple.toolkits.infoflow.InfoFlowAnalysis dfa,FlowSet<Pair<soot.EquivalentValue,soot.EquivalentValue>> emptySet,FlowSet<Pair<soot.EquivalentValue,soot.EquivalentValue>> entrySet,MutableDirectedGraph<soot.EquivalentValue> infoFlowGraph,private static final org.slf4j.Logger logger,boolean printMessages,boolean refOnly,soot.jimple.Ref returnRef,soot.SootMethod sm,soot.Value thisLocal