/* * This is a prototype implementation of the concept of Feature-Sen * sitive Dataflow Analysis. More details in the AOSD'12 paper: * Dataflow Analysis for Software Product Lines * * This 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 software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package br.ufal.cideei.handlers; import java.io.File; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.handlers.HandlerUtil; import soot.PackManager; import soot.Scene; import soot.Transform; import br.ufal.cideei.features.CIDEFeatureExtracterFactory; import br.ufal.cideei.features.IFeatureExtracter; import br.ufal.cideei.soot.SootManager; import br.ufal.cideei.soot.instrument.FeatureModelInstrumentorTransformer; import br.ufal.cideei.util.count.MetricsSink; import br.ufal.cideei.util.count.MetricsTable; /** * Invokes feature-insensitive analyses on a Eclipse project. Mainly for collecting data/metrics. * * @author T�rsis */ public class DoFeatureObliviousAnalysisOnClassPath extends AbstractHandler { // #ifdef METRICS //@ private static MetricsSink sink; //@ // #endif @Override public Object execute(ExecutionEvent event) throws ExecutionException { // TODO: exteriorize this number as a configuration parameter. Abstract away the looping. int times = 10; try { for (int i = 0; i < times; i++) { // #ifdef METRICS //@ sink = new MetricsSink(new MetricsTable(new File(System.getProperty("user.home") + File.separator + "fo.xls"))); // #endif IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getActiveMenuSelection(event); Object firstElement = selection.getFirstElement(); if (firstElement instanceof IJavaProject) { IJavaProject javaProject = (IJavaProject) firstElement; IClasspathEntry[] classPathEntries = null; try { classPathEntries = javaProject.getResolvedClasspath(true); } catch (JavaModelException e) { e.printStackTrace(); throw new ExecutionException("No source classpath identified"); } /* * To build the path string variable that will represent Soot's classpath we will first iterate * through all libs (.jars) files, then through all source classpaths. * * FIXME: WARNING: A bug was found on Soot, in which the FileSourceTag would contain incorrect * information regarding the absolute location of the source file. In this workaround, the classpath * must be injected into the FeatureModelInstrumentorTransformer class (done though its * constructor). * * As a consequence, we CANNOT build an string with all classpaths that contains source code for the * project and thus one only source code classpath can be analysed at a given time. * * This seriously restricts the range of projects that can be analysed with this tool. */ StringBuilder libsPaths = new StringBuilder(); for (IClasspathEntry entry : classPathEntries) { if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { File file = entry.getPath().makeAbsolute().toFile(); if (file.isAbsolute()) { libsPaths.append(file.getAbsolutePath() + File.pathSeparator); } else { libsPaths.append(ResourcesPlugin.getWorkspace().getRoot().getFile(entry.getPath()).getLocation().toOSString() + File.pathSeparator); } } } for (IClasspathEntry entry : classPathEntries) { if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { this.addPacks(javaProject, entry, libsPaths.toString()); } } } SootManager.reset(); // #ifdef METRICS //@ sink.terminate(); //@ sink = null; // #endif System.out.println("=============" + (i + 1) + "/" + times + "============="); } } catch (Throwable e) { e.printStackTrace(); } finally { SootManager.reset(); // #ifdef METRICS //@ sink.terminate(); // #endif } return null; } private void addPacks(IJavaProject javaProject, IClasspathEntry entry, String libs) { /* * if the classpath entry is "", then JDT will complain about it. */ String classPath; if (entry.getPath().toOSString().equals(File.separator + javaProject.getElementName())) { classPath = javaProject.getResource().getLocation().toFile().getAbsolutePath(); } else { classPath = ResourcesPlugin.getWorkspace().getRoot().getFolder(entry.getPath()).getLocation().toOSString(); } SootManager.configure(classPath + File.pathSeparator + libs); IFeatureExtracter extracter = CIDEFeatureExtracterFactory.getInstance().getExtracter(); IPackageFragmentRoot[] packageFragmentRoots = javaProject.findPackageFragmentRoots(entry); for (IPackageFragmentRoot packageFragmentRoot : packageFragmentRoots) { IJavaElement[] children = null; try { children = packageFragmentRoot.getChildren(); } catch (JavaModelException e) { // TODO Auto-generated catch block e.printStackTrace(); } for (IJavaElement child : children) { IPackageFragment packageFragment = (IPackageFragment) child; ICompilationUnit[] compilationUnits = null; try { compilationUnits = packageFragment.getCompilationUnits(); } catch (JavaModelException e) { // TODO Auto-generated catch block e.printStackTrace(); } for (ICompilationUnit compilationUnit : compilationUnits) { String fragmentName = packageFragment.getElementName(); String compilationName = compilationUnit.getElementName(); StringBuilder qualifiedNameStrBuilder = new StringBuilder(fragmentName); // If it's the default package: if (qualifiedNameStrBuilder.length() == 0) { // Remove ".java" suffix qualifiedNameStrBuilder.append(compilationName.substring(0, compilationName.length() - 5)); } else { // Remove ".java" suffix qualifiedNameStrBuilder.append(".").append(compilationName.substring(0, compilationName.length() - 5)); } // This goes into Soot loadAndSupport SootManager.loadAndSupport(qualifiedNameStrBuilder.toString()); } } } Scene.v().loadNecessaryClasses(); addPacks(classPath, extracter); SootManager.runPacks(extracter); } private void addPacks(String classPath, IFeatureExtracter extracter) { Transform instrumentation = new Transform("jtp.fminst", new FeatureModelInstrumentorTransformer(extracter, classPath) // #ifdef METRICS //@ .setMetricsSink(sink) // #endif ); PackManager.v().getPack("jtp").add(instrumentation); // Transform reachingDef = new Transform("jap.simplerd", WholeLineObliviousReachingDefinitionsAnalysis.v() // // #ifdef METRICS // .setMetricsSink(sink) // // #endif // ); // PackManager.v().getPack("jap").add(reachingDef); // // Transform uninitVars = new Transform("jap.simpleuv", WholeLineObliviousUninitializedVariablesAnalysis.v() // // #ifdef METRICS // .setMetricsSink(sink) // // #endif // ); // PackManager.v().getPack("jap").add(uninitVars); // // // #ifdef METRICS // Transform assignmentsCounter = new Transform("jap.counter.assgnmt", new AssignmentsCounter(sink, true)); // PackManager.v().getPack("jap").add(assignmentsCounter); // // Transform localCounter = new Transform("jap.counter.local", new LocalCounter(sink, true)); // PackManager.v().getPack("jap").add(localCounter); // // Transform estimativeCounter = new Transform("jap.counter.estimative", new FeatureObliviousEstimative(sink)); // PackManager.v().getPack("jap").add(estimativeCounter); // // #endif } }