001package co.codewizards.cloudstore.ls.client.handler;
002
003import static co.codewizards.cloudstore.core.util.Util.*;
004import static java.util.Objects.*;
005
006import co.codewizards.cloudstore.core.Uid;
007import co.codewizards.cloudstore.ls.core.invoke.ClassManager;
008import co.codewizards.cloudstore.ls.core.invoke.InverseMethodInvocationRequest;
009import co.codewizards.cloudstore.ls.core.invoke.InverseMethodInvocationResponse;
010import co.codewizards.cloudstore.ls.core.invoke.InvokeMethodExecutor;
011import co.codewizards.cloudstore.ls.core.invoke.MethodInvocationRequest;
012import co.codewizards.cloudstore.ls.core.invoke.MethodInvocationResponse;
013import co.codewizards.cloudstore.ls.core.invoke.ObjectManager;
014import co.codewizards.cloudstore.ls.core.invoke.ObjectRef;
015import co.codewizards.cloudstore.ls.core.invoke.ObjectRefWithRefId;
016import co.codewizards.cloudstore.ls.core.invoke.filter.ExtMethodInvocationRequest;
017
018public class InverseMethodInvocationRequestHandler extends AbstractInverseServiceRequestHandler<InverseMethodInvocationRequest, InverseMethodInvocationResponse> {
019
020        private static final InvokeMethodExecutor invokeMethodExecutor = new InvokeMethodExecutor();
021
022        @Override
023        public InverseMethodInvocationResponse handle(final InverseMethodInvocationRequest request) throws Exception {
024                requireNonNull(request, "request");
025
026                final MethodInvocationRequest methodInvocationRequest = request.getMethodInvocationRequest();
027                if (methodInvocationRequest != null) {
028                        final MethodInvocationResponse response = performMethodInvocation(methodInvocationRequest);
029                        return new InverseMethodInvocationResponse(request, response);
030                }
031
032                final Uid delayedResponseId = request.getDelayedResponseId();
033                if (delayedResponseId != null) {
034                        final MethodInvocationResponse response = getDelayedMethodInvocationResponse(delayedResponseId);
035                        return new InverseMethodInvocationResponse(request, response);
036                }
037
038                throw new IllegalArgumentException("request.methodInvocationRequest and request.delayedResponseId are both null!");
039        }
040
041        private MethodInvocationResponse performMethodInvocation(final MethodInvocationRequest methodInvocationRequest) throws Exception {
042                requireNonNull(methodInvocationRequest, "methodInvocationRequest");
043
044                final ObjectManager objectManager = getLocalServerClient().getObjectManager();
045                final ClassManager classManager = objectManager.getClassManager();
046
047                final String className = methodInvocationRequest.getClassName();
048                final Class<?> clazz = className == null ? null : classManager.getClassOrFail(className);
049
050                final String methodName = methodInvocationRequest.getMethodName();
051
052                if (ObjectRef.VIRTUAL_METHOD_NAME_INC_REF_COUNT.equals(methodName)) {
053                        final ObjectRefWithRefId[] objectRefWithRefIds = cast(methodInvocationRequest.getArguments()[0]);
054                        for (final ObjectRefWithRefId objectRefWithRefId : objectRefWithRefIds)
055                                objectManager.incRefCount(objectRefWithRefId.object, objectRefWithRefId.refId);
056
057                        return MethodInvocationResponse.forInvocation(null, null);
058                }
059                else if (ObjectRef.VIRTUAL_METHOD_NAME_DEC_REF_COUNT.equals(methodName)) {
060                        final ObjectRefWithRefId[] objectRefWithRefIds = cast(methodInvocationRequest.getArguments()[0]);
061                        for (final ObjectRefWithRefId objectRefWithRefId : objectRefWithRefIds)
062                                objectManager.decRefCount(objectRefWithRefId.object, objectRefWithRefId.refId);
063
064                        return MethodInvocationResponse.forInvocation(null, null);
065                }
066
067                final ExtMethodInvocationRequest extMethodInvocationRequest = new ExtMethodInvocationRequest(objectManager, methodInvocationRequest, clazz);
068                final MethodInvocationResponse response = invokeMethodExecutor.execute(extMethodInvocationRequest);
069                return response;
070
071//              InvocationFilterRegistry.getInstance().assertCanInvoke(extMethodInvocationRequest);
072//
073//              final String[] argumentTypeNames = methodInvocationRequest.getArgumentTypeNames();
074//              final Class<?>[] argumentTypes = argumentTypeNames == null ? null : classManager.getClassesOrFail(argumentTypeNames);
075//
076//              final Object[] arguments = methodInvocationRequest.getArguments();
077//
078//              Object resultObject = null;
079//
080//              final InvocationType invocationType = methodInvocationRequest.getInvocationType();
081//
082//              objectManager.getReferenceCleanerRegistry().preInvoke(extMethodInvocationRequest);
083//
084//              Throwable error = null;
085//              try {
086//                      switch (invocationType) {
087//                              case CONSTRUCTOR:
088//                                      resultObject = invokeConstructor(clazz, arguments);
089//                                      break;
090//                              case OBJECT:
091//                                      resultObject = invoke(object, methodName, argumentTypes, arguments);
092//                                      break;
093//                              case STATIC:
094//                                      resultObject = invokeStatic(clazz, methodName, arguments);
095//                                      break;
096//                              default:
097//                                      throw new IllegalStateException("Unknown InvocationType: " + invocationType);
098//                      }
099//              } catch (Throwable x) {
100//                      error = x;
101//              } finally {
102//                      objectManager.getReferenceCleanerRegistry().postInvoke(extMethodInvocationRequest, resultObject, error);
103//              }
104//
105//              if (error != null) {
106//                      if (error instanceof RuntimeException)
107//                              throw (RuntimeException) error;
108//                      else if (error instanceof Error)
109//                              throw (Error) error;
110//                      else
111//                              throw new RuntimeException(error);
112//              }
113//
114//              return new InverseMethodInvocationResponse(request, MethodInvocationResponse.forInvocation(resultObject));
115        }
116
117        private MethodInvocationResponse getDelayedMethodInvocationResponse(final Uid delayedResponseId) throws Exception {
118                requireNonNull(delayedResponseId, "delayedResponseId");
119                return invokeMethodExecutor.getDelayedResponse(delayedResponseId);
120        }
121}