rubah.runtime.classloader.VersionLoader.java Source code

Java tutorial

Introduction

Here is the source code for rubah.runtime.classloader.VersionLoader.java

Source

/*******************************************************************************
 *     Copyright 2014,
 *        Luis Pina <luis@luispina.me>,
 *        Michael Hicks <mwh@cs.umd.edu>
 *     
 *     This file is part of Rubah.
 *
 *     Rubah 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 3 of the License, or
 *     (at your option) any later version.
 *
 *     Rubah 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 Rubah.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package rubah.runtime.classloader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import org.apache.commons.io.IOUtils;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;

import rubah.bytecode.transformers.DummifyStaticInitTransformer;
import rubah.bytecode.transformers.ReflectionRewritter;
import rubah.runtime.Version;

public class VersionLoader extends DefaultClassLoader {
    protected Version version;
    private JarFile versionJar;

    public VersionLoader(Version version, File versionJar, TransformerFactory factory) {
        super(version.getNamespace(), factory);
        this.version = version;
        this.factory = factory;
        try {
            if (versionJar != null) {
                this.versionJar = new JarFile(versionJar);
            }
        } catch (IOException e) {
            throw new Error(e);
        }
    }

    @Override
    protected byte[] getOriginalClassBytes(String className) throws IOException {
        String resourceName = className.replace('.', '/') + ".class";

        if (this.versionJar == null) {
            return super.getOriginalClassBytes(className);
        }

        return this.getResource(resourceName);
    }

    @Override
    public byte[] getResource(String resourceName) throws IOException {
        if (this.versionJar == null) {
            return super.getResource(resourceName);
        }

        JarFile jarFile = this.versionJar;

        ZipEntry ze = jarFile.getEntry(resourceName);
        if (ze == null)
            throw new FileNotFoundException(resourceName);
        return IOUtils.toByteArray(jarFile.getInputStream(ze));
    }

    @Override
    protected ClassVisitor addTransformers(ClassVisitor visitor, HashMap<String, Object> objectsMap) {

        visitor = this.factory.getUpdatableClassRenamer(objectsMap, this.version, this.namespace, visitor);
        visitor = new DummifyStaticInitTransformer(objectsMap, this.version, visitor);
        visitor = new ReflectionRewritter(objectsMap, this.namespace, visitor);
        return super.addTransformers(visitor, objectsMap);
    }

    @Override
    protected void analyzeClass(byte[] classBytes) {
        // Empty, updatable classes were already analyzed
    }

    @Override
    protected ClassWriter getClassWriter(int flags) {
        return new RubahClassWriter(flags, this.version, this.namespace);
    }

    @Override
    protected String getOriginalClassName(String className) {
        return this.version.getOriginalName(className);
    }

    public JarFile getVersionJar() {
        return this.versionJar;
    }
}