/**
* This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details.
*/
package edu.illinois.keshmesh.walaconfig;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import com.ibm.wala.client.AbstractAnalysisEngine;
import com.ibm.wala.ide.util.EclipseProjectPath;
import com.ibm.wala.ide.util.EclipseProjectPath.AnalysisScopeType;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.ClassTargetSelector;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.MethodTargetSelector;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ipa.summaries.BypassClassTargetSelector;
import com.ibm.wala.ipa.summaries.BypassMethodTargetSelector;
import com.ibm.wala.ipa.summaries.MethodSummary;
import com.ibm.wala.ipa.summaries.XMLMethodSummaryReader;
import com.ibm.wala.types.MemberReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.util.strings.Atom;
import edu.illinois.keshmesh.detector.util.AnalysisUtils;
/**
*
* @author Mohsen Vakilian
* @author Stas Negara
*
*/
public class EclipseProjectAnalysisEngine extends AbstractAnalysisEngine {
private final IJavaProject javaProject;
private final int objectSensitivityLevel;
private Iterable<Entrypoint> entryPoints;
public EclipseProjectAnalysisEngine(IJavaProject javaProject, int objectSensitivityLevel) {
this.javaProject = javaProject;
this.objectSensitivityLevel = objectSensitivityLevel;
}
@Override
public void buildAnalysisScope() throws IOException {
try {
EclipseProjectPath eclipseProjectPath = EclipseProjectPath.make(javaProject, AnalysisScopeType.NO_SOURCE);
scope = eclipseProjectPath.toAnalysisScope(new File(getExclusionsFile()));
} catch (CoreException ex) {
throw new RuntimeException(ex);
}
}
/**
*
* See com.ibm.wala.ipa.callgraph.impl.Util.addBypassLogic(AnalysisOptions,
* AnalysisScope, ClassLoader, String, IClassHierarchy)
*
* @param classHierarchy
* @param analysisOptions
* @throws IllegalArgumentException
*/
private void addCustomBypassLogic(IClassHierarchy classHierarchy, AnalysisOptions analysisOptions) throws IllegalArgumentException {
ClassLoader classLoader = Util.class.getClassLoader();
if (classLoader == null) {
throw new IllegalArgumentException("classLoader is null");
}
Util.addDefaultSelectors(analysisOptions, classHierarchy);
InputStream inputStream = classLoader.getResourceAsStream(Util.nativeSpec);
XMLMethodSummaryReader methodSummaryReader = new XMLMethodSummaryReader(inputStream, scope);
MethodTargetSelector customMethodTargetSelector = getCustomBypassMethodTargetSelector(classHierarchy, analysisOptions, methodSummaryReader);
analysisOptions.setSelector(customMethodTargetSelector);
ClassTargetSelector customClassTargetSelector = new BypassClassTargetSelector(analysisOptions.getClassTargetSelector(), methodSummaryReader.getAllocatableClasses(), classHierarchy,
classHierarchy.getLoader(scope.getLoader(Atom.findOrCreateUnicodeAtom("Synthetic"))));
analysisOptions.setSelector(customClassTargetSelector);
}
private BypassMethodTargetSelector getCustomBypassMethodTargetSelector(IClassHierarchy classHierarchy, AnalysisOptions analysisOptions, XMLMethodSummaryReader summary) {
return new KeshmeshBypassMethodTargetSelector(analysisOptions.getMethodTargetSelector(), summary.getSummaries(), summary.getIgnoredPackages(), classHierarchy);
}
@Override
protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy classHierarchy, AnalysisOptions analysisOptions, AnalysisCache analysisCache) {
addCustomBypassLogic(classHierarchy, analysisOptions);
return KeshmeshAnalysisEngine.getCallGraphBuilder(scope, classHierarchy, analysisOptions, analysisCache, objectSensitivityLevel);
}
@Override
protected Iterable<Entrypoint> makeDefaultEntrypoints(AnalysisScope analysisScope, IClassHierarchy classHierarchy) {
Set<Entrypoint> entryPointsSet = KeshmeshAnalysisEngine.findEntryPoints(classHierarchy);
entryPoints = KeshmeshAnalysisEngine.toIterable(entryPointsSet);
return entryPoints;
}
public Iterable<Entrypoint> getEntryPoints() {
if (entryPoints == null) {
throw new RuntimeException("getEntryPoints() should be called after makeDefaultEntrypoints().");
}
return entryPoints;
}
}
class KeshmeshBypassMethodTargetSelector extends BypassMethodTargetSelector {
public KeshmeshBypassMethodTargetSelector(MethodTargetSelector parent, Map<MethodReference, MethodSummary> methodSummaries, Set<Atom> ignoredPackages, IClassHierarchy cha) {
super(parent, methodSummaries, ignoredPackages, cha);
}
@Override
protected boolean canIgnore(MemberReference m) {
//FIXME: LCK01BugDetector depends on some JDK classes.
// if (AnalysisUtils.isLibraryClass(m.getDeclaringClass()) || (AnalysisUtils.isJDKClass(m.getDeclaringClass()) && !AnalysisUtils.isObjectGetClass(m))) {
if (AnalysisUtils.isLibraryClass(m.getDeclaringClass())) {
return true;
} else {
return super.canIgnore(m);
}
}
}