org.curjent.impl.agent
Class ProxyFactory

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

final class ProxyFactory
extends Factory

Factory for generating and creating an agent's proxy. Uses TypeInfo to evaluate and gather bytecode generation information based on the agent's interfaces and task type. Delegates message class generation to MessageFactory. Caches generated classes using ProxyCache.

See Also:
Agent.newInstance(AgentLoader, Class[], AgentTasks, Class)

Field Summary
private static ProxyCache cache
          Caches the generated proxies' constructors.
private static String CALL_INFO_ARRAY_DESCRIPTOR
          Internal JVM descriptor for array of CallInfo.
private static String CALL_INFO_DESCRIPTOR
          Internal JVM descriptor for CallInfo.
private  ClassLoader classLoader
          ClassLoader from loader.
private static Class<?>[] CONSTRUCTOR_PARAMS
          Proxy constructor's parameter types.
private static String CONTROLLER_DESCRIPTOR
          Internal JVM descriptor for Controller.
private static String CONTROLLER_INTERNAL
          Internal JVM name for Controller.
private static String DISPATCH_DESCRIPTOR
          Internal JVM descriptor for the void dispatch(Message) and send methods.
private static String GET_CONTEXT_DESCRIPTOR
          Internal JVM descriptor for the MessageCall getCall() method.
private static String INIT_DESCRIPTOR
          Internal JVM descriptor for the generated proxy's constructor.
private static String INSIDER_INTERNAL
          Internal JVM name for Insider.
private  String[] interfaceNames
          Names of the agent's interfaces.
private  Class<?>[] interfaces
          Agent's interfaces.
private  AgentLoader loader
          Creates and loads generated classes.
private static String MESSAGE_CALL_DESCRIPTOR
          Internal JVM descriptor for MessageCall.
private static String MESSAGE_DESCRIPTOR
          Internal JVM descriptor for Message.
private static String MESSAGE_FUTURE_INIT_DESCRIPTOR
          Internal JVM descriptor for the MessageFuture's constructor.
private static String MESSAGE_FUTURE_INTERNAL
          Internal JVM name for MessageFuture.
private static String MESSAGE_INIT_DESCRIPTOR
          Internal JVM descriptor for the generated message constructors.
private  String proxyKey
          Unique caching key for this proxy.
private static String SUPER_INIT_DESCRIPTOR
          Internal JVM descriptor for the base Proxy constructor.
private static String SUPER_PROXY_INTERNAL
          Internal JVM name for Proxy.
private  String taskName
          Name of the task type.
private  AgentTasks tasks
          Source of tasks for the agent.
private  Class<?> taskType
          Agent's task type.
private  TypeInfo typeInfo
          Information for bytecode generation.
 
Constructor Summary
ProxyFactory(AgentLoader loader, ClassLoader classLoader, Class<?>[] interfaces, AgentTasks tasks, Class<?> taskType)
          Initializes the factory.
 
Method Summary
private  void addConstructor(ClassWriter cw)
          Generates the proxy's constructor.
private  void addMethod(ClassWriter cw, MethodInfo method, int index)
          Generates a method for the proxy.
private  ProxyInfo createClass()
          Generates and creates the proxy and message classes.
private  AgentException evaluate(Throwable exception)
          Wraps a checked exception as the cause of an AgentException.
private static String[] getNames(Class<?>[] types)
          Returns the class names for the given types.
(package private)  Object newInstance()
          Returns a new proxy.
private  ClassWriter startClass()
          Creates the ASM ClassWriter and starts generation of the proxy class.
private  void validateArguments()
          Validates the arguments to Agent.newInstance().
 
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

cache

private static final ProxyCache cache
Caches the generated proxies' constructors.


SUPER_PROXY_INTERNAL

private static final String SUPER_PROXY_INTERNAL
Internal JVM name for Proxy.


CONTROLLER_INTERNAL

private static final String CONTROLLER_INTERNAL
Internal JVM name for Controller.


CONTROLLER_DESCRIPTOR

private static final String CONTROLLER_DESCRIPTOR
Internal JVM descriptor for Controller.


MESSAGE_DESCRIPTOR

private static final String MESSAGE_DESCRIPTOR
Internal JVM descriptor for Message.


MESSAGE_CALL_DESCRIPTOR

private static final String MESSAGE_CALL_DESCRIPTOR
Internal JVM descriptor for MessageCall.


CALL_INFO_DESCRIPTOR

private static final String CALL_INFO_DESCRIPTOR
Internal JVM descriptor for CallInfo.


CALL_INFO_ARRAY_DESCRIPTOR

private static final String CALL_INFO_ARRAY_DESCRIPTOR
Internal JVM descriptor for array of CallInfo.


INSIDER_INTERNAL

private static final String INSIDER_INTERNAL
Internal JVM name for Insider.


MESSAGE_FUTURE_INTERNAL

private static final String MESSAGE_FUTURE_INTERNAL
Internal JVM name for MessageFuture.


CONSTRUCTOR_PARAMS

private static final Class<?>[] CONSTRUCTOR_PARAMS
Proxy constructor's parameter types.


INIT_DESCRIPTOR

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


SUPER_INIT_DESCRIPTOR

private static final String SUPER_INIT_DESCRIPTOR
Internal JVM descriptor for the base Proxy constructor.


MESSAGE_INIT_DESCRIPTOR

private static final String MESSAGE_INIT_DESCRIPTOR
Internal JVM descriptor for the generated message constructors.


DISPATCH_DESCRIPTOR

private static final String DISPATCH_DESCRIPTOR
Internal JVM descriptor for the void dispatch(Message) and send methods.


GET_CONTEXT_DESCRIPTOR

private static final String GET_CONTEXT_DESCRIPTOR
Internal JVM descriptor for the MessageCall getCall() method.


MESSAGE_FUTURE_INIT_DESCRIPTOR

private static final String MESSAGE_FUTURE_INIT_DESCRIPTOR
Internal JVM descriptor for the MessageFuture's constructor.


loader

private final AgentLoader loader
Creates and loads generated classes.


classLoader

private final ClassLoader classLoader
ClassLoader from loader. Used by this class for caching purposes and to verify accessibility of agent's interfaces and task type.

See Also:
AgentLoader.getClassLoader()

interfaces

private final Class<?>[] interfaces
Agent's interfaces.


interfaceNames

private final String[] interfaceNames
Names of the agent's interfaces.

See Also:
Class.getName()

tasks

private final AgentTasks tasks
Source of tasks for the agent.


taskType

private final Class<?> taskType
Agent's task type.


taskName

private final String taskName
Name of the task type.

See Also:
Class.getName()

proxyKey

private final String proxyKey
Unique caching key for this proxy.

See Also:
ProxyCache

typeInfo

private TypeInfo typeInfo
Information for bytecode generation.

Constructor Detail

ProxyFactory

ProxyFactory(AgentLoader loader,
             ClassLoader classLoader,
             Class<?>[] interfaces,
             AgentTasks tasks,
             Class<?> taskType)
Initializes the factory.

Method Detail

newInstance

Object newInstance()
Returns a new proxy. Creates the proxy and message classes if not already available in the cache.

Throws:
IllegalArgumentException - Invalid or inaccessible argument.
AgentException - Unexpected checked exception wrapped as the cause.

createClass

private ProxyInfo createClass()
                       throws Exception
Generates and creates the proxy and message classes. Returns information for the proxy class.

The proxy's constructor is cached explicitly, but the message classes are not. In fact, the message classes are generated and created but not otherwise directly referenced. The JVM and class loader resolve dependencies between classes, and the message classes are not eligible for garbage collection until all classes for the class loader, and the class loader itself, are eligible.

Throws:
Exception
See Also:
MessageFactory, AgentLoader.defineClass(String, byte[])

startClass

private ClassWriter startClass()
Creates the ASM ClassWriter and starts generation of the proxy class.
    public final class {proxyName} extends Proxy implements {interfaceNames} {
        private final CallInfo call{i};
        ...
    }
 


addConstructor

private void addConstructor(ClassWriter cw)
Generates the proxy's constructor.
    public {proxyName}(Controller controller, CallInfo[] calls) {
        super(controller);
        call{i} = calls[{i}];
    }
 


addMethod

private void addMethod(ClassWriter cw,
                       MethodInfo method,
                       int index)
Generates a method for the proxy.
    public {returnType} {methodName}({paramType} paramName, ...) throws {exceptionType}, ... {
        {messageType} message = new {messageType}(call{index});
        synchronized (message) { message.{paramName} = {paramName}; } // for each parameter
        
        try { controller.send(message); } // asynchronous, void
        try { controller.send(message); return new MessageFuture(message); } // asynchronous, future
        try { controller.send(message); return message.getCall(); } // asynchronous, agent call
        try { controller.send(message); message.await(); } // synchronous, void
        try { controller.dispatch(message); message.await(); } // synchronous, void, reentrant
        
        try { controller.send(message); message.await(); // synchronous, non-void
        try { controller.dispatch(message); message.await(); // synchronous, non-void, reentrant
        synchronized (message) { return message.result; } }
        
        catch ({exceptionType} e) { throw e; } // for each checked exception type
        catch (Throwable e) { throw Insider.evaluate(e); }
    }
 


getNames

private static String[] getNames(Class<?>[] types)
Returns the class names for the given types.


evaluate

private AgentException evaluate(Throwable exception)
Wraps a checked exception as the cause of an AgentException. Rethrows RuntimeException and Error exceptions. Extracts the root cause of a reflection InvocationTargetException.


validateArguments

private void validateArguments()
Validates the arguments to Agent.newInstance(). Checks for illegal arguments and verifies the interfaces and task type are accessible by the given class loader.

Insider.newInstance() performs a basic validation of arguments sufficient for previously created and cached proxies. This method is only used before creating a new proxy. It performs more extensive and more expensive validations.

See Also:
Agent.newInstance(AgentLoader, Class[], AgentTasks, Class)


Copyright 2009-2011 Tom Landon
Apache License 2.0