final EJBLocator locator = invocation.getLocator();
final EjbDeploymentInformation ejb = findBean(locator.getAppName(), locator.getModuleName(), locator.getDistinctName(), locator.getBeanName());
final EJBComponent ejbComponent = ejb.getEjbComponent();
final Class<?> viewClass = invocation.getViewClass();
final ComponentView view = ejb.getView(viewClass.getName());
if (view == null) {
throw new RuntimeException("Could not find view " + viewClass + " for ejb " + ejb.getEjbName());
}
final ClonerConfiguration paramConfig = new ClonerConfiguration();
paramConfig.setClassCloner(new ClassLoaderClassCloner(ejb.getDeploymentClassLoader()));
final ObjectCloner parameterCloner = ObjectCloners.getSerializingObjectClonerFactory().createCloner(paramConfig);
//TODO: this is not very efficent
final Method method = view.getMethod(invocation.getInvokedMethod().getName(), DescriptorUtils.methodDescriptor(invocation.getInvokedMethod()));
final boolean async = view.isAsynchronous(method);
final Object[] parameters;
if (invocation.getParameters() == null) {
parameters = EMPTY_OBJECT_ARRAY;
} else {
parameters = new Object[invocation.getParameters().length];
for (int i = 0; i < parameters.length; ++i) {
parameters[i] = clone(method.getParameterTypes()[i], parameterCloner, invocation.getParameters()[i], allowPassByReference);
}
}
final InterceptorContext context = new InterceptorContext();
context.setParameters(parameters);
context.setMethod(method);
context.setTarget(invocation.getInvokedProxy());
context.setContextData(new HashMap<String, Object>());
context.putPrivateData(Component.class, ejbComponent);
context.putPrivateData(ComponentView.class, view);
if (locator instanceof StatefulEJBLocator) {
final SessionID sessionID = ((StatefulEJBLocator) locator).getSessionId();
context.putPrivateData(SessionID.SESSION_ID_KEY, sessionID);
} else if (locator instanceof EntityEJBLocator) {
final Object primaryKey = ((EntityEJBLocator) locator).getPrimaryKey();
context.putPrivateData(EntityBeanComponent.PRIMARY_KEY_CONTEXT_KEY, primaryKey);
}
final ClonerConfiguration config = new ClonerConfiguration();
config.setClassCloner(new ClassLoaderClassCloner(invocation.getInvokedProxy().getClass().getClassLoader()));
final ObjectCloner resultCloner = ObjectCloners.getSerializingObjectClonerFactory().createCloner(config);
if (async) {
if (ejbComponent instanceof SessionBeanComponent) {
final SessionBeanComponent component = (SessionBeanComponent) ejbComponent;
final CancellationFlag flag = new CancellationFlag();
final AsyncInvocationTask task = new AsyncInvocationTask(flag) {
@Override
protected Object runInvocation() throws Exception {
return view.invoke(context);
}
};
context.putPrivateData(CancellationFlag.class, flag);
component.getAsynchronousExecutor().submit(task);
//TODO: we do not clone the result of an async task
//TODO: we do not clone the exception of an async task
receiverContext.resultReady(new ImmediateResultProducer(task));
} else {
throw new RuntimeException("Cannot perform asynchronous local invocation for component that is not a session bean");
}
} else {
final Object result;
try {
result = view.invoke(context);
} catch (Exception e) {
//we even have to clone the exception type
//to make sure it matches
throw (Exception) clone(resultCloner, e);
}