org.jboss.weld.event.ExtensionObserverMethodImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weld-servlet-shaded Show documentation
Show all versions of weld-servlet-shaded Show documentation
This jar bundles all the bits of Weld and CDI required for running in a Servlet container.
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, 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.event;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ObserverMethod;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.ProcessSyntheticAnnotatedType;
import javax.enterprise.inject.spi.WithAnnotations;
import org.jboss.weld.Container;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMethod;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedParameter;
import org.jboss.weld.bean.RIBean;
import org.jboss.weld.bean.builtin.ExtensionBean;
import org.jboss.weld.bootstrap.events.NotificationListener;
import org.jboss.weld.injection.InjectionPointFactory;
import org.jboss.weld.injection.MethodInjectionPoint;
import org.jboss.weld.injection.MethodInjectionPoint.MethodInjectionPointType;
import org.jboss.weld.logging.EventLogger;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.util.collections.ImmutableSet;
import org.jboss.weld.util.reflection.Formats;
import org.jboss.weld.util.reflection.Reflections;
/**
* An implementation of {@link ObserverMethod} used for events delivered to extensions.
* The observer method does not require contexts to be active.
*
* @author Jozef Hartinger
*
*/
public class ExtensionObserverMethodImpl extends ObserverMethodImpl implements ContainerLifecycleEventObserverMethod {
private final Container containerLifecycleEventDeliveryLock;
private final Set> requiredTypeAnnotations;
private volatile Set> requiredScopeTypeAnnotations;
protected ExtensionObserverMethodImpl(EnhancedAnnotatedMethod observer, RIBean declaringBean, BeanManagerImpl manager, boolean isAsync) {
super(observer, declaringBean, manager, isAsync);
this.containerLifecycleEventDeliveryLock = Container.instance(manager);
this.requiredTypeAnnotations = initRequiredTypeAnnotations(observer);
}
protected Set> initRequiredTypeAnnotations(EnhancedAnnotatedMethod observer) {
EnhancedAnnotatedParameter, ? super X> eventParameter = getEventParameter(observer);
WithAnnotations annotation = eventParameter.getAnnotation(WithAnnotations.class);
if (annotation != null) {
return ImmutableSet.>of(annotation.value());
}
return Collections.emptySet();
}
@Override
protected void checkRequiredTypeAnnotations(EnhancedAnnotatedParameter, ?> eventParameter) {
Class> rawObserverType = Reflections.getRawType(getObservedType());
boolean isProcessAnnotatedType = rawObserverType.equals(ProcessAnnotatedType.class) || rawObserverType.equals(ProcessSyntheticAnnotatedType.class);
if (!isProcessAnnotatedType && !requiredTypeAnnotations.isEmpty()) {
throw EventLogger.LOG
.invalidWithAnnotations(this, Formats.formatAsStackTraceElement(eventParameter.getDeclaringEnhancedCallable().getJavaMember()));
}
if (isProcessAnnotatedType && requiredTypeAnnotations.isEmpty()) {
Type[] typeArguments = eventParameter.getActualTypeArguments();
if (typeArguments.length == 0 || Reflections.isUnboundedWildcard(typeArguments[0]) || Reflections.isUnboundedTypeVariable(typeArguments[0])) {
EventLogger.LOG.unrestrictedProcessAnnotatedTypes(this);
}
}
}
@Override
protected MethodInjectionPoint initMethodInjectionPoint(EnhancedAnnotatedMethod observer, RIBean declaringBean, BeanManagerImpl manager) {
// use silent creation of injection points for ProcessInjectionPoint events not to be fired for extension observer methods
return InjectionPointFactory.silentInstance().createMethodInjectionPoint(MethodInjectionPointType.OBSERVER, observer, declaringBean, declaringBean.getBeanClass(), SPECIAL_PARAM_MARKERS, manager);
}
@Override
protected void preNotify(T event, Object receiver) {
if (event instanceof NotificationListener) {
NotificationListener.class.cast(event).preNotify((Extension) receiver);
}
}
@Override
protected void postNotify(T event, Object receiver) {
if (event instanceof NotificationListener) {
NotificationListener.class.cast(event).postNotify((Extension) receiver);
}
}
/*
* Contexts may not be active during notification of container lifecycle events. Therefore, we invoke the methods directly on
* an extension instance.
*/
@Override
protected Object getReceiver(CreationalContext ctx) {
return getDeclaringBean().create(null);
}
@Override
protected void sendEvent(T event, Object receiver, CreationalContext> creationalContext) {
synchronized (containerLifecycleEventDeliveryLock) {
super.sendEvent(event, receiver, creationalContext);
}
}
protected String createTypeId(RIBean> declaringBean) {
if (declaringBean instanceof ExtensionBean) {
ExtensionBean> extensionBean = (ExtensionBean>) declaringBean;
return extensionBean.getAnnotatedType().getIdentifier().asString();
}
return super.createTypeId(declaringBean);
}
public Collection> getRequiredAnnotations() {
return requiredTypeAnnotations;
}
public Collection> getRequiredScopeAnnotations() {
if (requiredScopeTypeAnnotations == null) {
// this init may be performed more than once - which is OK
ImmutableSet.Builder> builder = ImmutableSet.builder();
for (Class extends Annotation> annotation : requiredTypeAnnotations) {
if (beanManager.isScope(annotation)) {
builder.add(annotation);
}
}
this.requiredScopeTypeAnnotations = builder.build();
}
return requiredScopeTypeAnnotations;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
ExtensionObserverMethodImpl, ?> that = (ExtensionObserverMethodImpl, ?>) obj;
return super.equals(that);
}
@Override
public int hashCode() {
return super.hashCode();
}
}