/* * * Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under * one or more contributor license agreements (see COPYRIGHT for details). * The CA licenses this file to you under the GNU Affero General Public * License version 3, (the "License"); you may not use this file except in * compliance with the License. This file is part of kune. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package cc.kune.core.server; import static com.google.inject.name.Names.named; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.aopalliance.intercept.MethodInterceptor; import com.google.inject.AbstractModule; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.matcher.Matcher; // TODO: Auto-generated Javadoc /** * An extension of AbstractModule that provides support for member injection of * instances constructed at bind-time; in particular, itself and * MethodInterceptors. * * @author vjrj@ourproject.org (Vicente J. Ruiz Jurado) */ /* * See: * http://tembrel.blogspot.com/2007/09/injecting-method-interceptors-in-guice * .html */ public abstract class AbstractExtendedModule extends AbstractModule { /** The Constant COUNT. */ private static final AtomicInteger COUNT = new AtomicInteger(); /** * Hack to ensure unique Keys for binding different instances of * ExtendedModule. The prefix is chosen to reduce the chances of a conflict * with some other use of * * @return the unique annotation * @Named. A better solution would be to invent an Annotation for just this * purpose. */ private static Annotation getUniqueAnnotation() { return named("ExtendedModule-" + COUNT.incrementAndGet()); } /** The self injected. */ private boolean selfInjected = false; /** The to be injected. */ private final Set<Object> toBeInjected = new HashSet<Object>(); /** * Overridden version of bindInterceptor that, in addition to the standard * behavior, arranges for field and method injection of each MethodInterceptor * in {@code interceptors}. * * @param classMatcher * the class matcher * @param methodMatcher * the method matcher * @param interceptors * the interceptors */ @Override public void bindInterceptor(final Matcher<? super Class<?>> classMatcher, final Matcher<? super Method> methodMatcher, final MethodInterceptor... interceptors) { registerForInjection(interceptors); super.bindInterceptor(classMatcher, methodMatcher, interceptors); } /** * Ensure self injection. */ private void ensureSelfInjection() { if (!selfInjected) { bind(AbstractExtendedModule.class).annotatedWith(getUniqueAnnotation()).toInstance(this); selfInjected = true; } } /** * Inject registered objects. * * @param injector * the injector */ @SuppressWarnings("unused") @Inject private void injectRegisteredObjects(final Injector injector) { for (final Object injectee : toBeInjected) { injector.injectMembers(injectee); } } /** * Arranges for this module and each of the given objects (if any) to be field * and method injected when the Injector is created. It is safe to call this * method more than once, and it is safe to call it more than once on the same * object(s). * * @param <T> * the generic type * @param objects * the objects */ protected <T> void registerForInjection(final T... objects) { ensureSelfInjection(); if (objects != null) { for (final T object : objects) { if (object != null) { toBeInjected.add(object); } } } } }