/*
* Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: MetaDataBytecodeTransformer.java 3918 2008-04-14 17:35:35Z gbevin $
*/
package com.uwyn.rife.site.instrument;
import com.uwyn.rife.asm.ClassReader;
import com.uwyn.rife.asm.ClassVisitor;
import com.uwyn.rife.asm.ClassWriter;
import com.uwyn.rife.site.MetaDataMerged;
/**
* This utility class provides an entrance method to modify the bytecode of a
* class so that meta data from a sibling class is merged into the first class.
* <p>
* Basically, this automatically creates an instance of the meta data class and
* stores it as a field of the modified class. All the interfaces of the meta
* data class are also automatically implemented by the modified class by
* delegating all the method calls to the added field instance.
* <p>
* WARNING: this class is not supposed to be used directly, it is made public
* since the general RIFE EngineClassLoader has to be able to access it.
*
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
* @version $Revision: 3918 $
* @since 1.6
*/
public abstract class MetaDataBytecodeTransformer
{
/**
* Performs the actual merging of the meta data class' functionalities into
* the bytes of the class that were provided.
*
* @param origBytes the bytes that have to be modied
* @param metaData the meta data classes that will be merged into it
* @return the modified bytes
* @since 1.6
*/
public static byte[] mergeMetaDataIntoBytes(byte[] origBytes, Class metaData)
{
// only perform the instrumentation if the MetaDataMerged interface is implemented
if (!MetaDataMerged.class.isAssignableFrom(metaData))
{
return origBytes;
}
// merge the meta data class into the original bytes
ClassReader cr = new ClassReader(origBytes);
MetaDataMethodCollector method_collector = new MetaDataMethodCollector();
cr.accept(method_collector, ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor meta_data_adapter = new MetaDataClassAdapter(method_collector.getMethods(), metaData, cw);
cr.accept(meta_data_adapter, ClassReader.SKIP_FRAMES);
return cw.toByteArray();
}
}