ch.nydi.aop.interceptor.Interceptors.java Source code

Java tutorial

Introduction

Here is the source code for ch.nydi.aop.interceptor.Interceptors.java

Source

/*
 * Copyright 2011 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 ch.nydi.aop.interceptor;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.ArrayUtils;

/**
 * An interceptor that chains other interceptors.
 * 
 * @author Daniel Nydegger
 */
public final class Interceptors implements MethodInterceptor {

    public static final MethodInterceptor EMPTY = new MethodInterceptor() {

        @Override
        public Object invoke(final MethodInvocation invocation) throws Throwable {
            return invocation.proceed();
        }
    };

    private final MethodInterceptor[] interceptors;

    /**
     * Creates an interceptor that chains other interceptors.
     * 
     * @param interceptors
     *            instances of {@link MethodInterceptor}.
     * @return interceptor that enclose other interceptors or Interceptors.EMPTY instance if interceptors argument is
     *         null or empty
     */
    public static MethodInterceptor create(final MethodInterceptor... interceptors) {

        if (ArrayUtils.isEmpty(interceptors)) {
            return Interceptors.EMPTY;
        }

        final List<MethodInterceptor> flatlist = new ArrayList<>();
        for (final MethodInterceptor interceptor : interceptors) {
            assert (interceptor != null);

            if (interceptor instanceof Interceptors) {
                flatlist.addAll(Arrays.asList(((Interceptors) interceptor).interceptors));
            } else if (EMPTY != interceptor) {
                flatlist.add(interceptor);
            }
        }
        if (flatlist.isEmpty()) {
            return EMPTY;
        } else if (flatlist.size() == 1) {
            return flatlist.get(0);
        }
        return new Interceptors(flatlist.toArray(new MethodInterceptor[flatlist.size()]));
    }

    private Interceptors(final MethodInterceptor[] interceptors) {
        this.interceptors = interceptors;
    }

    @Override
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        MethodInvocation nextInvocation = invocation;

        // chain the method invocation of interceptors in reverse order
        for (int i = interceptors.length - 1; i >= 0; i--) {
            final MethodInterceptor interceptor = interceptors[i];
            final MethodInvocation previousInvocation = nextInvocation;
            nextInvocation = new MethodInvocation() {

                @Override
                public Object proceed() throws Throwable {
                    return interceptor.invoke(previousInvocation);
                }

                @Override
                public Object getThis() {
                    return invocation.getThis();
                }

                @Override
                public AccessibleObject getStaticPart() {
                    return invocation.getStaticPart();
                }

                @Override
                public Object[] getArguments() {
                    return invocation.getArguments();
                }

                @Override
                public Method getMethod() {
                    return invocation.getMethod();
                }
            };
        }
        return nextInvocation.proceed();
    }
}