EclipseMEClassLoadingHook.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
eclipseme.core.hooks |
![]() |
![]() |
EclipseME |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
| Metric | Description | |
|---|---|---|
/**
* Copyright (c) 2003-2006 Craig Setera
* All Rights Reserved.
* Licensed under the Eclipse Public License - v 1.0
* For more information see http://www.eclipse.org/legal/epl-v10.html
*/
package eclipseme.core.hooks;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import org.eclipse.osgi.baseadaptor.BaseData;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
import org.eclipse.osgi.framework.internal.core.BundleLoader;
import org.eclipse.osgi.util.ManifestElement;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.util.TraceClassVisitor;
import org.osgi.framework.BundleException;
/**
* Hooks the classloading functionality for EclipseME functionality.
* <p />
* Copyright (c) 2003-2006 Craig Setera<br>
* All Rights Reserved.<br>
* Licensed under the Eclipse Public License - v 1.0<p/>
* <br>
* $Revision: 1.1 $
* <br>
* $Date: 2007/01/19 01:38:10 $
* <br>
* @author Craig Setera
*/
public class EclipseMEClassLoadingHook implements ClassLoadingHook {
private static final String SOURCE_FILE_CLASS =
"org.eclipse.jdt.internal.core.builder.SourceFile";
// Type reference to the IFile interface
private static Type IFile_Type =
Type.getType("Lorg/eclipse/core/resources/IFile;");
// Type reference to the JDT SourceFile class
private static Type SourceFile_Type =
Type.getType("Lorg/eclipse/jdt/internal/core/builder/SourceFile;");
// Type reference to the SourceMapperAccess type
private static String SOURCE_MAPPER_CLASS =
"eclipseme.core.hook.sourceMapper.SourceMapperAccess";
private static Type SourceMapperAccess_Type =
Type.getType("Leclipseme/core/hook/sourceMapper/SourceMapperAccess;");
/**
* Class adapter for rewriting the get contents method.
*/
class SourceFileClassAdapter extends ClassAdapter {
/**
* Construct a new adapter instance.
*
* @param cv
*/
public SourceFileClassAdapter(ClassVisitor cv) {
super(cv);
}
/**
* @see org.objectweb.asm.ClassAdapter#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
*/
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
if (name.equals("getContents")) {
if (Debug.DEBUG_GENERAL) {
System.out.println("SourceFile#getContents spotted. Rewriting method.");
}
methodVisitor = new GetContentsMethodVisitor(methodVisitor);
}
return methodVisitor;
}
}
/**
* Class adapter for rewriting the SourceMapperAccess class
*/
class SourceMapperAccessClassAdapter extends ClassAdapter {
/**
* Construct a new adapter instance.
*
* @param cv
*/
public SourceMapperAccessClassAdapter(ClassVisitor cv) {
super(cv);
}
/**
* @see org.objectweb.asm.ClassAdapter#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
*/
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
if (name.equals("isHookCodeInstalled")) {
if (Debug.DEBUG_GENERAL) {
System.out.println("SourceMapperAccess#isHookInstalled spotted. Rewriting method.");
}
methodVisitor = new IsHookInstalledMethodVisitor(methodVisitor);
}
return methodVisitor;
}
}
/**
* MethodVisitor implementation to rewrite the getContents method of
* the SourceFile class.
*/
class GetContentsMethodVisitor extends MethodAdapter {
boolean foundReturn = false;
public GetContentsMethodVisitor(MethodVisitor mv) {
super(mv);
}
/**
* @see org.objectweb.asm.MethodAdapter#visitFieldInsn(int, java.lang.String, java.lang.String, java.lang.String)
*/
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
if ((opcode == Opcodes.GETFIELD) && (name.equals("resource")) && !foundReturn) {
insertMappedResourceCode();
} else {
super.visitFieldInsn(opcode, owner, name, desc);
}
}
/**
* @see org.objectweb.asm.MethodAdapter#visitInsn(int)
*/
public void visitInsn(int opcode) {
if (!foundReturn && (opcode == Opcodes.ARETURN)) {
if (Debug.DEBUG_GENERAL) {
System.out.println("Found ARETURN in method.");
}
foundReturn = true;
}
super.visitInsn(opcode);
}
/**
* Insert the code that will attempt to request the mapped
* resource from the {@link SourceMapperTracker}.
*/
private void insertMappedResourceCode() {
if (Debug.DEBUG_GENERAL) {
System.out.println("Inserting mapped resource lookup code into method.");
}
// We want to rewrite the first GETFIELD call for the resource
// object as a call to the mapping function
Label endLabel = new Label();
// Call through the mapper accessor to see if we
// get a mapped resource
insertDebugMessageCode("Rewritten SourceFile");
super.visitInsn(Opcodes.POP);
super.visitVarInsn(Opcodes.ALOAD, 0); // Load "this"
super.visitFieldInsn(
Opcodes.GETFIELD,
SourceFile_Type.getInternalName(),
"resource",
IFile_Type.getDescriptor());
super.visitMethodInsn(
Opcodes.INVOKESTATIC,
SourceMapperAccess_Type.getInternalName(),
"getMappedSourceFile",
Type.getMethodDescriptor(IFile_Type, new Type[] { IFile_Type }));
// If the result was non-null, we are done... otherwise we need to
// clear the extra copy and load the raw resource
super.visitInsn(Opcodes.DUP);
super.visitJumpInsn(Opcodes.IFNONNULL, endLabel);
insertDebugMessageCode("Mapped resource was null");
super.visitInsn(Opcodes.POP);
// Load the local (raw) resource
insertDebugMessageCode("Using raw resource");
super.visitVarInsn(Opcodes.ALOAD, 0); // Load "this"
super.visitFieldInsn(
Opcodes.GETFIELD,
SourceFile_Type.getInternalName(),
"resource",
IFile_Type.getDescriptor());
// All done with the rewrite
visitLabel(endLabel);
insertDebugMessageCode("Finished generated code");
}
/**
* Write the code that will write a debug message.
*
* @param message
*/
private void insertDebugMessageCode(String message) {
if (Debug.DEBUG_GENERAL) {
super.visitFieldInsn(
Opcodes.GETSTATIC,
"java/lang/System",
"out",
"Ljava/io/PrintStream;");
super.visitLdcInsn(message);
super.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
"(Ljava/lang/String;)V");
}
}
}
/**
* MethodVisitor implementation to rewrite the isHookInstalled method of
* the SourceMapperAccess class.
*/
class IsHookInstalledMethodVisitor extends MethodAdapter {
public IsHookInstalledMethodVisitor(MethodVisitor mv) {
super(mv);
}
public void visitInsn(int opcode) {
if (opcode == Opcodes.ICONST_0) {
opcode = Opcodes.ICONST_1;
}
super.visitInsn(opcode);
}
}
/**
* @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#addClassPathEntry(java.util.ArrayList, java.lang.String, org.eclipse.osgi.baseadaptor.loader.ClasspathManager, org.eclipse.osgi.baseadaptor.BaseData, java.security.ProtectionDomain)
*/
public boolean addClassPathEntry(
ArrayList cpEntries,
String cp,
ClasspathManager hostmanager,
BaseData sourcedata,
ProtectionDomain sourcedomain)
{
return false;
}
/**
* @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#createClassLoader(java.lang.ClassLoader, org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate, org.eclipse.osgi.framework.adaptor.BundleProtectionDomain, org.eclipse.osgi.baseadaptor.BaseData, java.lang.String[])
*/
public BaseClassLoader createClassLoader(
ClassLoader parent,
ClassLoaderDelegate delegate,
BundleProtectionDomain domain,
BaseData data,
String[] bundleclasspath)
{
boolean isJdtCore = "org.eclipse.jdt.core".equals(data.getSymbolicName());
boolean isEclipseBundleLoader = delegate instanceof BundleLoader;
// If the bundle loader is of the corrent type and is for
// the JDT core bundle, we will go ahead and force an OSGi "wire"
// back to our package implementation from the JDT plugin.
if (isEclipseBundleLoader && isJdtCore) {
if (Debug.DEBUG_GENERAL) {
System.out.println("Adding dynamic import into JDT Core bundle");
}
try {
ManifestElement[] dynamicElements = ManifestElement.parseHeader(
"DynamicImport-Package",
"eclipseme.core.hook.sourceMapper");
((BundleLoader) delegate).addDynamicImportPackage(dynamicElements);
} catch (BundleException e) {
if (Debug.DEBUG_GENERAL) {
e.printStackTrace();
}
}
}
// Let the framework know that we did not create the classloader
return null;
}
/**
* @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#findLibrary(org.eclipse.osgi.baseadaptor.BaseData, java.lang.String)
*/
public String findLibrary(BaseData data, String libName) {
// Do nothing
return null;
}
/**
* @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#getBundleClassLoaderParent()
*/
public ClassLoader getBundleClassLoaderParent() {
// Do nothing
return null;
}
/**
* @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#initializedClassLoader(org.eclipse.osgi.baseadaptor.loader.BaseClassLoader, org.eclipse.osgi.baseadaptor.BaseData)
*/
public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) {
// Do nothing
}
/**
* @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#processClass(java.lang.String, byte[], org.eclipse.osgi.baseadaptor.loader.ClasspathEntry, org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry, org.eclipse.osgi.baseadaptor.loader.ClasspathManager)
*/
public byte[] processClass(
String name,
byte[] classbytes,
ClasspathEntry classpathEntry,
BundleEntry entry,
ClasspathManager manager)
{
byte[] processed = null;
if (SOURCE_FILE_CLASS.equals(name) || SOURCE_MAPPER_CLASS.equals(name)) {
processed = rewriteSourceFileClass(name, classbytes);
}
return processed;
}
/**
* Rewrite the SourceFile class given the specified class bytes.
*
* @param classBytes
* @return
*/
private byte[] rewriteSourceFileClass(String name, byte[] classBytes) {
byte[] rewritten = classBytes;
if (Debug.DEBUG_GENERAL) {
System.out.println(name + " located. Rewriting class bytes.");
}
// Use ASM to rewrite the SourceFile.getMethods call
ClassReader classReader = new ClassReader(classBytes);
ClassWriter classWriter = new ClassWriter(true);
ClassAdapter adapter = null;
if (SOURCE_FILE_CLASS.equals(name)) {
adapter = new SourceFileClassAdapter(classWriter);
} else {
adapter = new SourceMapperAccessClassAdapter(classWriter);
}
classReader.accept(adapter, false);
rewritten = classWriter.toByteArray();
// Dump the rewritten class file if debug is enabled
if (Debug.DEBUG_GENERAL) {
StringWriter stringWriter = new StringWriter();
ClassReader reader = new ClassReader(rewritten);
TraceClassVisitor writer = new TraceClassVisitor(new PrintWriter(stringWriter));
reader.accept(writer, true);
System.out.println(stringWriter);
}
return rewritten;
}
}
The table below shows all metrics for EclipseMEClassLoadingHook.java.
| Metric | Value | Description | |
|---|---|---|---|



