View Javadoc
1   /*
2    * Copyright (C) 2012-2024 RRiBbit.org
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.rribbit.creation;
17  
18  import org.rribbit.Listener;
19  import org.rribbit.ListenerObject;
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  import java.lang.reflect.InvocationTargetException;
24  import java.util.Collection;
25  
26  /**
27   * This {@link ListenerObjectCreator} creates {@link ListenerObject}s from classes. Users can pass in {@link Class}es or packagenames and this class will scan the {@link Class}es
28   * and create {@link ListenerObject}s for the public methods that are annotated with {@link Listener}. Note that public methods inherited from superclasses and superinterfaces will also be
29   * scanned. This means that users must take care not to scan a method twice, once as a method of a class and once as a method of a superclass, by passing a class/interface and its
30   * superclass/superinterface separately to this {@link ListenerObjectCreator}.
31   * <p />
32   * Please note that in Java, method annotations are NOT inherited. This means that, if you override/implement a method in a subclass or subinterface, and the overriding/implementing method
33   * does not have the annotation, then that method will not inherit it. If a class or interface just inherits a method, without overriding it, then the annotation WILL exist.
34   * <p />
35   * To get the actual {@link Object}s that the listeners run on, this class simply attempts to instantiate an {@link Object} for each {@link Class} that it scans.
36   * When there is no default constructor for a {@link Class}, the {@link Class} will simply be ignored.
37   *
38   * @author G.J. Schouten
39   *
40   */
41  public class InstantiatingClassBasedListenerObjectCreator extends AbstractClassBasedListenerObjectCreator {
42  
43  	private static final Logger log = LoggerFactory.getLogger(InstantiatingClassBasedListenerObjectCreator.class);
44  
45  	/**
46  	 * @param classes
47  	 *
48  	 * @see AbstractClassBasedListenerObjectCreator#AbstractClassBasedListenerObjectCreator(Class...)
49  	 */
50  	public InstantiatingClassBasedListenerObjectCreator(Class<?>... classes) {
51  		super(classes);
52  	}
53  
54  	/**
55  	 * @param excludedClasses
56  	 * @param scanSubPackages
57  	 * @param packageNames
58  	 *
59  	 * @see AbstractClassBasedListenerObjectCreator#AbstractClassBasedListenerObjectCreator(Collection, boolean, String...)
60  	 */
61  	public InstantiatingClassBasedListenerObjectCreator(Collection<Class<?>> excludedClasses, boolean scanSubPackages, String... packageNames) {
62  		super(excludedClasses, scanSubPackages, packageNames);
63  	}
64  
65  	@Override
66  	protected Object getTargetObjectForClass(Class<?> clazz) {
67  
68  		try {
69  			log.debug("Attempting to construct instance of class '{}'", clazz.getName());
70  			return clazz.getConstructor().newInstance();
71  		} catch(InvocationTargetException e) {
72  			throw new RuntimeException("Exception thrown from constructor of Listener", e.getCause());
73  		} catch(Exception e) {
74  			log.debug("No suitable constructor found, returning null");
75  			return null;
76  		}
77  	}
78  }