/* * Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com> * Licensed under the Apache License, Version 2.0 (the "License") * $Id: ResumableClassAdapter.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.continuations.instrument; import com.uwyn.rife.asm.*; import com.uwyn.rife.continuations.ContinuationConfigInstrument; import com.uwyn.rife.continuations.instrument.ContinuationDebug; import com.uwyn.rife.continuations.instrument.MetricsClassVisitor; import com.uwyn.rife.continuations.instrument.NoOpAnnotationVisitor; import com.uwyn.rife.continuations.instrument.ResumableMethodAdapter; import com.uwyn.rife.continuations.instrument.TypesClassVisitor; import java.util.logging.Level; import static com.uwyn.rife.continuations.instrument.ContinuationDebug.*; class ResumableClassAdapter implements ClassVisitor { private ContinuationConfigInstrument mConfig = null; private MetricsClassVisitor mMetrics = null; private TypesClassVisitor mTypes = null; private String mClassName = null; private String mEntryMethodName = null; private String mEntryMethodDesc = null; private ClassVisitor mClassVisitor = null; private boolean mAdapt = false; private NoOpAnnotationVisitor mAnnotationVisitor = new NoOpAnnotationVisitor(); ResumableClassAdapter(ContinuationConfigInstrument config, MetricsClassVisitor metrics, TypesClassVisitor types, String className, ClassVisitor classVisitor) { mConfig = config; mMetrics = metrics; mTypes = types; mClassName = className; mEntryMethodName = config.getEntryMethodName(); mEntryMethodDesc = Type.getMethodDescriptor(config.getEntryMethodReturnType(), config.getEntryMethodArgumentTypes()); mClassVisitor = classVisitor; mAdapt = (classVisitor != null); } public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visit ("+access+", \""+name+"\", \""+signature+"\", \""+superName+"\", "+(null == interfaces ? null : join(interfaces, ","))+")"); ///CLOVER:ON if (mAdapt) { mClassVisitor.visit(version, access, name, signature, superName, interfaces); } } public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visitField ("+access+", \""+name+"\", \""+desc+"\", "+signature+", "+value+")"); ///CLOVER:ON if (mAdapt) { return mClassVisitor.visitField(access, name, desc, signature, value); } return null; } public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visitMethod ("+access+", \""+name+"\", \""+desc+"\", \""+signature+"\", "+(null == exceptions ? null : join(exceptions, ","))+")"); ///CLOVER:ON // only adapt the processElement method if (mEntryMethodName.equals(name) && mEntryMethodDesc.equals(desc)) { if (mAdapt) { if (!mMetrics.makeResumable()) { return new ResumableMethodAdapter(mConfig, null, mClassVisitor.visitMethod(access, name, desc, signature, exceptions), mClassName, false, -1, 0); } else { return new ResumableMethodAdapter(mConfig, mTypes, mClassVisitor.visitMethod(access, name, desc, signature, exceptions), mClassName, true, mMetrics.getMaxLocals(), mMetrics.getPauseCount()); } } else { return new ResumableMethodAdapter(mConfig, null, null, null, false, -1, 0); } } if (null == mClassVisitor) { return null; } else { return new MethodAdapter(mClassVisitor.visitMethod(access, name, desc, signature, exceptions)); } } public void visitInnerClass(String name, String outerName, String innerName, int access) { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visitInnerClass (\""+name+"\", \""+outerName+"\", \""+innerName+", "+access+")"); ///CLOVER:ON if (mAdapt) { mClassVisitor.visitInnerClass(name, outerName, innerName, access); } } public void visitAttribute(Attribute attr) { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visitAttribute ("+attr+")"); ///CLOVER:ON if (mAdapt) { mClassVisitor.visitAttribute(attr); } } public void visitSource(String source, String debug) { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visitSource (\""+source+"\", \""+debug+"\")"); ///CLOVER:ON if (mAdapt) { mClassVisitor.visitSource(source, debug); } } public void visitOuterClass(String owner, String name, String desc) { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visitOuterClass (\""+owner+"\", \""+name+"\", \""+desc+"\")"); ///CLOVER:ON if (mAdapt) { mClassVisitor.visitOuterClass(owner, name, desc); } } public AnnotationVisitor visitAnnotation(String desc, boolean visible) { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visitAnnotation (\""+desc+"\", "+visible+")"); ///CLOVER:ON if (mAdapt) { return mClassVisitor.visitAnnotation(desc, visible); } return mAnnotationVisitor; } public void visitEnd() { ///CLOVER:OFF if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) ContinuationDebug.LOGGER.finest("Class:visitEnd ()"); ///CLOVER:ON if (mAdapt) { mClassVisitor.visitEnd(); } } }