com.github.blazeds.replicator.HibernateAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.github.blazeds.replicator.HibernateAdapter.java

Source

/*
 * Copyright 2002-2005 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 com.github.blazeds.replicator;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.beanlib.hibernate3.Hibernate3BeanReplicator;

import org.springframework.aop.support.AopUtils;

import flex.messaging.FactoryInstance;
import flex.messaging.messages.Message;
import flex.messaging.messages.RemotingMessage;
import flex.messaging.services.remoting.RemotingDestination;
import flex.messaging.services.remoting.adapters.JavaAdapter;

/**
 * @author Max Pimm
 * 
 *         Custom adapter that avoids serializing whole object graphs using
 *         beanlib and custom annotations.
 * 
 *         A method that returns a result serialized by Blaze DS may use the
 *         {@link ReplicateResult} annotation.
 * 
 *         This annotation defines:
 * 
 *         1) Whether uninitialized lazy collections should be fetched o
 *         excluded from the result
 * 
 *         2) A list of other properties to exclude from the result using the
 *         {@link ReplicateProperty} annotation.
 * 
 *         Internally this class uses beanlib to replicate the result replacing
 *         excluded properties and collections with null.
 * 
 *         See anotations {@link ReplicateResult} and {@link ReplicateProperty}
 */
public class HibernateAdapter extends JavaAdapter {

    private Hibernate3BeanReplicator replicator;

    private Map<Method, ReplicationPropertyFilter> filterCache;

    private boolean aopPresent;

    public HibernateAdapter() {
        super();
        checkAOPPresent();
    }

    public HibernateAdapter(boolean enableManagement) {
        super(enableManagement);
        checkAOPPresent();
    }

    @Override
    public Object invoke(Message message) {

        // Init filter cache on first visit
        if (filterCache == null) {
            filterCache = new HashMap<Method, ReplicationPropertyFilter>();
        }

        // Invoke incoming service call via blazeds
        Object result = super.invoke(message);
        if (result == null) {
            return null;
        }

        // Get method and check for filter in cache
        Method method = getMethod(message);
        ReplicationPropertyFilter filter;
        if (filterCache.containsKey(method)) {

            filter = filterCache.get(method);
            if (filter == null) {
                // If no filter defined for this method do nothing
                return result;
            } else {
                replicator = new Hibernate3BeanReplicator(null, null, filter);
            }
        } else {

            // Get the annotation
            if (!method.isAnnotationPresent(ReplicateResult.class)) {
                // Add null value to cache to denote that the result from this
                // method does not need replication
                filterCache.put(method, null);
                return result;
            } else {
                // Initialize a new filter for this method using the replication
                // configuration
                ReplicateResult replicationConfig = method.getAnnotation(ReplicateResult.class);
                filter = new ReplicationPropertyFilter(replicationConfig);
                filterCache.put(method, filter);
                replicator = new Hibernate3BeanReplicator(null, null, filter);
            }
        }

        // Nullify lazy collections if fetch eager set to false
        if (!filter.isFetchEager()) {
            NullifyLazyTransformer.Factory factory = new NullifyLazyTransformer.Factory();
            replicator.initCustomTransformerFactory(factory);
        }

        // Bean lib only handles beans not collections
        if (result instanceof Collection<?>) {
            CollectionWrapper wrapper = new CollectionWrapper();
            wrapper.setCollection((Collection<?>) result);
            result = replicator.copy(wrapper).getCollection();
        } else {
            result = replicator.copy(result);
        }

        return result;
    }

    /**
     * @param message
     * @return
     */
    private Method getMethod(Message message) {

        // Have to create instance to get class
        RemotingDestination remotingDestination = (RemotingDestination) getDestination();
        FactoryInstance factoryInstance = remotingDestination.getFactoryInstance();
        Object instance = createInstance(factoryInstance.getInstanceClass());

        // Class may be wrapped in proxy
        Class<?> targetClass;
        if (aopPresent && AopUtils.isAopProxy(instance) || AopUtils.isCglibProxy(instance)) {
            targetClass = AopUtils.getTargetClass(instance);
        } else {
            targetClass = instance.getClass();
        }

        // Get method to be invoked
        String operation = ((RemotingMessage) message).getOperation();
        @SuppressWarnings("rawtypes")
        List parameters = ((RemotingMessage) message).getParameters();
        Method method = remotingDestination.getMethodMatcher().getMethod(targetClass, operation, parameters);

        return method;
    }

    private void checkAOPPresent() {
        try {
            Class.forName("org.springframework.aop.framework.AopProxyUtils", false, null);
            aopPresent = true;
        } catch (ClassNotFoundException e) {
            aopPresent = false;
        }
    }
}