/*
 * Bean Testing.
 *
 * 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 info.novatec.beantest.producers;

import info.novatec.beantest.api.CdiContainerShutdown;

import java.lang.reflect.Member;
import java.lang.reflect.Method;

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Entity manager producer.
 * <p>
 * It initializes the entity manager to be injected in EJBs
 *
 * @author Carlos Barragan (carlos.barragan@novatec-gmbh.de)
 */
@RequestScoped
public class EntityManagerProducer {

    private static final Logger LOGGER = LoggerFactory.getLogger(EntityManagerProducer.class);
    
    private static final String DEFAULT_BEAN_TEST_PERSISTENCE_UNIT = "beanTestPU";
     
    private EntityManagerFactory emf;
    
    private EntityManager em;

    @PostConstruct
    private void initializeEntityManagerFactory() {
        emf = Persistence.createEntityManagerFactory(DEFAULT_BEAN_TEST_PERSISTENCE_UNIT);
        LOGGER.info("Entity Manager Factory was successfully initialized");

    }
   

    @Produces
    public EntityManager getEntityManager(InjectionPoint ip) {
        PersistenceContext ctx = ip.getAnnotated().getAnnotation(PersistenceContext.class);
        
        if (ctx == null) {
        	//if @PersisteceContext is declared on method, ctx is null at this point.
        	//ctx should be retrieved from the Method.
        	Member member = ip.getMember();
        	if (member instanceof Method) {
        		Method method = (Method) member;
        		ctx = method.getAnnotation(PersistenceContext.class);
        	}
        }
        
        
        LOGGER.debug("PersistenceContext info:");
        LOGGER.debug("Unit name: {}", ctx.unitName());
        LOGGER.debug("Bean defining the injection point: {}", ip.getBean().getBeanClass());
        LOGGER.debug("Field to be injected: {}", ip.getMember());

        if (em == null) {
            em = emf.createEntityManager();
        }
        return em;
    }
    
    /**
     * Closes the entity manager and entity manager factory when the event {@link CdiContainerShutdown} is fired.
     * 
     * @param containerShutdown
     *            the event that indicates that the container is about to shutdown.
     */
    public void closeEntityManagerAndEntityManagerFactory(@Observes CdiContainerShutdown containerShutdown) {
        closeEntityManager();
        closeEntityManagerFactory();
    }

    private void closeEntityManager() {
        if (em == null) {
            return;
        }
        if (em.isOpen()) {
            try {
                // In case a transaction is still open.
                if (em.getTransaction().isActive() && !em.getTransaction().getRollbackOnly()) {
                    em.getTransaction().commit();
                }
            } finally {
                LOGGER.debug("Closing entity manager");
                em.close();
            }

        }
    }

    private void closeEntityManagerFactory() {
        if (emf == null) {
            return;
        }
        if (emf.isOpen()) {
            LOGGER.debug("Closing entity manager factory");
            emf.close();
        }
    }

}

@@ -673,17 +673,16 @@
 utdown;%0A
-%0A
 import j
@@ -739,17 +739,16 @@
 Method;%0A
-%0A
 import j
@@ -1127,17 +1127,16 @@
 ontext;%0A
-%0A
 import o
@@ -2476,25 +2476,16 @@
        %0A
-        %0A
         
@@ -2522,24 +2522,170 @@
 xt info:%22);%0A
+        //This could happen if the application injects the EntityManager via @Inject instead of @PersistenceContext%0A        if(ctx != null) %7B%0A    
         LOGG
@@ -2723,24 +2723,43 @@
 nitName());%0A
+        %7D%0A        %0A
         LOGG

Fix a NPE if the EntityManager when @PersistenceContext is not used to inject the EntityManager