se.sics.kompics.simulation.TimeInterceptor.java Source code

Java tutorial

Introduction

Here is the source code for se.sics.kompics.simulation.TimeInterceptor.java

Source

/**
 * This file is part of the Kompics P2P Framework.
 * 
 * Copyright (C) 2009 Swedish Institute of Computer Science (SICS)
 * Copyright (C) 2009 Royal Institute of Technology (KTH)
 *
 * Kompics is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package se.sics.kompics.simulation;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Properties;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import javassist.Translator;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;

/**
 * The <code>TimeInterceptor</code> class.
 * 
 * @author Cosmin Arad <cosmin@sics.se>
 * @version $Id$
 */
public class TimeInterceptor implements Translator {

    private static final String s = "se.sics.kompics.simulation.SimulatorSystem";

    private static HashSet<String> exceptions = new HashSet<String>();

    private File directory;

    public TimeInterceptor(File directory) {
        this.directory = directory;
    }

    public void start(ClassPool pool) throws NotFoundException, CannotCompileException {

        // well known exceptions
        exceptions.add("se.sics.kompics.p2p.simulator.P2pSimulator");
        exceptions.add("org.apache.log4j.PropertyConfigurator");
        exceptions.add("org.apache.log4j.helpers.FileWatchdog");
        exceptions.add("org.mortbay.thread.QueuedThreadPool");
        exceptions.add("org.mortbay.io.nio.SelectorManager");
        exceptions.add("org.mortbay.io.nio.SelectorManager$SelectSet");
        exceptions.add("org.apache.commons.math.stat.descriptive.SummaryStatistics");
        exceptions.add("org.apache.commons.math.stat.descriptive.DescriptiveStatistics");

        // try to add user-defined exceptions from properties file
        InputStream in = ClassLoader.getSystemResourceAsStream("timer.interceptor.properties");
        Properties p = new Properties();
        if (in != null) {
            try {
                p.load(in);
                for (String classname : p.stringPropertyNames()) {
                    String value = p.getProperty(classname);
                    if (value != null && value.equals("IGNORE")) {
                        exceptions.add(classname);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void onLoad(ClassPool pool, final String classname) throws NotFoundException, CannotCompileException {

        int d = classname.indexOf("$");
        String outerClass = (d == -1 ? classname : classname.substring(0, d));

        if (exceptions.contains(outerClass)) {
            CtClass cc = pool.get(classname);
            saveClass(cc);

            return;
        }

        CtClass cc = pool.get(classname);

        // makeSerializable(pool, cc);

        cc.defrost();
        cc.instrument(new ExprEditor() {
            // redirect method calls
            @Override
            public void edit(MethodCall m) throws CannotCompileException {
                String className = m.getClassName();
                String method = m.getMethodName();
                try {
                    className = m.getMethod().getDeclaringClass().getName();
                } catch (NotFoundException e) {
                    throw new RuntimeException(
                            "Cannot instrument call to " + className + "." + method + "() in " + classname, e);
                }
                if (className == null || method == null) {
                    return;
                }
                // redirect calls to System.currentTimeMillis()
                if (className.equals("java.lang.System") && method.equals("currentTimeMillis")) {

                    m.replace("{ $_ = " + s + ".currentTimeMillis(); }");
                }
                // redirect calls to System.nanoTime()
                if (className.equals("java.lang.System") && method.equals("nanoTime")) {
                    m.replace("{ $_ = " + s + ".nanoTime(); }");
                }
                // redirect calls to Thread.sleep()
                if (className.equals("java.lang.Thread") && method.equals("sleep")) {
                    m.replace("{ " + s + ".sleep($$); }");
                }
                // redirect calls to Thread.start()
                if (className.equals("java.lang.Thread") && method.equals("start")) {
                    m.replace("{ " + s + ".start(); }");
                }
            }
        });

        saveClass(cc);
    }

    private void saveClass(CtClass cc) {
        if (directory != null) {
            try {
                cc.writeFile(directory.getAbsolutePath());
            } catch (CannotCompileException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // private void makeSerializable(ClassPool pool, CtClass cc)
    // throws NotFoundException {
    // boolean alreadySerializable = false;
    // CtClass parent = cc;
    //      
    // // abort if class is already Serializable
    // do {
    // CtClass[] interfaces = parent.getInterfaces();
    // for (int i = 0; i < interfaces.length; i++) {
    // if (interfaces[i].getName().equals("java.io.Serializable")) {
    // alreadySerializable = true;
    // }
    // }
    // parent = parent.getSuperclass();
    // } while (parent != null);
    //
    // if (!alreadySerializable) {
    // cc.addInterface(pool.get("java.io.Serializable"));
    // }
    // }
}