/** * All files in the distribution of BLOAT (Bytecode Level Optimization and * Analysis tool for Java(tm)) are Copyright 1997-2001 by the Purdue * Research Foundation of Purdue University. All rights reserved. * * This library 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 library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package EDU.purdue.cs.bloat.context; import java.io.*; import java.util.*; import EDU.purdue.cs.bloat.editor.*; import EDU.purdue.cs.bloat.file.*; import EDU.purdue.cs.bloat.inline.*; import EDU.purdue.cs.bloat.reflect.*; /** * This abstract class is a central repository for all things that are necessary * for a BLOATing sessions. Its subclasses implement certain schemes for * managing BLOAT data structures such as editors and control flow graphs. */ public abstract class BloatContext implements InlineContext { public static boolean DEBUG = Boolean.getBoolean("BloatContext.DEBUG"); protected InlineStats inlineStats; // Ignore stuff for inlining protected Set ignorePackages = new HashSet(); protected Set ignoreClasses = new HashSet(); protected Set ignoreMethods = new HashSet(); protected Set ignoreFields = new HashSet(); protected boolean ignoreSystem = false; protected CallGraph callGraph; protected Set roots; // Root methods of call graph protected static void db(final String s) { if (BloatContext.DEBUG) { System.out.println(s); } } protected ClassInfoLoader loader; /** * Constructor. Each BloatContext needs to know about a * ClassInfoLoader. */ public BloatContext(final ClassInfoLoader loader) { this.loader = loader; } private static ClassLoader systemCL; static { final String s = ""; BloatContext.systemCL = s.getClass().getClassLoader(); } /** * Returns true if the give type is a system class (that is, has * the same class loader as java.lang.String). */ public static boolean isSystem(final Type type) { Class c = null; try { c = Class.forName(type.className().replace('/', '.')); } catch (final ClassNotFoundException ex) { System.err.println("** Could not find class " + type.className()); ex.printStackTrace(System.err); System.exit(1); } // Have to use == because class loader might be null return (c.getClassLoader() == BloatContext.systemCL); } public void setRootMethods(final Set roots) { if (this.callGraph != null) { // Can't set the call graph roots after its been created throw new IllegalStateException("Cannot set roots after " + "call graph has been created"); } this.roots = roots; } public CallGraph getCallGraph() { if (this.callGraph == null) { // Create a new CallGraph this.callGraph = new CallGraph(this, this.roots); } return (this.callGraph); } public InlineStats getInlineStats() { if (inlineStats == null) { inlineStats = new InlineStats(); } return (inlineStats); } public void addIgnorePackage(String name) { name = name.replace('.', '/'); ignorePackages.add(name); } public void addIgnoreClass(final Type type) { ignoreClasses.add(type); } public void addIgnoreMethod(final MemberRef method) { ignoreMethods.add(method); } public void addIgnoreField(final MemberRef field) { ignoreFields.add(field); } public void setIgnoreSystem(final boolean ignore) { this.ignoreSystem = ignore; } public boolean ignoreClass(final Type type) { // First, check to see if we explicitly ignore it. If not, check // to see if we ignore its package. The ladies always seem to // ignore my package. if (ignoreClasses.contains(type)) { return (true); } else if (type.isPrimitive()) { addIgnoreClass(type); return (true); } else { if (this.ignoreSystem) { if (BloatContext.isSystem(type)) { addIgnoreClass(type); return (true); } } String packageName = type.className(); final int lastSlash = packageName.lastIndexOf('/'); if (lastSlash == -1) { return (false); } packageName = packageName.substring(0, lastSlash); // If any ignore package is a prefix of the class's package, // then ignore it. This makes our lives easier. final Iterator packages = ignorePackages.iterator(); while (packages.hasNext()) { final String s = (String) packages.next(); if (type.className().startsWith(s)) { addIgnoreClass(type); return (true); } } return (false); } } public boolean ignoreMethod(final MemberRef method) { if (ignoreMethods.contains(method)) { return (true); } else if (ignoreClass(method.declaringClass())) { addIgnoreMethod(method); return (true); } return (false); } public boolean ignoreField(final MemberRef field) { if (ignoreMethods.contains(field)) { return (true); } else if (ignoreClass(field.declaringClass())) { addIgnoreField(field); return (true); } return (false); } /** * Commits all classes, methods, and fields, that have been modified. */ public abstract void commitDirty(); /** * Test the ignore stuff. */ public static void main(final String[] args) { final PrintWriter out = new PrintWriter(System.out, true); final PrintWriter err = new PrintWriter(System.err, true); final BloatContext context = new CachingBloatContext( new ClassFileLoader(), new ArrayList(), false); final List types = new ArrayList(); for (int i = 0; i < args.length; i++) { if (args[i].equals("-ip")) { if (++i >= args.length) { err.println("** Missing package name"); System.exit(1); } out.println("Ignoring package " + args[i]); context.addIgnorePackage(args[i]); } else if (args[i].equals("-ic")) { if (++i >= args.length) { err.println("** Missing class name"); System.exit(1); } out.println("Ignoring class " + args[i]); final String type = args[i].replace('.', '/'); context.addIgnoreClass(Type.getType("L" + type + ";")); } else { // A type final String type = args[i].replace('.', '/'); types.add(Type.getType("L" + type + ";")); } } out.println(""); final Iterator iter = types.iterator(); while (iter.hasNext()) { final Type type = (Type) iter.next(); out.println("Ignore " + type + "? " + context.ignoreClass(type)); } } }