All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.weld.environment.se.ContainerLifecycleObserver Maven / Gradle / Ivy

There is a newer version: 6.0.2.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2016, 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.weld.environment.se;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

import javax.enterprise.event.Reception;
import javax.enterprise.event.TransactionPhase;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.AfterTypeDiscovery;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.BeforeShutdown;
import javax.enterprise.inject.spi.ObserverMethod;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.ProcessBean;
import javax.enterprise.inject.spi.ProcessBeanAttributes;
import javax.enterprise.inject.spi.ProcessInjectionPoint;
import javax.enterprise.inject.spi.ProcessInjectionTarget;
import javax.enterprise.inject.spi.ProcessManagedBean;
import javax.enterprise.inject.spi.ProcessObserverMethod;
import javax.enterprise.inject.spi.ProcessProducer;
import javax.enterprise.inject.spi.ProcessProducerField;
import javax.enterprise.inject.spi.ProcessProducerMethod;
import javax.enterprise.inject.spi.ProcessSessionBean;
import javax.enterprise.inject.spi.ProcessSyntheticAnnotatedType;
import javax.enterprise.inject.spi.WithAnnotations;
import javax.enterprise.util.TypeLiteral;

import org.jboss.weld.bootstrap.SyntheticExtension;
import org.jboss.weld.bootstrap.events.NotificationListener;
import org.jboss.weld.environment.se.logging.WeldSELogger;
import org.jboss.weld.event.ContainerLifecycleEventObserverMethod;
import org.jboss.weld.util.Observers;
import org.jboss.weld.util.Preconditions;
import org.jboss.weld.util.reflection.Reflections;

/**
 * A synthetic container lifecycle event observer.
 *
 * @author Martin Kouba
 * @see SyntheticExtension
 * @see Weld#addExtension(javax.enterprise.inject.spi.Extension)
 * @see Weld#addContainerLifecycleObserver(ContainerLifecycleObserver)
 */
public final class ContainerLifecycleObserver implements ContainerLifecycleEventObserverMethod {

    private final int priority;

    private final Type observedType;

    private final BiConsumer callbackWithBeanManager;

    private final Consumer callback;

    private final Collection> requiredAnnotations;

    private volatile BeanManager beanManager;

    private volatile SyntheticExtension extension;

    /**
     *
     * @param priority
     * @param observedType
     * @param callbackWithBeanManager
     * @param callback
     * @param requiredAnnotations
     */
    private ContainerLifecycleObserver(int priority, Type observedType, BiConsumer callbackWithBeanManager, Consumer callback,
            Collection> requiredAnnotations) {
        this.priority = priority;
        this.observedType = observedType;
        this.callbackWithBeanManager = callbackWithBeanManager;
        this.callback = callback;
        this.requiredAnnotations = requiredAnnotations;
    }

    @Override
    public int getPriority() {
        return priority;
    }

    @Override
    public Class getBeanClass() {
        return ContainerLifecycleObserver.class;
    }

    @Override
    public Type getObservedType() {
        return observedType;
    }

    @Override
    public Set getObservedQualifiers() {
        return Collections.emptySet();
    }

    @Override
    public Reception getReception() {
        return Reception.ALWAYS;
    }

    @Override
    public TransactionPhase getTransactionPhase() {
        return TransactionPhase.IN_PROGRESS;
    }

    @Override
    public void notify(T event) {
        if (beanManager == null || extension == null) {
            throw WeldSELogger.LOG.containerLifecycleObserverNotInitialized(toString());
        }
        if (event instanceof NotificationListener) {
            NotificationListener.class.cast(event).preNotify(extension);
        }
        try {
            if (callbackWithBeanManager != null) {
                callbackWithBeanManager.accept(event, beanManager);
            } else {
                callback.accept(event);
            }
        } finally {
            if (event instanceof NotificationListener) {
                NotificationListener.class.cast(event).postNotify(null);
            }
        }
    }

    @Override
    public Collection> getRequiredAnnotations() {
        return requiredAnnotations;
    }

    private void setBeanManager(BeanManager beanManager) {
        this.beanManager = beanManager;
    }

    private void setExtension(SyntheticExtension extension) {
        this.extension = extension;
    }

    @Override
    public String toString() {
        return String.format("ContainerLifecyleObserver [priority=%s, observedType=%s]", priority, observedType);
    }

    // Static methods used to init a new builder or a new observer instance

    /**
     *
     * @return a new builder instance
     * @see BeforeBeanDiscovery
     */
    public static Builder beforeBeanDiscovery() {
        return ContainerLifecycleObserver. of(BeforeBeanDiscovery.class);
    }

    /**
     *
     * @param callback
     * @return a new container lifecycle observer
     * @see BeforeBeanDiscovery
     */
    public static ContainerLifecycleObserver beforeBeanDiscovery(Consumer callback) {
        return beforeBeanDiscovery().notify(callback);
    }

    /**
     *
     * @return a new builder instance
     * @see AfterBeanDiscovery
     */
    public static Builder afterBeanDiscovery() {
        return ContainerLifecycleObserver. of(AfterBeanDiscovery.class);
    }

    /**
     *
     * @param callback
     * @return a new container lifecycle observer
     * @see AfterBeanDiscovery
     */
    public static ContainerLifecycleObserver afterBeanDiscovery(Consumer callback) {
        return afterBeanDiscovery().notify(callback);
    }

    /**
     *
     * @return a new builder instance
     * @see AfterTypeDiscovery
     */
    public static Builder afterTypeDiscovery() {
        return ContainerLifecycleObserver. of(AfterTypeDiscovery.class);
    }

    /**
     *
     * @param callback
     * @return a new container lifecycle observer
     * @see AfterTypeDiscovery
     */
    public static ContainerLifecycleObserver afterTypeDiscovery(Consumer callback) {
        return afterTypeDiscovery().notify(callback);
    }

    /**
     *
     * @param callback
     * @return a new builder instance
     * @see AfterDeploymentValidation
     */
    public static Builder afterDeploymentValidation() {
        return ContainerLifecycleObserver. of(AfterDeploymentValidation.class);
    }

    /**
     *
     * @param callback
     * @return a new container lifecycle observer
     * @see AfterDeploymentValidation
     */
    public static ContainerLifecycleObserver afterDeploymentValidation(Consumer callback) {
        return afterDeploymentValidation().notify(callback);
    }

    /**
     *
     * @param callback
     * @return a new builder instance
     * @see BeforeShutdown
     */
    public static Builder beforeShutdown() {
        return ContainerLifecycleObserver. of(BeforeShutdown.class);
    }

    /**
     *
     * @param callback
     * @return a new container lifecycle observer
     * @see BeforeShutdown
     */
    public static ContainerLifecycleObserver beforeShutdown(Consumer callback) {
        return beforeShutdown().notify(callback);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessAnnotatedType
     */
    @SuppressWarnings("serial")
    public static Builder> processAnnotatedType() {
        return processAnnotatedType(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessAnnotatedType
     */
    public static Builder> processAnnotatedType(Type observedType) {
        checkRawType(observedType, ProcessAnnotatedType.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessSyntheticAnnotatedType
     */
    public static Builder> processSyntheticAnnotatedType(Type observedType) {
        checkRawType(observedType, ProcessSyntheticAnnotatedType.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessInjectionPoint
     */
    @SuppressWarnings("serial")
    public static Builder> processInjectionPoint() {
        return processInjectionPoint(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessInjectionPoint
     */
    public static Builder> processInjectionPoint(Type observedType) {
        checkRawType(observedType, ProcessInjectionPoint.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessInjectionTarget
     *
     */
    @SuppressWarnings("serial")
    public static Builder> processInjectionTarget() {
        return processInjectionTarget(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessInjectionTarget
     */
    public static Builder> processInjectionTarget(Type observedType) {
        checkRawType(observedType, ProcessInjectionTarget.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessBeanAttributes
     */
    @SuppressWarnings("serial")
    public static Builder> processBeanAttributes() {
        return processBeanAttributes(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessBeanAttributes
     */
    public static Builder> processBeanAttributes(Type observedType) {
        checkRawType(observedType, ProcessBeanAttributes.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessBean
     */
    @SuppressWarnings("serial")
    public static Builder> processBean() {
        return processBean(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessBean
     */
    public static Builder> processBean(Type observedType) {
        checkRawType(observedType, ProcessBean.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessManagedBean
     */
    @SuppressWarnings("serial")
    public static Builder> processManagedBean() {
        return processManagedBean(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessManagedBean
     */
    public static Builder> processManagedBean(Type observedType) {
        checkRawType(observedType, ProcessManagedBean.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessSessionBean
     */
    @SuppressWarnings("serial")
    public static Builder> processSessionBean() {
        return processSessionBean(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessSessionBean
     */
    public static Builder> processSessionBean(Type observedType) {
        checkRawType(observedType, ProcessSessionBean.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessProducerMethod
     */
    @SuppressWarnings("serial")
    public static Builder> processProducerMethod() {
        return processProducerMethod(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessProducerMethod
     */
    public static Builder> processProducerMethod(Type observedType) {
        checkRawType(observedType, ProcessProducerMethod.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessProducerField
     */
    @SuppressWarnings("serial")
    public static Builder> processProducerField() {
        return processProducerField(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessProducerField
     */
    public static Builder> processProducerField(Type observedType) {
        checkRawType(observedType, ProcessProducerField.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessProducer
     */
    @SuppressWarnings("serial")
    public static Builder> processProducer() {
        return processProducer(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessProducer
     */
    public static Builder> processProducer(Type observedType) {
        checkRawType(observedType, ProcessProducer.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     *
     * @return a new builder instance
     * @see ProcessObserverMethod
     */
    @SuppressWarnings("serial")
    public static Builder> processObserverMethod() {
        return processObserverMethod(new TypeLiteral>() {
        }.getType());
    }

    /**
     *
     * @param observedType
     * @return a new builder instance
     * @see ProcessObserverMethod
     */
    public static Builder> processObserverMethod(Type observedType) {
        checkRawType(observedType, ProcessObserverMethod.class);
        return ContainerLifecycleObserver.> of(observedType);
    }

    /**
     * A synthetic extension is basically a container for synthetic container lifecycle event observers.
     *
     * @return a builder for a synthetic extension
     */
    public static ContainerLifecycleObserverExtension.Builder extensionBuilder() {
        return new ContainerLifecycleObserverExtension.Builder();
    }

    private static  Builder of(Type observedType) {
        if (!Observers.CONTAINER_LIFECYCLE_EVENT_TYPES.contains(Reflections.getRawType(observedType))) {
            throw WeldSELogger.LOG.observedTypeNotContonainerLifecycleEventType(observedType);
        }
        return new Builder<>(observedType);
    }

    private static void checkRawType(Type observedType, Class rawType) {
        if (!rawType.equals(Reflections.getRawType(observedType))) {
            throw WeldSELogger.LOG.observedTypeDoesNotMatchContonainerLifecycleEventType(observedType, rawType);
        }
    }

    public static class Builder {

        private static final String OBSERVED_TYPE = "observedType";
        private static final String CALLBACK = "callback";

        @SuppressWarnings("checkstyle:magicnumber")
        private static final int DEFAULT_PRIORITY = javax.interceptor.Interceptor.Priority.APPLICATION + 500;

        private int priority = DEFAULT_PRIORITY;

        private Type observedType;

        private Collection> requiredAnnotations = Collections.emptySet();

        private Builder(Type observedType) {
            Preconditions.checkArgumentNotNull(observedType, OBSERVED_TYPE);
            this.observedType = observedType;
        }

        /**
         * Set the priority.
         *
         * @param priority
         * @return self
         */
        public Builder priority(int priority) {
            this.priority = priority;
            return this;
        }

        /**
         * The annotations are only considered for {@link ProcessAnnotatedType}, i.e. they are ignored for other container lifecycle events.
         *
         * @param annotations
         * @return self
         * @see WithAnnotations
         */
        @SafeVarargs
        public final Builder withAnnotations(Class... annotations) {
            this.requiredAnnotations = new HashSet<>();
            Collections.addAll(requiredAnnotations, annotations);
            return this;
        }

        /**
         * Set a callback used during observer notification. The first callback parameter is an event object and the second parameter is a {@link BeanManager}
         * instance.
         * 

* This is a terminal operation. * * @param callback * @return the built observer * @see ObserverMethod#notify(Object) */ public ContainerLifecycleObserver notify(BiConsumer callback) { Preconditions.checkArgumentNotNull(callback, CALLBACK); return new ContainerLifecycleObserver<>(priority, observedType, callback, null, requiredAnnotations); } /** * Set a callback used during observer notification. The callback parameter is an event object. *

* This is a terminal operation. * * @param callback * @return the built observer * @see ObserverMethod#notify(Object) */ public ContainerLifecycleObserver notify(Consumer callback) { Preconditions.checkArgumentNotNull(callback, CALLBACK); return new ContainerLifecycleObserver<>(priority, observedType, null, callback, requiredAnnotations); } } /** * A synthetic extension, i.e. a collection of synthetic container lifecycle observers. * * @author Martin Kouba */ public static class ContainerLifecycleObserverExtension implements SyntheticExtension { private final List> observers; ContainerLifecycleObserverExtension(List> observers) { this.observers = new ArrayList<>(observers); } public void initialize(BeanManager beanManager) { for (ContainerLifecycleObserver observer : observers) { observer.setBeanManager(beanManager); observer.setExtension(this); } } @Override public Collection> getObservers() { return Reflections.cast(observers); } public static class Builder { private final List> observers; private Builder() { this.observers = new ArrayList<>(); } /** * * @param observer * @return self */ public ContainerLifecycleObserverExtension.Builder add(ContainerLifecycleObserver observer) { observers.add(observer); return this; } public ContainerLifecycleObserverExtension build() { return new ContainerLifecycleObserverExtension(observers); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy