/******************************************************************************* * 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; } }