001/*
002 * Copyright 2002-2013 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.springframework.batch.core.listener;
017
018import java.util.Map;
019import java.util.Set;
020
021import org.aopalliance.intercept.MethodInterceptor;
022import org.aopalliance.intercept.MethodInvocation;
023import org.springframework.batch.core.ExitStatus;
024import org.springframework.batch.core.StepExecutionListener;
025import org.springframework.batch.support.MethodInvoker;
026
027/**
028 * {@link MethodInterceptor} that, given a map of method names and
029 * {@link MethodInvoker}s, will execute all methods tied to a particular method
030 * name, with the provided arguments. The only possible return value that is
031 * handled is of type ExitStatus, since the only StepListener implementation
032 * that isn't void is
033 * {@link StepExecutionListener#afterStep(org.springframework.batch.core.StepExecution)}
034 * , which returns ExitStatus.
035 *
036 * @author Lucas Ward
037 * @since 2.0
038 * @see MethodInvoker
039 */
040public class MethodInvokerMethodInterceptor implements MethodInterceptor {
041
042        private final Map<String, Set<MethodInvoker>> invokerMap;
043        private final boolean ordered;
044
045        public MethodInvokerMethodInterceptor(Map<String, Set<MethodInvoker>> invokerMap) {
046                this(invokerMap, false);
047        }
048
049        public MethodInvokerMethodInterceptor(Map<String, Set<MethodInvoker>> invokerMap, boolean ordered) {
050                this.ordered = ordered;
051                this.invokerMap = invokerMap;
052        }
053
054        @Override
055        public Object invoke(MethodInvocation invocation) throws Throwable {
056
057                String methodName = invocation.getMethod().getName();
058                if (ordered && methodName.equals("getOrder")) {
059                        return invocation.proceed();
060                }
061
062                Set<MethodInvoker> invokers = invokerMap.get(methodName);
063
064                if (invokers == null) {
065                        return null;
066                }
067                ExitStatus status = null;
068                for (MethodInvoker invoker : invokers) {
069                        Object retVal = invoker.invokeMethod(invocation.getArguments());
070                        if (retVal instanceof ExitStatus) {
071                                if (status != null) {
072                                        status = status.and((ExitStatus) retVal);
073                                }
074                                else {
075                                        status = (ExitStatus) retVal;
076                                }
077                        }
078                }
079
080                // The only possible return values are ExitStatus or int (from Ordered)
081                return status;
082        }
083
084        /**
085         * {@inheritDoc}
086         */
087        @Override
088        public boolean equals(Object obj) {
089                if (!(obj instanceof MethodInvokerMethodInterceptor)) {
090                        return false;
091                }
092                MethodInvokerMethodInterceptor other = (MethodInvokerMethodInterceptor) obj;
093                return invokerMap.equals(other.invokerMap);
094        }
095
096        /**
097         * {@inheritDoc}
098         */
099        @Override
100        public int hashCode() {
101                return invokerMap.hashCode();
102        }
103
104}