/* * 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 java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.handlers.HandlerUtil; import soot.G; import soot.spl.ifds.Main; import br.ufpe.cin.emergo.properties.DFA4SPLProperties; //TODO: this class is very similar to DoFeatureObliviousAnalysisOnClassPath. Check for common funcionality and for code reuse opportunities. /** * Invokes feature-sensitive analyses on a Eclipse project. Mainly for collecting data/metrics. * * @author T�rsis */ public class DoAnalysisOnClassPath extends AbstractHandler { // #ifdef METRICS //@ private static MetricsSink sink; //@ // #endif @Override public Object execute(ExecutionEvent event) throws ExecutionException { IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getActiveMenuSelection(event); Object firstElement = selection.getFirstElement(); if (firstElement instanceof IJavaProject) { IJavaProject javaProject = (IJavaProject) firstElement; applyToProject(javaProject, AnalysisArgs.interactive()); } else if(firstElement instanceof ICompilationUnit) { ICompilationUnit cu = (ICompilationUnit) firstElement; IType type = cu.findPrimaryType(); IJavaProject javaProject = cu.getJavaProject(); if(type!=null) { try { String mainClass = type.getFullyQualifiedName(); Main.main(getSootClasspath(javaProject), mainClass, javaProject, AnalysisArgs.interactive()); } finally { G.reset(); } } } // //#ifdef CACHEPURGE ////@ br.Main.randomLong(); // //#endif // // // TODO: exteriorize this number as a configuration parameter. Abstract away the looping. // int times = 1; // try { // for (int i = 0; i < times; i++) { // // #ifdef METRICS ////@ sink = new MetricsSink(new MetricsTable(new File(System.getProperty("user.home") + File.separator + "fs.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 through 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()); // } // } // } // // Resets SOOT // SootManager.reset(); // // /* // * terminate the Metrics Facade. This dumps all the in-memory information. // */ // // #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; } public static void applyToProject(IJavaProject javaProject, AnalysisArgs args) { try { String mainClass = DFA4SPLProperties.getMainClass(javaProject.getResource()); Main.main(getSootClasspath(javaProject), mainClass, javaProject, args); } finally { G.reset(); } } public static URL[] projectClassPath(IJavaProject javaProject) { IClasspathEntry[] cp; try { cp = javaProject.getResolvedClasspath(true); List<URL> urls = new ArrayList<URL>(); // String uriString = ResourcesPlugin.getWorkspace().getRoot().getFile( // javaProject.getOutputLocation()).getLocationURI().toString() // + "/"; // urls.add(new URI(uriString).toURL()); for (IClasspathEntry entry : cp) { IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(entry.getPath()); File f; if(file==null) { f = entry.getPath().toFile(); } else { IPath location = file.getLocation(); if(location!=null) f = location.toFile(); else f = file.getFullPath().toFile(); } URL url = f.toURI().toURL(); urls.add(url); } URL[] array = new URL[urls.size()]; urls.toArray(array); return array; } catch (JavaModelException e) { e.printStackTrace(); return new URL[0]; } catch (MalformedURLException e) { e.printStackTrace(); return new URL[0]; } } public static String getSootClasspath(IJavaProject javaProject) { return urlsToString(projectClassPath(javaProject)); } public static String urlsToString(URL[] urls) { StringBuffer cp = new StringBuffer(); for (URL url : urls) { cp.append(url.getPath()); cp.append(File.pathSeparator); } return cp.toString(); } }