001 /** 002 Licensed to the Apache Software Foundation (ASF) under one or more 003 contributor license agreements. See the NOTICE file distributed with 004 this work for additional information regarding copyright ownership. 005 The ASF licenses this file to You under the Apache License, Version 2.0 006 (the "License"); you may not use this file except in compliance with 007 the License. You may obtain a copy of the License at 008 009 http://www.apache.org/licenses/LICENSE-2.0 010 011 Unless required by applicable law or agreed to in writing, software 012 distributed under the License is distributed on an "AS IS" BASIS, 013 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 See the License for the specific language governing permissions and 015 limitations under the License. 016 */ 017 package org.apache.commons.inject.api; 018 019 import java.lang.annotation.Annotation; 020 import java.lang.reflect.Field; 021 import java.util.ArrayList; 022 import java.util.List; 023 024 import org.apache.commons.inject.api.bind.IBinder; 025 import org.apache.commons.inject.api.bind.IModule; 026 import org.apache.commons.inject.api.bind.IBinder.IInjectionParticipator; 027 import org.apache.commons.inject.util.Exceptions; 028 029 /** 030 * Abstract implementation of a module, which injects loggers into fields. 031 * The field must be annotated like this: 032 * <pre> 033 * @InjLogger private Logger log; 034 * </pre> 035 * or 036 * <pre> 037 * @InjLogger(id="LoggerId") private Logger log; 038 * </pre> 039 * The second example would create a logger with the id "LoggerId". The first 040 * example would use the class name as a default value. (The class being that 041 * class, which declares the field. 042 */ 043 public abstract class AbstractLoggerInjectingModule<Log> implements IModule { 044 045 @Override 046 public void configure(IBinder pBinder) { 047 pBinder.add(new IInjectionParticipator() { 048 @Override 049 public List<IPoint<Object>> getPoints(IKey<?> pKey, Class<?> pType) { 050 final List<IPoint<Object>> points = new ArrayList<IPoint<Object>>(); 051 final Field[] fields = pType.getDeclaredFields(); 052 final Class<? extends Annotation> annotationClass = getAnnotationClass(); 053 for (final Field f : fields) { 054 if (f.isAnnotationPresent(annotationClass)) { 055 final Annotation annotation = f.getAnnotation(annotationClass); 056 String id = getId(annotation, f.getDeclaringClass()); 057 if (id == null || id.length() == 0) { 058 id = f.getDeclaringClass().getName(); 059 } 060 final Log logger = newLogger(id); 061 points.add(new IPoint<Object>(){ 062 @Override 063 public void injectTo(Object pInstance, 064 IInjector pInjector) { 065 try { 066 if (!f.isAccessible()) { 067 f.setAccessible(true); 068 } 069 f.set(pInstance, logger); 070 } catch (Throwable t) { 071 throw Exceptions.show(t); 072 } 073 } 074 }); 075 } 076 } 077 return points; 078 } 079 }); 080 } 081 082 /** 083 * Creates a new logger with the given Id. Subclasses <em>must</em> 084 * overwrite this to return a suitable logger implementation. 085 */ 086 protected abstract Log newLogger(String pId); 087 088 /** 089 * Returns the annotation class, which denotes suitable target fields. 090 * By default, the class {@link InjLogger} is used. 091 */ 092 protected Class<? extends Annotation> getAnnotationClass() { 093 return InjLogger.class; 094 } 095 096 /** 097 * Called to calculate the Id, which is used to invoke {@link #newLogger(String)}. 098 * By default, {@link InjLogger#name()} is returned. 099 */ 100 protected String getId(Annotation pAnnotation, Class<?> pClass) { 101 final InjLogger injLogger = (InjLogger) pAnnotation; 102 final String id = injLogger.id(); 103 if (id == null || id.length() == 0) { 104 return pClass.getName(); 105 } else { 106 return id; 107 } 108 } 109 }