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 }