Java tutorial
/* * 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.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.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.AlloyConfigurationCheck; import br.ufal.cideei.features.CIDEFeatureExtracterFactory; import br.ufal.cideei.features.FeatureSetChecker; import br.ufal.cideei.features.IFeatureExtracter; import br.ufal.cideei.soot.SootManager; import br.ufal.cideei.soot.analyses.wholeline.WholeLineObliviousReachingDefinitionsAnalysis; import br.ufal.cideei.soot.analyses.wholeline.WholeLineObliviousUninitializedVariablesAnalysis; //#ifdef METRICS import br.ufal.cideei.soot.count.AssignmentsCounter; import br.ufal.cideei.soot.count.FeatureObliviousEstimative; import br.ufal.cideei.soot.count.LocalCounter; //#endif import br.ufal.cideei.soot.instrument.FeatureModelInstrumentorTransformer; import br.ufal.cideei.util.count.MetricsSink; import br.ufal.cideei.util.count.MetricsTable; import br.ufpe.cin.dfa4spl.plverifier.alloy.io.CannotReadAlloyFileException; /** * Invokes feature-insensitive analyses on a Eclipse project. Mainly for collecting data/metrics. * * @author Trsis */ public class DoFeatureObliviousAnalysisOnClassPath extends AbstractHandler { // #ifdef METRICS private static MetricsSink sink; // #endif @Override public Object execute(ExecutionEvent event) throws ExecutionException { try { IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getActiveMenuSelection(event); Object firstElement = selection.getFirstElement(); if (!(firstElement instanceof IJavaProject)) { throw new UnsupportedOperationException("selected resource is not a java project"); } 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 only one source code classpath can be analysed at a given time. * * This seriously restricts the range of projects that can be analysed with this tool. */ List<IClasspathEntry> sourceClasspathEntries = new ArrayList<IClasspathEntry>(); 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); } } else if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { sourceClasspathEntries.add(entry); } } if (sourceClasspathEntries.size() != 1) { throw new UnsupportedOperationException("project must have exactly one source classpath entry"); } IClasspathEntry entry = sourceClasspathEntries.get(0); final int times = 10; for (int i = 0; i < times; i++) { // #ifdef METRICS String sinkFile = System.getProperty("user.home") + File.separator + javaProject.getElementName().trim().toLowerCase().replace(' ', '-') + "-fo"; // #ifdef LAZY sinkFile += "-lazy"; // #endif // #ifdef FEATUREMODEL //@ sinkFile += "-fm"; // #endif sink = new MetricsSink(new MetricsTable(new File(sinkFile + ".xls"))); // #endif this.addPacks(javaProject, entry, libsPaths.toString()); SootManager.reset(); // #ifdef METRICS sink.terminate(); // #endif System.out.println("=============" + (i + 1) + "/" + times + "============="); } sink.createFeatureObliviousSummaryFile(); } catch (Throwable e) { e.printStackTrace(); } finally { SootManager.reset(); // #ifdef METRICS if (sink != null && !sink.terminated()) { 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(); AlloyConfigurationCheck alloyConfigurationCheck = null; // #ifdef FEATUREMODEL //@ try { //@ String absolutePath = javaProject.getResource().getLocation().toFile().getAbsolutePath(); //@ alloyConfigurationCheck = new AlloyConfigurationCheck(absolutePath + File.separator + "fm.als"); //@ } catch (CannotReadAlloyFileException e) { //@ e.printStackTrace(); //@ return; //@ } // #endif addPacks(classPath, extracter, alloyConfigurationCheck); SootManager.runPacks(extracter); } private void addPacks(String classPath, IFeatureExtracter extracter, FeatureSetChecker checker) { Transform instrumentation = new Transform("jtp.fminst", new FeatureModelInstrumentorTransformer(extracter, classPath) // #ifdef METRICS .setMetricsSink(sink) // #endif // #ifdef FEATUREMODEL //@ .setFeatureModelChecker(checker) // #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 } }