Package org.restlet.engine.resource

Source Code of org.restlet.engine.resource.ClientInvocationHandler

/**
* Copyright 2005-2011 Noelios Technologies.
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL 1.0 (the
* "Licenses"). You can select the license that you prefer but you may not use
* this file except in compliance with one of these Licenses.
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.opensource.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.opensource.org/licenses/lgpl-2.1.php
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.opensource.org/licenses/cddl1.php
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.noelios.com/products/restlet-engine
*
* Restlet is a registered trademark of Noelios Technologies.
*/

package org.restlet.engine.resource;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Uniform;
import org.restlet.data.ClientInfo;
import org.restlet.representation.Representation;
import org.restlet.representation.Variant;
import org.restlet.resource.ClientProxy;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Result;

// [excludes gwt]
/**
* Reflection proxy invocation handler created for the
* {@link ClientResource#wrap(Class)} and related methods.
*
* @author Jerome Louvel
*
* @param <T> The annotated resource interface.
*/
public class ClientInvocationHandler<T> implements InvocationHandler {

    /** The annotations of the resource interface. */
    private final List<AnnotationInfo> annotations;

    /** The associated client resource. */
    private final ClientResource clientResource;

    /**
     * Constructor.
     *
     * @param clientResource
     *            The associated client resource.
     * @param resourceInterface
     *            The annotated resource interface.
     */
    public ClientInvocationHandler(ClientResource clientResource,
            Class<? extends T> resourceInterface) {
        this.clientResource = clientResource;

        // Introspect the interface for Restlet annotations
        this.annotations = AnnotationUtils.getAnnotations(resourceInterface);
    }

    /**
     * Returns the annotations of the resource interface.
     *
     * @return The annotations of the resource interface.
     */
    public List<AnnotationInfo> getAnnotations() {
        return annotations;
    }

    /**
     * Returns the associated client resource.
     *
     * @return The associated client resource.
     */
    public ClientResource getClientResource() {
        return clientResource;
    }

    /**
     * Effectively invokes a Java method on the given proxy object.
     */
    @SuppressWarnings("rawtypes")
    public Object invoke(Object proxy, java.lang.reflect.Method javaMethod,
            Object[] args) throws Throwable {
        Object result = null;

        if (javaMethod.equals(Object.class.getMethod("toString"))) {
            // Help debug
            result = "ClientProxy for resource: " + clientResource;
        } else if (javaMethod.equals(ClientProxy.class
                .getMethod("getClientResource"))) {
            result = clientResource;
        } else {
            AnnotationInfo annotation = AnnotationUtils.getAnnotation(
                    annotations, javaMethod);

            if (annotation != null) {
                Representation requestEntity = null;
                boolean isSynchronous = true;

                if ((args != null) && args.length > 0) {
                    // Checks if the user has defined its own
                    // callback.
                    for (int i = 0; i < args.length; i++) {
                        Object o = args[i];

                        if (o == null) {
                            requestEntity = null;
                        } else if (Result.class.isAssignableFrom(o.getClass())) {
                            // Asynchronous mode where a callback
                            // object is to be called.
                            isSynchronous = false;

                            // Get the kind of result expected.
                            final Result rCallback = (Result) o;
                            Type[] genericParameterTypes = javaMethod
                                    .getGenericParameterTypes();
                            Type genericParameterType = genericParameterTypes[i];
                            ParameterizedType parameterizedType = (genericParameterType instanceof java.lang.reflect.ParameterizedType) ? (java.lang.reflect.ParameterizedType) genericParameterType
                                    : null;
                            final Class<?> actualType = (parameterizedType
                                    .getActualTypeArguments()[0] instanceof Class<?>) ? (Class<?>) parameterizedType
                                    .getActualTypeArguments()[0] : null;

                            // Define the callback
                            Uniform callback = new Uniform() {
                                @SuppressWarnings("unchecked")
                                public void handle(Request request,
                                        Response response) {
                                    if (response.getStatus().isError()) {
                                        rCallback
                                                .onFailure(new ResourceException(
                                                        response.getStatus()));
                                    } else {
                                        if (actualType != null) {
                                            rCallback
                                                    .onSuccess(getClientResource()
                                                            .toObject(
                                                                    response.getEntity(),
                                                                    actualType
                                                                            .getClass()));
                                        } else {
                                            rCallback.onSuccess(null);
                                        }
                                    }
                                }
                            };

                            getClientResource().setOnResponse(callback);
                        } else {
                            requestEntity = getClientResource()
                                    .toRepresentation(args[i], null);
                        }
                    }
                }

                // Clone the prototype request
                Request request = getClientResource().createRequest(
                        getClientResource().getRequest());

                // The Java method was annotated
                request.setMethod(annotation.getRestletMethod());

                // Set the entity
                request.setEntity(requestEntity);

                // Updates the client preferences if they weren't changed
                if ((request.getClientInfo().getAcceptedCharacterSets().size() == 0)
                        && (request.getClientInfo().getAcceptedEncodings()
                                .size() == 0)
                        && (request.getClientInfo().getAcceptedLanguages()
                                .size() == 0)
                        && (request.getClientInfo().getAcceptedMediaTypes()
                                .size() == 0)) {
                    List<Variant> responseVariants = annotation
                            .getResponseVariants(getClientResource()
                                    .getMetadataService(), getClientResource()
                                    .getConverterService());

                    if (responseVariants != null) {
                        request.setClientInfo(new ClientInfo(responseVariants));
                    }
                }

                // Effectively handle the call
                Response response = getClientResource().handle(request);

                // Handle the response
                if (isSynchronous) {
                    if (response.getStatus().isError()) {
                        getClientResource().doError(response.getStatus());
                    }

                    if (!annotation.getJavaOutputType().equals(void.class)) {
                        result = getClientResource()
                                .toObject(
                                        (response == null ? null
                                                : response.getEntity()),
                                        annotation.getJavaOutputType());
                    }
                }
            }
        }

        return result;
    }

}
TOP

Related Classes of org.restlet.engine.resource.ClientInvocationHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.