org.jdal.aop.DelegateFactoryIntroductionInterceptor.java Source code

Java tutorial

Introduction

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

Source

/*
 * Copyright 2009-2014 Jose Luis Martin.
 *
 * 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.util.Map;
import java.util.WeakHashMap;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.IntroductionInterceptor;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.IntroductionInfoSupport;

/**
 * DelegatingIntroductionInterceptor that use a Factory to create delegates.
 * <p>
 * Note: this class include code from {@link org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor}
 * </p>
 * @author Jose Luis Martin
 * @since 2.0
 */
@SuppressWarnings({ "serial" })
public class DelegateFactoryIntroductionInterceptor extends IntroductionInfoSupport
        implements IntroductionInterceptor {

    private DelegateFactory delegateFactory;
    private Class<?> interfaceType;

    /** 
     * Hold weak references to keys as we don't want to interfere with garbage collection..
     */
    private final Map<Object, Object> delegateMap = new WeakHashMap<Object, Object>();

    public DelegateFactoryIntroductionInterceptor(DelegateFactory delegateFactory, Class<?> interfaceType) {
        this.delegateFactory = delegateFactory;
        this.interfaceType = interfaceType;
        this.publishedInterfaces.add(interfaceType);
    }

    public Object invoke(MethodInvocation mi) throws Throwable {
        if (isMethodOnIntroducedInterface(mi)) {
            Object delegate = getIntroductionDelegateFor(mi.getThis());
            Object retVal = AopUtils.invokeJoinpointUsingReflection(delegate, mi.getMethod(), mi.getArguments());

            if (retVal == delegate && mi instanceof ProxyMethodInvocation) {
                retVal = ((ProxyMethodInvocation) mi).getProxy();
            }
            return retVal;
        }

        return doProceed(mi);
    }

    protected Object doProceed(MethodInvocation mi) throws Throwable {
        return mi.proceed();
    }

    private Object getIntroductionDelegateFor(Object targetObject) {
        synchronized (this.delegateMap) {
            if (this.delegateMap.containsKey(targetObject)) {
                return this.delegateMap.get(targetObject);
            } else {
                Object delegate = createNewDelegate(targetObject);
                this.delegateMap.put(targetObject, delegate);
                return delegate;
            }
        }
    }

    protected Object createNewDelegate(Object targetObject) {
        try {
            return delegateFactory.createNewDelegate(targetObject);
        } catch (Exception e) {
            throw new IllegalStateException("Cant create delegate instance of type [" + this.interfaceType.getName()
                    + "] : " + e.getMessage());
        }
    }

    public interface DelegateFactory {

        Object createNewDelegate(Object target) throws Exception;
    }
}