Package org.springbyexample.mvc.rest.client.factory

Source Code of org.springbyexample.mvc.rest.client.factory.RestClientFactoryBean

/*
* Copyright 2007-2013 the original author or authors.
*
* 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 org.springbyexample.mvc.rest.client.factory;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springbyexample.mvc.bind.annotation.RestRequestResource;
import org.springbyexample.mvc.bind.annotation.RestResource;
import org.springbyexample.mvc.rest.client.RestClient;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodFilter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethodSelector;


/**
* Creates a REST client bean instances from type and method-level
* {@link RequestMapping @RequestMapping} annotations in
* {@link @RestResource @RestResource} classes.
*
* @author David Winterfeldt
*/
public class RestClientFactoryBean {

    final Logger logger = LoggerFactory.getLogger(getClass());

    private final RestClient client;
    private Class<?> marshallingServiceClass;

    private Object bean;

    @Autowired
    public RestClientFactoryBean(RestClient client) {
        this.client = client;
    }

    public void setMarshallingServiceClass(Class<?> marshallingServiceClass) {
        this.marshallingServiceClass = marshallingServiceClass;
    }

    public Object getBean() throws BeansException {
        logger.info("########## {} ######", marshallingServiceClass);

        if (bean == null) {
            RestResource restResource = AnnotationUtils.findAnnotation(marshallingServiceClass, RestResource.class);
            Class<?> serviceClass = restResource.service();

            Map<Method, ClientRequestHandlerInfo> methodRequestHandlers = new HashMap<Method, ClientRequestHandlerInfo>();

            Set<Method> methods = HandlerMethodSelector.selectMethods(marshallingServiceClass, new MethodFilter() {
                @Override
                public boolean matches(Method method) {
                    return (AnnotationUtils.findAnnotation(method, RequestMapping.class) != null);
                }
            });

            for (Method interfaceMethod : methods) {
                Method method = BridgeMethodResolver.findBridgedMethod(interfaceMethod);
                Class<?> responseClazz = method.getReturnType();

                RequestMapping requestMapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
                RestRequestResource restRequestResource = AnnotationUtils.findAnnotation(method, RestRequestResource.class);
                boolean export = (restRequestResource != null ? restRequestResource.export() : true);

                // if the method declaring class is in the parent, get the return type from the service or converter (because of erasure)
                if (!marshallingServiceClass.equals(method.getDeclaringClass())) {
                    String restRequestResourceMethodName = (restRequestResource != null ? restRequestResource.methodName() : null);
                    String methodName = (StringUtils.hasText(restRequestResourceMethodName) ? restRequestResourceMethodName : method.getName());
                    Class<?>[] paramTypes = method.getParameterTypes();

                    try {
                        Method serviceMethod = ReflectionUtils.findMethod(serviceClass, methodName, paramTypes);
                        responseClazz = serviceMethod.getReturnType();
                    } catch(IllegalStateException e) {
                    }
                }

                if (export) {
                    boolean relative = (restRequestResource != null ? restRequestResource.relative() : true);

                    // just get first param if more than one
                    StringBuilder uri = new StringBuilder();

                    if (relative) {
                        for (String pattern : requestMapping.value()) {
                            // add REST resource path prefix to URI,
                            // if relative path is just '/' add an empty string
                            uri.append(restResource.path());
                            uri.append((!"/".equals(pattern) ? pattern : ""));

                            break;
                        }
                    } else {
                        uri.append(requestMapping.value()[0]);
                    }

                    String[] params = requestMapping.params();

                    if (params != null && params.length > 0) {
                        uri.append("?");

                        for (int i = 0; i < params.length; i++) {
                            String param = params[i];

                            uri.append(param);
                            uri.append("={");
                            uri.append(param);
                            uri.append("}");

                            if (i < (params.length - 1)) {
                                uri.append("&");
                            }
                        }
                    }

                    RequestMethod requestMethod = requestMapping.method()[0];

                    if (RequestMethod.POST.equals(requestMethod) || RequestMethod.PUT.equals(requestMethod)
                            || RequestMethod.DELETE.equals(requestMethod)) {
                        responseClazz = restResource.responseClass();
                    }
//                    else if (RequestMethod.DELETE.equals(requestMethod)) {
//                        responseClazz = ResponseResult.class;
//                    }

                    ClientRequestHandlerInfo clientRequestHandlerInfo =
                            new ClientRequestHandlerInfo(uri.toString(), responseClazz, requestMethod);

                    methodRequestHandlers.put(method, clientRequestHandlerInfo);
                } else {
                    // configure to throw UnsupportedOperationException
                }

            }

            bean = Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), new Class[] { marshallingServiceClass },
                                          new RestClientInvocationHandler(client, methodRequestHandlers));
        }

        return bean;
    }

}
TOP

Related Classes of org.springbyexample.mvc.rest.client.factory.RestClientFactoryBean

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.