org.openspaces.remoting.RemotingAnnotationBeanPostProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.openspaces.remoting.RemotingAnnotationBeanPostProcessor.java

Source

/*
 * Copyright (c) 2008-2016, GigaSpaces Technologies, Inc. All Rights Reserved.
 *
 * 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.openspaces.remoting;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openspaces.core.GigaSpace;
import org.openspaces.core.util.AnnotationUtils;
import org.openspaces.remoting.scripting.EventDrivenScriptingExecutor;
import org.openspaces.remoting.scripting.ExecutorScriptingExecutor;
import org.openspaces.remoting.scripting.LazyLoadingRemoteInvocationAspect;
import org.openspaces.remoting.scripting.ScriptingExecutor;
import org.openspaces.remoting.scripting.ScriptingMetaArgumentsHandler;
import org.openspaces.remoting.scripting.ScriptingRemoteRoutingHandler;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import static org.openspaces.remoting.RemotingUtils.createByClassOrFindByName;

/**
 * @author kimchy
 */
public class RemotingAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements ApplicationContextAware, Ordered {

    private static final Log logger = LogFactory.getLog(RemotingAnnotationBeanPostProcessor.class);

    private ApplicationContext applicationContext;

    private Map<String, GigaSpace> gsByName;

    private GigaSpace uniqueGs;

    private int order = Ordered.LOWEST_PRECEDENCE;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean == null) {
            return bean;
        }
        Class beanClass = AopUtils.getTargetClass(bean);
        if (beanClass == null) {
            return bean;
        }
        RemotingService remotingService = AnnotationUtils.findAnnotation(beanClass, RemotingService.class);
        if (remotingService != null) {
            SpaceRemotingServiceExporter exporter;
            if (StringUtils.hasLength(remotingService.exporter())) {
                exporter = (SpaceRemotingServiceExporter) applicationContext.getBean(remotingService.exporter());
                if (exporter == null) {
                    throw new IllegalArgumentException("Failed to find exporter under name ["
                            + remotingService.exporter() + "] for bean [" + beanName + "]");
                }
            } else {
                Map exporters = applicationContext.getBeansOfType(SpaceRemotingServiceExporter.class);
                if (exporters.isEmpty()) {
                    throw new IllegalArgumentException(
                            "No service exporters are defined within the context, can't register remote service bean ["
                                    + beanName + "]");
                }
                if (exporters.size() > 1) {
                    throw new IllegalStateException(
                            "More than one service exporter are defined within the context, please specify the exact service exported to register with");
                }
                exporter = (SpaceRemotingServiceExporter) exporters.values().iterator().next();
            }
            exporter.addService(beanName, bean);
        }
        return bean;
    }

    @Override
    public boolean postProcessAfterInstantiation(final Object bean, String beanName) throws BeansException {
        Class beanClass = AopUtils.getTargetClass(bean);
        if (beanClass == null) {
            return true;
        }
        ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                ExecutorScriptingExecutor executorScriptingExecutor = field
                        .getAnnotation(ExecutorScriptingExecutor.class);
                if (executorScriptingExecutor != null) {
                    ExecutorSpaceRemotingProxyFactoryBean factoryBean = new ExecutorSpaceRemotingProxyFactoryBean();
                    factoryBean.setGigaSpace(findGigaSpaceByName(executorScriptingExecutor.gigaSpace()));
                    factoryBean.setTimeout(executorScriptingExecutor.timeout());
                    factoryBean.setMetaArgumentsHandler(new ScriptingMetaArgumentsHandler());
                    factoryBean.setRemoteInvocationAspect(new LazyLoadingRemoteInvocationAspect());
                    factoryBean.setRemoteRoutingHandler(new ScriptingRemoteRoutingHandler());
                    factoryBean.setServiceInterface(ScriptingExecutor.class);
                    factoryBean.afterPropertiesSet();
                    field.setAccessible(true);
                    field.set(bean, factoryBean.getObject());
                }
                EventDrivenScriptingExecutor eventDrivenScriptingExecutor = field
                        .getAnnotation(EventDrivenScriptingExecutor.class);
                if (eventDrivenScriptingExecutor != null) {
                    EventDrivenSpaceRemotingProxyFactoryBean factoryBean = new EventDrivenSpaceRemotingProxyFactoryBean();
                    factoryBean.setTimeout(eventDrivenScriptingExecutor.timeout());
                    factoryBean.setFifo(eventDrivenScriptingExecutor.fifo());
                    factoryBean.setGigaSpace(findGigaSpaceByName(eventDrivenScriptingExecutor.gigaSpace()));
                    factoryBean.setMetaArgumentsHandler(new ScriptingMetaArgumentsHandler());
                    factoryBean.setRemoteInvocationAspect(new LazyLoadingRemoteInvocationAspect());
                    factoryBean.setRemoteRoutingHandler(new ScriptingRemoteRoutingHandler());
                    factoryBean.setServiceInterface(ScriptingExecutor.class);
                    factoryBean.afterPropertiesSet();
                    field.setAccessible(true);
                    field.set(bean, factoryBean.getObject());
                }
                EventDrivenProxy eventDrivenProxy = field.getAnnotation(EventDrivenProxy.class);
                if (eventDrivenProxy != null) {
                    EventDrivenSpaceRemotingProxyFactoryBean factoryBean = new EventDrivenSpaceRemotingProxyFactoryBean();
                    factoryBean.setTimeout(eventDrivenProxy.timeout());
                    factoryBean.setFifo(eventDrivenProxy.fifo());
                    factoryBean.setGigaSpace(findGigaSpaceByName(eventDrivenProxy.gigaSpace()));
                    factoryBean.setAsyncMethodPrefix(eventDrivenProxy.asyncMethodPrefix());
                    factoryBean.setMetaArgumentsHandler((MetaArgumentsHandler) createByClassOrFindByName(
                            applicationContext, eventDrivenProxy.metaArgumentsHandler(),
                            eventDrivenProxy.metaArgumentsHandlerType()));
                    factoryBean.setRemoteInvocationAspect((RemoteInvocationAspect) createByClassOrFindByName(
                            applicationContext, eventDrivenProxy.remoteInvocationAspect(),
                            eventDrivenProxy.remoteInvocationAspectType()));
                    factoryBean.setRemoteRoutingHandler((RemoteRoutingHandler) createByClassOrFindByName(
                            applicationContext, eventDrivenProxy.remoteRoutingHandler(),
                            eventDrivenProxy.remoteRoutingHandlerType()));
                    factoryBean.setServiceInterface(field.getType());
                    factoryBean.afterPropertiesSet();
                    field.setAccessible(true);
                    field.set(bean, factoryBean.getObject());
                }
                ExecutorProxy executorProxy = field.getAnnotation(ExecutorProxy.class);
                if (executorProxy != null) {
                    ExecutorSpaceRemotingProxyFactoryBean factoryBean = new ExecutorSpaceRemotingProxyFactoryBean();
                    factoryBean.setGigaSpace(findGigaSpaceByName(executorProxy.gigaSpace()));
                    factoryBean.setTimeout(executorProxy.timeout());
                    factoryBean.setBroadcast(executorProxy.broadcast());
                    factoryBean.setMetaArgumentsHandler((MetaArgumentsHandler) createByClassOrFindByName(
                            applicationContext, executorProxy.metaArgumentsHandler(),
                            executorProxy.metaArgumentsHandlerType()));
                    factoryBean.setRemoteInvocationAspect((RemoteInvocationAspect) createByClassOrFindByName(
                            applicationContext, executorProxy.remoteInvocationAspect(),
                            executorProxy.remoteInvocationAspectType()));
                    factoryBean.setRemoteRoutingHandler((RemoteRoutingHandler) createByClassOrFindByName(
                            applicationContext, executorProxy.remoteRoutingHandler(),
                            executorProxy.remoteRoutingHandlerType()));
                    factoryBean.setRemoteResultReducer(
                            (RemoteResultReducer) createByClassOrFindByName(applicationContext,
                                    executorProxy.remoteResultReducer(), executorProxy.remoteResultReducerType()));
                    factoryBean.setReturnFirstResult(executorProxy.returnFirstResult());
                    factoryBean.setServiceInterface(field.getType());
                    factoryBean.afterPropertiesSet();
                    field.setAccessible(true);
                    field.set(bean, factoryBean.getObject());
                }
            }
        });

        return true;
    }

    protected GigaSpace findGigaSpaceByName(String gsName) throws NoSuchBeanDefinitionException {
        initMapsIfNecessary();
        if (gsName == null || "".equals(gsName)) {
            if (this.uniqueGs != null) {
                return this.uniqueGs;
            } else {
                throw new NoSuchBeanDefinitionException("No GigaSpaces name given and factory contains several");
            }
        }
        GigaSpace namedGs = this.gsByName.get(gsName);
        if (namedGs == null) {
            throw new NoSuchBeanDefinitionException("No GigaSpaces found for name [" + gsName + "]");
        }
        return namedGs;
    }

    /**
     * Lazily initialize gs map.
     */
    private synchronized void initMapsIfNecessary() {
        if (this.gsByName == null) {
            this.gsByName = new HashMap<String, GigaSpace>();
            // Look for named GigaSpaces

            for (String gsName : BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.applicationContext,
                    GigaSpace.class)) {

                GigaSpace gs = (GigaSpace) this.applicationContext.getBean(gsName);
                gsByName.put(gsName, gs);
            }

            if (this.gsByName.isEmpty()) {
                // Try to find a unique GigaSpaces.
                String[] gsNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.applicationContext,
                        GigaSpace.class);
                if (gsNames.length == 1) {
                    this.uniqueGs = (GigaSpace) this.applicationContext.getBean(gsNames[0]);
                }
            } else if (this.gsByName.size() == 1) {
                this.uniqueGs = this.gsByName.values().iterator().next();
            }

            if (this.gsByName.isEmpty() && this.uniqueGs == null) {
                logger.warn("No named gs instances defined and not exactly one anonymous one: cannot inject");
            }
        }
    }
}