TopLinkWeaverpublic class TopLinkWeaver extends Object implements ClassTransformerINTERNAL:
This class performs dynamic bytecode weaving: for each attribute
mapped with One To One mapping with Basic Indirection it substitutes the
original attribute's type for ValueHolderInterface. |
Fields Summary |
---|
public static final String | WEAVING_OUTPUT_PATH | public static final String | WEAVING_SHOULD_OVERWRITE | public static final String | WEAVER_NOT_OVERWRITING | public static final String | WEAVER_COULD_NOT_WRITE | public static final String | WEAVER_FAILED | public static final String | WEAVER_TRANSFORMED_CLASS | protected Session | session | protected Map | classDetailsMap |
Constructors Summary |
---|
public TopLinkWeaver(Session session, Map classDetailsMap)
this.session = session;
this.classDetailsMap = classDetailsMap;
|
Methods Summary |
---|
public java.util.Map | getClassDetailsMap()
return classDetailsMap;
| protected static java.lang.String | getShortName(java.lang.String name)
int pos = name.lastIndexOf('/");
if (pos >= 0) {
name = name.substring(pos+1);
if (name.endsWith(";")) {
name = name.substring(0, name.length()-1);
}
return name;
}
return "";
| protected void | log(int level, java.lang.String msg, java.lang.Object[] params)
((oracle.toplink.essentials.internal.sessions.AbstractSession)session).log(level,
SessionLog.WEAVER, msg, params);
| protected void | log(int level, java.lang.Throwable t)
((oracle.toplink.essentials.internal.sessions.AbstractSession)session).logThrowable(level,
SessionLog.WEAVER, t);
| protected void | outputFile(java.lang.String className, byte[] classBytes, java.lang.String outputPath)
StringBuffer directoryName = new StringBuffer();;
StringTokenizer tokenizer = new StringTokenizer(className, "\n\\/");
String token = null;
while (tokenizer.hasMoreTokens()){
token = tokenizer.nextToken();
if (tokenizer.hasMoreTokens()){
directoryName.append(token + File.separator);
}
}
try{
String usedOutputPath = outputPath;
if (!outputPath.endsWith(File.separator)){
usedOutputPath = outputPath + File.separator;
}
File file = new File(usedOutputPath + directoryName);
file.mkdirs();
file = new File(file, token + ".class");
if (!file.exists()){
file.createNewFile();
} else {
if (!System.getProperty(WEAVING_SHOULD_OVERWRITE, "false").equalsIgnoreCase("true")){
log(SessionLog.WARNING, WEAVER_NOT_OVERWRITING, new Object[]{className});
return;
}
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(classBytes);
fos.close();
} catch (Exception e){
log(SessionLog.WARNING, WEAVER_COULD_NOT_WRITE, new Object[]{className, e});
}
| public byte[] | transform(java.lang.ClassLoader loader, java.lang.String className, java.lang.Class classBeingRedefined, java.security.ProtectionDomain protectionDomain, byte[] classfileBuffer)
/*
* The ClassFileTransformer callback - when called by the JVM's
* Instrumentation implementation - is invoked for every class loaded.
* Thus, we must check the classDetailsMap to see if we are 'interested'
* in the class.
*
* Note: when invoked by the OC4J wrapper class
* oracle.toplink.essentials.internal.ejb.cmp3.oc4j.OC4JClassTransformer,
* callbacks are made only for the 'interesting' classes
*/
ClassDetails classDetails = (ClassDetails)classDetailsMap.get(className);
if (classDetails != null) {
ClassReader cr = new ClassReader(classfileBuffer);
ClassWriter cw = new ClassWriter(true, true);
TopLinkClassWeaver tcw = new TopLinkClassWeaver(cw, classDetails);
try {
cr.accept(tcw, Attributes.getDefaultAttributes(), false);
} catch (Throwable e) {
// RuntimeException or Error could be thrown from ASM
// log here because ClassLoader ignore any Throwable
log(SessionLog.SEVERE, WEAVER_FAILED, new Object[]{className, e});
log(SessionLog.SEVERE, e);
IllegalClassFormatException ex = new IllegalClassFormatException();
ex.initCause(e);
throw ex;
}
if (tcw.alreadyWeaved) {
return null;
}
byte[] bytes = cw.toByteArray();
String outputPath = System.getProperty(WEAVING_OUTPUT_PATH, "");
if (!outputPath.equals("")) {
outputFile(className, bytes, outputPath);
}
if (tcw.weavedVH) {
log(SessionLog.FINER, WEAVER_TRANSFORMED_CLASS, new Object[]{className});
return bytes;
}
}
return null; // returning null means 'use existing class bytes'
|
|