/* * JBoss, Home of Professional Open Source * Copyright 2014, Red Hat, Inc., and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * 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.jboss.javaee.mongodb; import com.mongodb.MongoClient; import com.mongodb.MongoClientURI; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.net.UnknownHostException; import java.util.Collections; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.AfterBeanDiscovery; import javax.enterprise.inject.spi.AfterTypeDiscovery; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanAttributes; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.InjectionTarget; import javax.enterprise.inject.spi.InjectionTargetFactory; import javax.enterprise.inject.spi.ProcessAnnotatedType; import javax.enterprise.inject.spi.WithAnnotations; /** * This CDI Extension registers a <code>Mongoclient</code> * defined by adding a {@link MongoClientDefinition} annotation to any class of the application * Registration will be aborted if user defines her own <code>MongoClient</code> bean or producer * * @author Anttoine Sabot-Durand */ public class MongoExtension implements Extension { private static final Logger log = Logger.getLogger(MongoExtension.class.getName()); private MongoClientDefinition mongoDef = null; private boolean moreThanOne = false; /** * Looks for {@link MongoClientDefinition} annotation to capture it. * Also Checks if the application contains more than one of these definition */ void detectMongoClientDefinition( @Observes @WithAnnotations(MongoClientDefinition.class) ProcessAnnotatedType<?> pat) { AnnotatedType at = pat.getAnnotatedType(); MongoClientDefinition md = at.getAnnotation(MongoClientDefinition.class); String name = md.name(); if (mongoDef != null) { moreThanOne = true; } else { mongoDef = md; } } /** * Warns user if there's none onr more than one {@link MongoClientDefinition} in the application */ void checkMongoClientUniqueness(@Observes AfterTypeDiscovery atd) { if (mongoDef == null) { log.warning("No MongoDB data sources found, mongo CDI extension will do nothing"); } else if (moreThanOne) { log.log(Level.WARNING, "You defined more than one MongoDB data source. Only the one with name {0} will be " + "created", mongoDef .name()); } } /** * If the application has a {@link MongoClientDefinition} register the bean for it unless user has defined a bean or a * producer for a <code>MongoClient</code> */ void registerDataSourceBeans(@Observes AfterBeanDiscovery abd, BeanManager bm) { if (mongoDef != null) { if (bm.getBeans(MongoClient.class, DefaultLiteral.INSTANCE).isEmpty()) { log.log(Level.INFO, "Registering bean for MongoDB datasource {0}", mongoDef.name()); MongoClientURI uri = new MongoClientURI(mongoDef.url()); abd.addBean(bm.createBean(new MongoClientBeanAttributes(bm.createBeanAttributes(bm.createAnnotatedType (MongoClient.class))), MongoClient.class, new MongoClientProducerFactory(uri))); } else { log.log(Level.INFO, "Application contains a default MongoClient Bean, automatic registration will be disabled"); } } } private static class MongoClientBeanAttributes implements BeanAttributes<MongoClient> { private BeanAttributes<MongoClient> delegate; MongoClientBeanAttributes(BeanAttributes<MongoClient> beanAttributes) { delegate = beanAttributes; } @Override public String getName() { return delegate.getName(); } @Override public Set<Annotation> getQualifiers() { return delegate.getQualifiers(); } @Override public Class<? extends Annotation> getScope() { return ApplicationScoped.class; } @Override public Set<Class<? extends Annotation>> getStereotypes() { return delegate.getStereotypes(); } @Override public Set<Type> getTypes() { return delegate.getTypes(); } @Override public boolean isAlternative() { return delegate.isAlternative(); } } private static class MongoClientProducerFactory implements InjectionTargetFactory<MongoClient> { MongoClientURI uri; MongoClientProducerFactory(MongoClientURI uri) { this.uri = uri; } @Override public InjectionTarget<MongoClient> createInjectionTarget(Bean<MongoClient> bean) { return new InjectionTarget<MongoClient>() { @Override public void inject(MongoClient instance, CreationalContext<MongoClient> ctx) { } @Override public void postConstruct(MongoClient instance) { } @Override public void preDestroy(MongoClient instance) { } @Override public MongoClient produce(CreationalContext<MongoClient> ctx) { try { return new MongoClient(uri); } catch (UnknownHostException e) { throw new IllegalArgumentException(e); } } @Override public void dispose(MongoClient instance) { instance.close(); } @Override public Set<InjectionPoint> getInjectionPoints() { return Collections.EMPTY_SET; } }; } } }