001/*
002 * Copyright 2002-2017 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 */
016
017package org.springframework.context.event;
018
019import org.springframework.aop.support.AopUtils;
020import org.springframework.context.ApplicationEvent;
021import org.springframework.context.ApplicationListener;
022import org.springframework.core.Ordered;
023import org.springframework.core.ResolvableType;
024import org.springframework.util.Assert;
025
026/**
027 * {@link GenericApplicationListener} adapter that determines supported event types
028 * through introspecting the generically declared type of the target listener.
029 *
030 * @author Juergen Hoeller
031 * @author Stephane Nicoll
032 * @since 3.0
033 * @see org.springframework.context.ApplicationListener#onApplicationEvent
034 */
035public class GenericApplicationListenerAdapter implements GenericApplicationListener, SmartApplicationListener {
036
037        private final ApplicationListener<ApplicationEvent> delegate;
038
039        private final ResolvableType declaredEventType;
040
041
042        /**
043         * Create a new GenericApplicationListener for the given delegate.
044         * @param delegate the delegate listener to be invoked
045         */
046        @SuppressWarnings("unchecked")
047        public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
048                Assert.notNull(delegate, "Delegate listener must not be null");
049                this.delegate = (ApplicationListener<ApplicationEvent>) delegate;
050                this.declaredEventType = resolveDeclaredEventType(this.delegate);
051        }
052
053
054        @Override
055        public void onApplicationEvent(ApplicationEvent event) {
056                this.delegate.onApplicationEvent(event);
057        }
058
059        @Override
060        @SuppressWarnings("unchecked")
061        public boolean supportsEventType(ResolvableType eventType) {
062                if (this.delegate instanceof SmartApplicationListener) {
063                        Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
064                        return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
065                }
066                else {
067                        return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
068                }
069        }
070
071        @Override
072        public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
073                return supportsEventType(ResolvableType.forClass(eventType));
074        }
075
076        @Override
077        public boolean supportsSourceType(Class<?> sourceType) {
078                return !(this.delegate instanceof SmartApplicationListener) ||
079                                ((SmartApplicationListener) this.delegate).supportsSourceType(sourceType);
080        }
081
082        @Override
083        public int getOrder() {
084                return (this.delegate instanceof Ordered ? ((Ordered) this.delegate).getOrder() : Ordered.LOWEST_PRECEDENCE);
085        }
086
087
088        static ResolvableType resolveDeclaredEventType(Class<?> listenerType) {
089                ResolvableType resolvableType = ResolvableType.forClass(listenerType).as(ApplicationListener.class);
090                return (resolvableType.hasGenerics() ? resolvableType.getGeneric() : null);
091        }
092
093        private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) {
094                ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass());
095                if (declaredEventType == null || declaredEventType.isAssignableFrom(
096                                ResolvableType.forClass(ApplicationEvent.class))) {
097                        Class<?> targetClass = AopUtils.getTargetClass(listener);
098                        if (targetClass != listener.getClass()) {
099                                declaredEventType = resolveDeclaredEventType(targetClass);
100                        }
101                }
102                return declaredEventType;
103        }
104
105}