Package ptolemy.copernicus.kernel

Source Code of ptolemy.copernicus.kernel.LibraryUsageReporter

/* A transformer that reports library methods used.

Copyright (c) 2001-2007 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.

IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.

PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.copernicus.kernel;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import soot.EntryPoints;
import soot.HasPhaseOptions;
import soot.Hierarchy;
import soot.PhaseOptions;
import soot.RefType;
import soot.Scene;
import soot.SceneTransformer;
import soot.SootClass;
import soot.SootMethod;
import soot.Type;
import soot.Unit;
import soot.Value;
import soot.ValueBox;
import soot.jimple.CastExpr;
import soot.jimple.InstanceOfExpr;
import soot.jimple.toolkits.callgraph.CallGraph;
import soot.jimple.toolkits.callgraph.CallGraphBuilder;
import soot.jimple.toolkits.callgraph.Edge;
import soot.jimple.toolkits.callgraph.EdgePredicate;
import soot.jimple.toolkits.callgraph.Filter;
import soot.jimple.toolkits.callgraph.ReachableMethods;
import soot.jimple.toolkits.pointer.DumbPointerAnalysis;

//////////////////////////////////////////////////////////////////////////
//// LibraryUsageReporter

/**
A Transformer that reports reachable methods in the Java libraries.

@author Stephen Neuendorffer
@version $Id: LibraryUsageReporter.java,v 1.38 2007/12/06 21:56:53 cxh Exp $
@since Ptolemy II 2.0
@Pt.ProposedRating Red (cxh)
@Pt.AcceptedRating Red (cxh)

*/
public class LibraryUsageReporter extends SceneTransformer implements
        HasPhaseOptions {
    /** Return an instance of this transformer that will operate on
     *  the given model.  The model is assumed to already have been
     *  properly initialized so that resolved types and other static
     *  properties of the model can be inspected.
     */
    public static LibraryUsageReporter v() {
        return _instance;
    }

    public String getPhaseName() {
        return "";
    }

    public String getDefaultOptions() {
        return "analyzeAllReachables:false";
    }

    public String getDeclaredOptions() {
        return "outFile analyzeAllReachables";
    }

    protected void internalTransform(String phaseName, Map options) {
        String outFile = PhaseOptions.getString(options, "outFile");
        boolean analyzeAllReachables = PhaseOptions.getBoolean(options,
                "analyzeAllReachables");
        System.out.println("LibraryUsageReporter.internalTransform("
                + phaseName + ", " + options + ")");
        Scene.v().releaseCallGraph();

        CallGraphBuilder cg = new CallGraphBuilder(DumbPointerAnalysis.v(),
                true);
        cg.build();
        CallGraph callGraph = Scene.v().getCallGraph();
        ReachableMethods reachableMethods = new ReachableMethods(callGraph,
                EntryPoints.v().application());

        reachableMethods.update();

        Hierarchy hierarchy = Scene.v().getActiveHierarchy();

        final Set createableClasses = new HashSet();

        for (Iterator reachables = reachableMethods.listener(); reachables
                .hasNext();) {
            SootMethod method = (SootMethod) reachables.next();
            //String methodName = method.getSignature();

            if (method.getName().equals("<init>")
                    && !method.getDeclaringClass().getName().startsWith("java")) {
                createableClasses
                        .addAll(hierarchy.getSuperclassesOfIncluding(method
                                .getDeclaringClass()));
                _addAllInterfaces(createableClasses, method.getDeclaringClass());
            }
        }

        System.out.println("createableClasses = " + createableClasses);

        // Now create a new set of reachable methods that only
        // includes methods that are static or are declared in classes
        // that can are created.
        Filter filter = new Filter(new EdgePredicate() {
            public boolean want(Edge e) {
                SootMethod target = e.tgt();
                return e.isExplicit()
                        && (target.isStatic() || createableClasses
                                .contains(target.getDeclaringClass()));
            }
        });
        Set necessaryClasses = new HashSet();
        ReachableMethods RTAReachableMethods = new ReachableMethods(callGraph,
                EntryPoints.v().application().iterator(), filter);
        RTAReachableMethods.update();

        List list = new LinkedList();

        for (Iterator reachables = RTAReachableMethods.listener(); reachables
                .hasNext();) {
            SootMethod method = (SootMethod) reachables.next();
            String methodName = method.getSignature();
            list.add(methodName);

            SootClass declaringClass = method.getDeclaringClass();

            if (!declaringClass.getName().startsWith("java")) {
                necessaryClasses.add(declaringClass);
            }

            if (method.isConcrete()) {
                for (Iterator units = method.retrieveActiveBody().getUnits()
                        .iterator(); units.hasNext();) {
                    Unit unit = (Unit) units.next();

                    for (Iterator boxes = unit.getUseBoxes().iterator(); boxes
                            .hasNext();) {
                        ValueBox box = (ValueBox) boxes.next();
                        Value value = box.getValue();

                        if (value instanceof CastExpr) {
                            CastExpr expr = (CastExpr) value;
                            Type castType = expr.getCastType();

                            if (castType instanceof RefType) {
                                SootClass castClass = ((RefType) castType)
                                        .getSootClass();

                                if (castClass.isInterface()) {
                                    necessaryClasses.add(castClass);
                                } else {
                                    necessaryClasses
                                            .addAll(hierarchy
                                                    .getSuperclassesOfIncluding(castClass));
                                }

                                _addAllInterfaces(necessaryClasses, castClass);
                            }
                        } else if (value instanceof InstanceOfExpr) {
                            InstanceOfExpr expr = (InstanceOfExpr) value;
                            Type checkType = expr.getCheckType();

                            if (checkType instanceof RefType) {
                                SootClass checkClass = ((RefType) checkType)
                                        .getSootClass();

                                if (!checkClass.isInterface()) {
                                    necessaryClasses
                                            .addAll(hierarchy
                                                    .getSuperclassesOfIncluding(checkClass));
                                }

                                _addAllInterfaces(necessaryClasses, checkClass);
                            }
                        }
                    }
                }
            }
        }

        // Print out all the used methods
        Collections.sort(list);

        for (Iterator names = list.iterator(); names.hasNext();) {
            System.out.println(names.next());
        }

        try {
            // Add to the set of necessary classes all that they depend on.
            DependedClasses dependedClasses = new DependedClasses(
                    necessaryClasses);
            FileWriter writer = null;
            try {
                writer = new FileWriter(outFile);

                for (Iterator classes = dependedClasses.list().iterator(); classes
                        .hasNext();) {
                    SootClass theClass = (SootClass) classes.next();

                    if (analyzeAllReachables) {
                        // Set the class to be an application class, so we can
                        // analyze it.
                        theClass.setApplicationClass();
                    }

                    writer.write(theClass.getName());
                    writer.write("\n");
                }
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (IOException ex2) {
                        ex2.printStackTrace();
                    }
                }
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void _addAllInterfaces(Set classSet, SootClass theClass) {
        for (Iterator i = theClass.getInterfaces().iterator(); i.hasNext();) {
            SootClass theInterface = (SootClass) i.next();
            classSet.add(theInterface);
            _addAllInterfaces(classSet, theInterface);
        }
    }

    private static LibraryUsageReporter _instance = new LibraryUsageReporter();
}
TOP

Related Classes of ptolemy.copernicus.kernel.LibraryUsageReporter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.