com.google.gwt.requestfactory.server.testing.InProcessRequestContext.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.requestfactory.server.testing.InProcessRequestContext.java

Source

/*
 * Copyright 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.requestfactory.server.testing;

import com.google.gwt.autobean.server.impl.BeanMethod;
import com.google.gwt.autobean.server.impl.TypeUtils;
import com.google.gwt.autobean.shared.AutoBean.PropertyName;
import com.google.gwt.autobean.shared.AutoBeanFactory;
import com.google.gwt.requestfactory.shared.InstanceRequest;
import com.google.gwt.requestfactory.shared.JsonRpcContent;
import com.google.gwt.requestfactory.shared.JsonRpcWireName;
import com.google.gwt.requestfactory.shared.Request;
import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.impl.AbstractRequest;
import com.google.gwt.requestfactory.shared.impl.AbstractRequestContext;
import com.google.gwt.requestfactory.shared.impl.AbstractRequestFactory;
import com.google.gwt.requestfactory.shared.impl.RequestData;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Collection;

/**
 * An in-process implementation of RequestContext
 *
 * <p><span style='color:red'>RequestFactory has moved to
 * <code>com.google.web.bindery.requestfactory</code>.  This package will be
 * removed in a future version of GWT.</span></p>
 */
@Deprecated
class InProcessRequestContext extends AbstractRequestContext {
    class RequestContextHandler implements InvocationHandler {
        public Object invoke(Object proxy, Method method, final Object[] args) throws Throwable {
            // Maybe delegate to superclass
            Class<?> owner = method.getDeclaringClass();
            if (Object.class.equals(owner) || RequestContext.class.equals(owner)
                    || AbstractRequestContext.class.equals(owner)) {
                try {
                    return method.invoke(InProcessRequestContext.this, args);
                } catch (InvocationTargetException e) {
                    throw e.getCause();
                }
            }

            /*
             * Instance methods treat the 0-th argument as the instance on which to
             * invoke the method.
             */
            final Object[] actualArgs;
            Type returnGenericType;
            boolean isInstance = InstanceRequest.class.isAssignableFrom(method.getReturnType());
            if (isInstance) {
                returnGenericType = TypeUtils.getParameterization(InstanceRequest.class,
                        method.getGenericReturnType(), method.getReturnType())[1];
                if (args == null) {
                    actualArgs = new Object[1];
                } else {
                    // Save a slot for the this argument
                    actualArgs = new Object[args.length + 1];
                    System.arraycopy(args, 0, actualArgs, 1, args.length);
                }
            } else {
                returnGenericType = TypeUtils.getSingleParameterization(Request.class,
                        method.getGenericReturnType(), method.getReturnType());
                if (args == null) {
                    actualArgs = NO_ARGS;
                } else {
                    actualArgs = args;
                }
            }

            Class<?> returnType = TypeUtils.ensureBaseType(returnGenericType);
            Class<?> elementType = Collection.class.isAssignableFrom(returnType)
                    ? TypeUtils.ensureBaseType(
                            TypeUtils.getSingleParameterization(Collection.class, returnGenericType))
                    : null;

            final RequestData data;
            if (dialect.equals(Dialect.STANDARD)) {
                String operation = method.getDeclaringClass().getName() + "::" + method.getName();

                data = new RequestData(operation, actualArgs, returnType, elementType);
            } else {
                // Calculate request metadata
                JsonRpcWireName wireInfo = method.getReturnType().getAnnotation(JsonRpcWireName.class);
                String apiVersion = wireInfo.version();
                String operation = wireInfo.value();

                int foundContent = -1;
                final String[] parameterNames = args == null ? new String[0] : new String[args.length];
                Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                parameter: for (int i = 0, j = parameterAnnotations.length; i < j; i++) {
                    for (Annotation annotation : parameterAnnotations[i]) {
                        if (PropertyName.class.equals(annotation.annotationType())) {
                            parameterNames[i] = ((PropertyName) annotation).value();
                            continue parameter;
                        } else if (JsonRpcContent.class.equals(annotation.annotationType())) {
                            foundContent = i;
                            continue parameter;
                        }
                    }
                    throw new UnsupportedOperationException("No " + PropertyName.class.getCanonicalName()
                            + " annotation on parameter " + i + " of method " + method.toString());
                }
                final int contentIdx = foundContent;

                data = new RequestData(operation, actualArgs, returnType, elementType);
                for (int i = 0, j = args.length; i < j; i++) {
                    if (i != contentIdx) {
                        data.setNamedParameter(parameterNames[i], args[i]);
                    } else {
                        data.setRequestContent(args[i]);
                    }
                    data.setApiVersion(apiVersion);
                }
            }

            // Create the request, just filling in the RequestData details
            final AbstractRequest<Object> req = new AbstractRequest<Object>(InProcessRequestContext.this) {
                @Override
                protected RequestData makeRequestData() {
                    data.setPropertyRefs(propertyRefs);
                    return data;
                }
            };

            if (!isInstance) {
                // Instance invocations are enqueued when using() is called
                addInvocation(req);
            }

            if (dialect.equals(Dialect.STANDARD)) {
                return req;
            } else if (dialect.equals(Dialect.JSON_RPC)) {
                // Support optional parameters for JSON-RPC payloads
                Class<?> requestType = method.getReturnType().asSubclass(Request.class);
                return Proxy.newProxyInstance(requestType.getClassLoader(), new Class<?>[] { requestType },
                        new InvocationHandler() {
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                if (Object.class.equals(method.getDeclaringClass())
                                        || Request.class.equals(method.getDeclaringClass())) {
                                    return method.invoke(req, args);
                                } else if (BeanMethod.SET.matches(method)
                                        || BeanMethod.SET_BUILDER.matches(method)) {
                                    req.getRequestData().setNamedParameter(BeanMethod.SET.inferName(method),
                                            args[0]);
                                    return Void.TYPE.equals(method.getReturnType()) ? null : proxy;
                                }
                                throw new UnsupportedOperationException(method.toString());
                            }
                        });
            } else {
                throw new RuntimeException("Should not reach here");
            }
        }
    }

    static final Object[] NO_ARGS = new Object[0];
    private final Dialect dialect;

    protected InProcessRequestContext(AbstractRequestFactory factory, Dialect dialect) {
        super(factory, dialect);
        this.dialect = dialect;
    }

    @Override
    protected AutoBeanFactory getAutoBeanFactory() {
        return ((InProcessRequestFactory) getRequestFactory()).getAutoBeanFactory();
    }
}