/** * Copyright (C) 2013 Kametic <epo.jemba@kametic.com> * * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June 2007; * or any later version * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/lgpl-3.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * */ package org.nuunframework.kernel.plugin; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.net.URL; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.nuunframework.kernel.commons.specification.AbstractSpecification; import org.nuunframework.kernel.commons.specification.AndSpecification; import org.nuunframework.kernel.commons.specification.NotSpecification; import org.nuunframework.kernel.commons.specification.OrSpecification; import org.nuunframework.kernel.commons.specification.Specification; import org.nuunframework.kernel.commons.specification.reflect.ClassMethodsAnnotatedWith; import org.nuunframework.kernel.commons.specification.reflect.DescendantOfSpecification; import org.nuunframework.kernel.context.Context; import org.nuunframework.kernel.context.InitContext; import org.nuunframework.kernel.plugin.provider.DependencyInjectionProvider; import org.nuunframework.kernel.plugin.request.BindingRequest; import org.nuunframework.kernel.plugin.request.BindingRequestBuilder; import org.nuunframework.kernel.plugin.request.ClasspathScanRequest; import org.nuunframework.kernel.plugin.request.ClasspathScanRequestBuilder; import org.nuunframework.kernel.plugin.request.KernelParamsRequest; import org.nuunframework.kernel.plugin.request.KernelParamsRequestBuilder; import org.nuunframework.kernel.plugin.request.builders.BindingRequestBuilderMain; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Epo Jemba */ public abstract class AbstractPlugin implements Plugin { Logger logger = LoggerFactory.getLogger(AbstractPlugin.class); protected Context context = null; protected Object containerContext = null; protected RoundEnvironment roundEnvironment; @SuppressWarnings("unused") private Map<String, String> kernelParams; @SuppressWarnings("unused") private InitContext initContext; private final KernelParamsRequestBuilder paramsBuilder; private final ClasspathScanRequestBuilder scanBuilder; private final BindingRequestBuilder bindingBuilder; /** * */ public AbstractPlugin() { paramsBuilder = new KernelParamsRequestBuilder(); scanBuilder = new ClasspathScanRequestBuilder(); bindingBuilder = new BindingRequestBuilder(); } /** * ============================= PLUGIN LIFE CYCLE USED BY KERNEL ============================= * @return **/ @Override public InitState init(InitContext initContext) { this.initContext = initContext; return InitState.INITIALIZED; } @Override public void stop() { } @Override public void start(Context context) { this.context = context; } @Override public void destroy() { } // /** // * ============================= PLUGIN Utilities Helpers ============================= // * // * // **/ protected KernelParamsRequestBuilder kernelParamsRequestBuilder() { paramsBuilder.reset(); return paramsBuilder; } protected ClasspathScanRequestBuilder classpathScanRequestBuilder() { scanBuilder.reset(); return scanBuilder; } protected BindingRequestBuilderMain bindingRequestsBuilder() { bindingBuilder.reset(); return bindingBuilder; } protected Specification<Class<?>> or(Specification<Class<?>>... participants) { return new OrSpecification<Class<?>>(participants); } protected Specification<Class<?>> and(Specification<Class<?>>... participants) { return new AndSpecification<Class<?>>(participants); } protected Specification<Class<?>> not(Specification<Class<?>> participant) { return new NotSpecification<Class<?>>(participant); } protected Specification<Class<?>> descendantOf(Class<?> ancestor) { return new DescendantOfSpecification(ancestor); } protected Specification<Class<?>> classMethodsAnnotatedWith (final Class<? extends Annotation> annotationClass) { return new ClassMethodsAnnotatedWith(annotationClass); } protected Specification<Class<?>> fieldAnnotatedWith (final Class<? extends Annotation> annotationClass) { return new AbstractSpecification<Class<?>> () { @Override public boolean isSatisfiedBy(Class<?> candidate) { if (candidate != null) { try { for (Field field : candidate.getDeclaredFields()) { if ( field.isAnnotationPresent(annotationClass) ) { return true; } } } catch (Throwable throwable) { logger.debug("fieldAnnotatedWith : " +candidate + " missing " + throwable ); } } return false; } }; } protected Specification<Class<?>> classAnnotatedWith(final Class<? extends Annotation> klass) { return new AbstractSpecification<Class<?>>() { @Override public boolean isSatisfiedBy(Class<?> candidate) { return candidate != null && candidate.getAnnotation(klass) != null; } }; } // TODO replace this implementation by the one in ClassMethodsAnnotatedWithSpecification protected Specification<Class<?>> classImplements(final Class<?> klass) { return new AbstractSpecification<Class<?>>() { @Override public boolean isSatisfiedBy(Class<?> candidate) { if (candidate != null && klass.isInterface()) { for (Class<?> i : candidate.getInterfaces()) { if (i.equals(klass)) { return true; } } } return false; } }; } // * ============================= PLUGIN info and requests * ============================= // @Override public abstract String name(); @Override public String description() { return name() + " Nuun Based Plugin."; } @Override public Collection<KernelParamsRequest> kernelParamsRequests() { return Collections.emptySet(); } public Collection<ClasspathScanRequest> classpathScanRequests() { return Collections.emptySet(); } @Override public Collection<BindingRequest> bindingRequests() { return Collections.emptySet(); } @Override public Collection<Class<? extends Plugin>> requiredPlugins() { return Collections.emptySet(); } @Override public Collection<Class<? extends Plugin>> dependentPlugins() { return Collections.emptySet(); } @Override public String pluginPropertiesPrefix() { return ""; } @Override public String pluginPackageRoot() { return ""; } @Override public Object dependencyInjectionDef() { return null; } @Override public Object dependencyInjectionOverridingDef() { return null; } @Override public void provideContainerContext(Object containerContext){ this.containerContext = containerContext; } @Override public Set<URL> computeAdditionalClasspathScan() { return Collections.emptySet(); } @Override public DependencyInjectionProvider dependencyInjectionProvider() { return null; } @Override public void provideRoundEnvironment(RoundEnvironment roundEnvironment) { this.roundEnvironment = roundEnvironment; } @Override public Map<String, String> kernelParametersAliases() { return new HashMap<String, String>(); } protected <T> Collection collectionOf(T... items) { return Arrays.asList(items); } }