org.curjent.impl.agent
Class MessageFactory

java.lang.Object
  extended by org.curjent.impl.agent.Factory
      extended by org.curjent.impl.agent.MessageFactory

final class MessageFactory
extends Factory

Factory for generating and creating an agent's message classes. One class is created for each unique interface method.

See Also:
TypeInfo

Field Summary
private static String CALL_INFO_DESCRIPTOR
          Internal JVM descriptor for CallInfo.
private static String CALL_STATE_DESCRIPTOR
          Internal JVM descriptor for CallState.
private static String CALL_STATE_INTERNAL
          Internal JVM name for CallState.
private static String[] DISPATCH_EXCEPTION_TYPES
          Internal JVM names for the declared exceptions of Message.dispatch(Object).
private static String FUTURE_INTERNAL
          Internal JVM name for Future.
(package private) static String INIT_DESCRIPTOR
          Internal JVM descriptor for the generated message's constructor.
private  AgentLoader loader
          Agent's loader for creating the message classes.
private static String SUPER_MESSAGE_INTERNAL
          Internal JVM name for Message.
private  TypeInfo typeInfo
          Interface and task information for generating classes.
 
Constructor Summary
MessageFactory(AgentLoader loader, TypeInfo typeInfo)
          Initializes the factory.
 
Method Summary
private  void addConstructor(ClassWriter cw)
          Generates the message class's constructor.
private  void addDispatcher(MethodInfo method, ClassWriter cw)
          Generates the message class's dispatch method.
private  void addGetArgumentMethod(MethodInfo method, ClassWriter cw)
          Generates the get argument method.
private  void addGetResultMethod(MethodInfo method, ClassWriter cw)
          Generates the get result method.
private  void addSetArgumentMethod(MethodInfo method, ClassWriter cw)
          Generates the set argument method.
private  void addSetResultMethod(MethodInfo method, ClassWriter cw)
          Generates the set result method.
(package private)  void createClass(MethodInfo method)
          Creates the message class for the given interface method.
private  ClassWriter startClass(MethodInfo method)
          Creates the ASM ClassWriter and starts bytecode generation, including definition of the message class's fields if any.
private static void visitGetBoxedField(MethodInfo method, MethodWriter mw, ParamInfo param)
          Generates code for getting a field and boxing it as needed.
private static void visitSetBoxedField(MethodInfo method, MethodWriter mw, ParamInfo param)
          Generates code for getting a field and boxing it as needed.
 
Methods inherited from class org.curjent.impl.agent.Factory
save
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

SUPER_MESSAGE_INTERNAL

private static final String SUPER_MESSAGE_INTERNAL
Internal JVM name for Message.


CALL_INFO_DESCRIPTOR

private static final String CALL_INFO_DESCRIPTOR
Internal JVM descriptor for CallInfo.


CALL_STATE_INTERNAL

private static final String CALL_STATE_INTERNAL
Internal JVM name for CallState.


CALL_STATE_DESCRIPTOR

private static final String CALL_STATE_DESCRIPTOR
Internal JVM descriptor for CallState.


DISPATCH_EXCEPTION_TYPES

private static final String[] DISPATCH_EXCEPTION_TYPES
Internal JVM names for the declared exceptions of Message.dispatch(Object).


FUTURE_INTERNAL

private static final String FUTURE_INTERNAL
Internal JVM name for Future.


INIT_DESCRIPTOR

static final String INIT_DESCRIPTOR
Internal JVM descriptor for the generated message's constructor.


loader

private final AgentLoader loader
Agent's loader for creating the message classes.


typeInfo

private final TypeInfo typeInfo
Interface and task information for generating classes.

Constructor Detail

MessageFactory

MessageFactory(AgentLoader loader,
               TypeInfo typeInfo)
Initializes the factory.

Method Detail

createClass

void createClass(MethodInfo method)
           throws Exception
Creates the message class for the given interface method. The new class is not directly used after it is created. The JVM and the class loader handle dependencies between classes and ensure the class is not garbage collected until all other classes and the class loader are also eligible for garbage collection.

Throws:
Exception

startClass

private ClassWriter startClass(MethodInfo method)
Creates the ASM ClassWriter and starts bytecode generation, including definition of the message class's fields if any.
    final class {messageName} extends Message {
        {paramType} {argName}; // for each method parameter
        {returnType} result; // for the method's result if any
        ...
    }
 


addConstructor

private void addConstructor(ClassWriter cw)
Generates the message class's constructor.
    {messageName}(CallInfo info) {
        super(info);
    }
 


addDispatcher

private void addDispatcher(MethodInfo method,
                           ClassWriter cw)
Generates the message class's dispatch method.
    protected void dispatch(Object queuedTask) throws Throwable {
        {taskType} task = ({taskType})queuedTask;
        {paramType} arg{i};
        synchronized (this) {
            if (state != EXECUTING) return;
            arg{i} = this.arg{i};
        }
        [{resultType} result =] task.{methodName}(arg{i}, ...);
        if (result != null) result = ((Future)result).get(); // task Future
        synchronized (this) {
            if (state != EXECUTING) return;
            this.result = result;
            cachedResult = this; // primitive type
            cachedResult = result; // non-primitive type
        }
    }
 


addGetArgumentMethod

private void addGetArgumentMethod(MethodInfo method,
                                  ClassWriter cw)
Generates the get argument method.
    protected Object getArgumentValue(int index) {
        // one argument
        return arg0;
        
        // two or more arguments
        Object value;
        if (index == 0) {
            value = {boxedType}.valueOf(arg{i}); // boxed types
        }
        else {
            value = arg{i}; // other types
        }
        return value;
    }
 


visitGetBoxedField

private static void visitGetBoxedField(MethodInfo method,
                                       MethodWriter mw,
                                       ParamInfo param)
Generates code for getting a field and boxing it as needed.


addSetArgumentMethod

private void addSetArgumentMethod(MethodInfo method,
                                  ClassWriter cw)
Generates the set argument method.
    protected void setArgumentValue(int index, Object value) {
        // one argument
        arg0 = ({paramType})value;
        
        // two or more arguments
        if (index == 0) {
            arg0 = value; // Object type
        }
        else if (index == 1) {
            arg1 = value==null ? {defaultValue} : (({boxedType})value).{unboxingName}Value(); // boxed type
        }
        else {
            arg2 = ({paramType})value; // other types
        }
    }
 


visitSetBoxedField

private static void visitSetBoxedField(MethodInfo method,
                                       MethodWriter mw,
                                       ParamInfo param)
Generates code for getting a field and boxing it as needed.


addGetResultMethod

private void addGetResultMethod(MethodInfo method,
                                ClassWriter cw)
Generates the get result method.
    protected Object getResultValue() {
        return {boxedType}.valueOf(result);
    }
 


addSetResultMethod

private void addSetResultMethod(MethodInfo method,
                                ClassWriter cw)
Generates the set result method.
    protected void setResultValue(Object value) {
        result = value; // Object type
        result = (value == null) ? {defaultValue} : (({boxedType})value).{unboxingName}Value(); // boxed types
        result = ({resultType})value; // other types
    }
 



Copyright 2009-2011 Tom Landon
Apache License 2.0