/************************************************
 * Copyright (c) Shen Li. All rights reserved.  *
 * http://joyaop.sourceforge.net                *
 * -------------------------------------------- *
 * Distributable under LGPL license.            *
 * See terms of license at gnu.org.             *
 ************************************************/
package net.sf.joyaop.impl;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.io.NotSerializableException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Set;

/**
 * @author Shen Li
 */
class WriteReplaceCallbackFactory extends CallbackFactory {
    private final WriteReplaceCallback callback;

    public WriteReplaceCallbackFactory(Set interfacesClass, CallbackFilter callbackFilter) {
        callback = new WriteReplaceCallback((Class[]) interfacesClass.toArray(new Class[interfacesClass.size()]), callbackFilter);
    }

    public WriteReplaceCallbackFactory(Class[] interfaceClasses, CallbackFilter callbackFilter) {
        callback = new WriteReplaceCallback(interfaceClasses, callbackFilter);
    }

    public Callback getCallback(RuntimeAspectInstanceFactory factory) {
        return callback;
    }

    public Callback getCallback() {
        return callback;
    }

    private static class WriteReplaceCallback implements MethodInterceptor, Serializable {
        private final Class[] interfacesClass;
        private final CallbackFilter callbackFilter;

        public WriteReplaceCallback(Class[] interfacesClass, CallbackFilter callbackFilter) {
            this.interfacesClass = interfacesClass;
            this.callbackFilter = callbackFilter;
        }

        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            if (Serializable.class.isAssignableFrom(proxy.getClass().getSuperclass())) {
                return new SerializableProxy(proxy, interfacesClass, callbackFilter);
            }
            throw new NotSerializableException(proxy.getClass().getSuperclass().getName() + " is not serializable.");
        }
    }
}
