org.jdal.aop.SerializableReference.java Source code

Java tutorial

Introduction

Here is the source code for org.jdal.aop.SerializableReference.java

Source

/*
 * Copyright 2009-2014 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.jdal.aop;

import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

/**
 * Serializable reference to a bean in application context.
 * 
 * @author Jose Luis Martin
 * @since 2.0
 *
 */
public class SerializableReference implements Serializable {

    private static final Log log = LogFactory.getLog(SerializableReference.class);
    private static final Map<String, Object> serializedObjects = new ConcurrentHashMap<String, Object>();
    /** force to use cglib in deseriazed proxies */
    private boolean proxyTargetClass;
    /** hold a copy of bean in memory instead looking in a bean factory */
    private boolean useMemoryCache;
    /** dependency descriptor used to lookup bean on deserialization */
    private DependencyDescriptor descriptor;
    /** bean factory to use */
    private ConfigurableListableBeanFactory beanFactory;
    /** id for in memory cache */
    private String id;
    /** bean name holding the serializable proxy */
    private String beanName;
    /** target object */
    private transient Object target;
    /** target bean name */
    private String targetBeanName;

    public SerializableReference() {

    }

    public SerializableReference(Object target, boolean proxyTargetClass, boolean useMemoryCache,
            ConfigurableListableBeanFactory beanFactory, DependencyDescriptor descriptor, String beanName) {

        this.proxyTargetClass = proxyTargetClass;
        this.useMemoryCache = useMemoryCache;
        this.beanFactory = beanFactory;
        this.beanName = beanName;
        this.descriptor = descriptor;
        this.target = target;
    }

    public SerializableReference(Object target, boolean proxyTargetClass, boolean useMemoryCache,
            ConfigurableListableBeanFactory beanFactory, String targetBeanName) {
        this(target, proxyTargetClass, useMemoryCache, beanFactory, null, null);
        this.targetBeanName = targetBeanName;
    }

    public void serialize() {
        if (useMemoryCache) {
            this.id = ObjectUtils.identityToString(target);
            serializedObjects.put(id, target);

            if (log.isDebugEnabled())
                log.debug("Added new serialized reference. serialized objects size [" + serializedObjects.size()
                        + "]");
        }
    }

    private Object readResolve() throws ObjectStreamException {
        if (beanFactory == null) {
            log.error("Can't not deserialize reference without bean factory");
            return null;
        }

        if (useMemoryCache) {
            Object ret = serializedObjects.remove(this.id);
            if (ret != null) {
                if (log.isDebugEnabled())
                    log.debug("Removed a serialized reference. serialized objects size [" + serializedObjects.size()
                            + "]");

                return getSerializableProxy(ret);
            }
        }

        if (targetBeanName != null) {
            if (log.isDebugEnabled())
                log.debug("Resolving serializable object to bean name [" + targetBeanName + "]");

            return getSerializableProxy();
        }

        if (log.isDebugEnabled())
            log.debug("Resolving serializable object for [" + descriptor.getDependencyName() + "]");

        Field field = descriptor.getField();

        // Check bean definition
        BeanDefinition rbd = beanFactory.getBeanDefinition(beanName);
        PropertyValues pvs = rbd.getPropertyValues();
        if (pvs.contains(field.getName())) {
            Object value = pvs.getPropertyValue(field.getName());
            if (value instanceof BeanReference) {
                // cache the bean name 
                this.targetBeanName = ((BeanReference) value).getBeanName();
                return getSerializableProxy();
            }
        }

        // Check Autowired
        try {
            Object bean = beanFactory.resolveDependency(descriptor, beanName);

            if (bean != null)
                return getSerializableProxy(bean);
        } catch (BeansException be) {
            // dependency not found.
        }

        // Check Resource annotation
        if (field.isAnnotationPresent(Resource.class)) {
            Resource r = field.getAnnotation(Resource.class);
            String name = StringUtils.isEmpty(r.name()) ? descriptor.getField().getName() : r.name();

            if (beanFactory.containsBean(name)) {
                this.targetBeanName = name;
                return getSerializableProxy();
            }
        }

        // Try with depend beans.      
        String[] dependentBeans = beanFactory.getDependenciesForBean(beanName);
        List<String> candidates = new ArrayList<String>();

        for (String name : dependentBeans) {
            if (beanFactory.isTypeMatch(name, descriptor.getDependencyType()))
                ;
            candidates.add(name);
        }

        if (candidates.size() == 1)
            return getSerializableProxy(beanFactory.getBean(candidates.get(0)));

        if (candidates.size() > 1) {
            for (PropertyValue pv : pvs.getPropertyValues()) {
                if (pv.getValue() instanceof BeanReference) {
                    BeanReference br = (BeanReference) pv.getValue();
                    if (candidates.contains(br.getBeanName()))
                        return getSerializableProxy(beanFactory.getBean(br.getBeanName()));
                }
            }
        }

        log.error("Cant not resolve serializable reference wiht candidates " + candidates.toArray());

        return null;
    }

    protected Object getSerializableProxy(Object targetObject) {
        if (targetBeanName != null)
            return getSerializableProxy();

        return SerializableProxyUtils.createSerializableProxy(targetObject, proxyTargetClass, useMemoryCache,
                beanFactory, descriptor, beanName);
    }

    protected Object getSerializableProxy() {
        return SerializableProxyUtils.createSerializableProxy(beanFactory.getBean(targetBeanName), proxyTargetClass,
                useMemoryCache, beanFactory, targetBeanName);
    }

    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }

    public void setTargetBeanName(String name) {
        this.targetBeanName = name;
    }

    public boolean isProxyTargetClass() {
        return proxyTargetClass;
    }

    public void setProxyTargetClass(boolean proxyTargetClass) {
        this.proxyTargetClass = proxyTargetClass;
    }

    public boolean isUseMemoryCache() {
        return useMemoryCache;
    }

    public void setUseMemoryCache(boolean useMemoryCache) {
        this.useMemoryCache = useMemoryCache;
    }

    public String getBeanName() {
        return beanName;
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public String getTargetBeanName() {
        return targetBeanName;
    }

    public ConfigurableListableBeanFactory getBeanFactory() {
        return beanFactory;
    }

    public void setBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

}