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}