org.apache.webbeans.config.BeansDeployer Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.webbeans.config;
import org.apache.webbeans.annotation.AnnotationManager;
import org.apache.webbeans.component.AbstractProducerBean;
import org.apache.webbeans.component.BeanAttributesImpl;
import org.apache.webbeans.component.CdiInterceptorBean;
import org.apache.webbeans.component.DecoratorBean;
import org.apache.webbeans.component.EnterpriseBeanMarker;
import org.apache.webbeans.component.InjectionTargetBean;
import org.apache.webbeans.component.ManagedBean;
import org.apache.webbeans.component.OwbBean;
import org.apache.webbeans.component.ProducerFieldBean;
import org.apache.webbeans.component.ProducerMethodBean;
import org.apache.webbeans.component.creation.BeanAttributesBuilder;
import org.apache.webbeans.component.creation.CdiInterceptorBeanBuilder;
import org.apache.webbeans.component.creation.DecoratorBeanBuilder;
import org.apache.webbeans.component.creation.ManagedBeanBuilder;
import org.apache.webbeans.component.creation.ObserverMethodsBuilder;
import org.apache.webbeans.component.creation.ProducerFieldBeansBuilder;
import org.apache.webbeans.component.creation.ProducerMethodBeansBuilder;
import org.apache.webbeans.container.BeanManagerImpl;
import org.apache.webbeans.container.InjectableBeanManager;
import org.apache.webbeans.container.InjectionResolver;
import org.apache.webbeans.corespi.se.DefaultJndiService;
import org.apache.webbeans.deployment.StereoTypeModel;
import org.apache.webbeans.event.ObserverMethodImpl;
import org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.exception.WebBeansDeploymentException;
import org.apache.webbeans.exception.WebBeansException;
import org.apache.webbeans.exception.inject.DefinitionException;
import org.apache.webbeans.exception.inject.DeploymentException;
import org.apache.webbeans.exception.inject.InconsistentSpecializationException;
import org.apache.webbeans.logger.WebBeansLoggerFacade;
import org.apache.webbeans.portable.AbstractProducer;
import org.apache.webbeans.portable.AnnotatedElementFactory;
import org.apache.webbeans.portable.events.ProcessAnnotatedTypeImpl;
import org.apache.webbeans.portable.events.ProcessBeanImpl;
import org.apache.webbeans.portable.events.ProcessInjectionTargetImpl;
import org.apache.webbeans.portable.events.discovery.AfterBeanDiscoveryImpl;
import org.apache.webbeans.portable.events.discovery.AfterDeploymentValidationImpl;
import org.apache.webbeans.portable.events.discovery.BeforeBeanDiscoveryImpl;
import org.apache.webbeans.portable.events.generics.GProcessManagedBean;
import org.apache.webbeans.spi.JNDIService;
import org.apache.webbeans.spi.ScannerService;
import org.apache.webbeans.spi.plugins.OpenWebBeansJavaEEPlugin;
import org.apache.webbeans.spi.plugins.OpenWebBeansWebPlugin;
import org.apache.webbeans.util.AnnotationUtil;
import org.apache.webbeans.util.ClassUtil;
import org.apache.webbeans.util.ExceptionUtil;
import org.apache.webbeans.util.InjectionExceptionUtil;
import org.apache.webbeans.util.WebBeansConstants;
import org.apache.webbeans.util.WebBeansUtil;
import org.apache.webbeans.xml.WebBeansXMLConfigurator;
import javax.enterprise.context.NormalScope;
import javax.enterprise.inject.AmbiguousResolutionException;
import javax.enterprise.inject.Model;
import javax.enterprise.inject.Specializes;
import javax.enterprise.inject.UnproxyableResolutionException;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.Interceptor;
import javax.enterprise.inject.spi.ObserverMethod;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Deploys the all beans that are defined in the {@link org.apache.webbeans.spi.ScannerService} at
* the scanner phase.
*/
@SuppressWarnings("unchecked")
//This class written as single threaded.
public class BeansDeployer
{
//Logger instance
private static final Logger logger = WebBeansLoggerFacade.getLogger(BeansDeployer.class);
public static final String JAVAX_ENTERPRISE_PACKAGE = "javax.enterprise.";
/**Deployment is started or not*/
protected boolean deployed = false;
/**XML Configurator*/
protected WebBeansXMLConfigurator xmlConfigurator = null;
/**Discover ejb or not*/
protected boolean discoverEjb = false;
private final WebBeansContext webBeansContext;
/**
* Creates a new deployer with given xml configurator.
*
* @param xmlConfigurator xml configurator
* @param webBeansContext
*/
public BeansDeployer(WebBeansXMLConfigurator xmlConfigurator, WebBeansContext webBeansContext)
{
this.xmlConfigurator = xmlConfigurator;
this.webBeansContext = webBeansContext;
String usage = this.webBeansContext.getOpenWebBeansConfiguration().getProperty(OpenWebBeansConfiguration.USE_EJB_DISCOVERY);
discoverEjb = Boolean.parseBoolean(usage);
}
/**
* Deploys all the defined web beans components in the container startup.
*
* It deploys from the web-beans.xml files and from the class files. It uses
* the {@link org.apache.webbeans.spi.ScannerService} to get classes.
*
*
* @throws WebBeansDeploymentException if any deployment exception occurs
*/
public synchronized void deploy(ScannerService scanner)
{
try
{
if (!deployed)
{
//Load Extensions
webBeansContext.getExtensionLoader().loadExtensionServices();
// Bind manager
JNDIService service = webBeansContext.getService(JNDIService.class);
//Default jndi is just a map
if(service instanceof DefaultJndiService)
{
service.bind(WebBeansConstants.WEB_BEANS_MANAGER_JNDI_NAME, new InjectableBeanManager(webBeansContext.getBeanManagerImpl()));
}
//Assume, actual JNDI implementation
else
{
service.bind(WebBeansConstants.WEB_BEANS_MANAGER_JNDI_NAME, webBeansContext.getBeanManagerImpl().getReference());
}
// Register Manager built-in component
webBeansContext.getBeanManagerImpl().addInternalBean(webBeansContext.getWebBeansUtil().getManagerBean());
//Fire Event
fireBeforeBeanDiscoveryEvent();
//Deploy bean from XML. Also configures deployments, interceptors, decorators.
deployFromXML(scanner);
//Checking stereotype conditions
checkStereoTypes(scanner);
//Configure Default Beans
configureDefaultBeans();
//Discover classpath classes
deployFromClassPath(scanner);
//Deploy additional Annotated Types
deployAdditionalAnnotatedTypes();
//Check Specialization
processSpecializations(scanner);
//Fire Event
fireAfterBeanDiscoveryEvent();
//Validate injection Points
validateInjectionPoints();
//Fire Event
fireAfterDeploymentValidationEvent();
// do some cleanup after the deployment
scanner.release();
webBeansContext.getAnnotatedElementFactory().clear();
}
}
catch (UnsatisfiedResolutionException e)
{
throw new DeploymentException(e);
}
catch (AmbiguousResolutionException e)
{
throw new DeploymentException(e);
}
catch (UnproxyableResolutionException e)
{
// the tck expects a DeploymentException, but it really should be a DefinitionException, see i.e. https://issues.jboss.org/browse/CDITCK-346
throw new DeploymentException(e);
}
catch (WebBeansConfigurationException e)
{
throw new DeploymentException(e);
}
catch (Exception e)
{
throw ExceptionUtil.throwAsRuntimeException(e);
}
finally
{
//if bootstrapping failed, it doesn't make sense to do it again
//esp. because #addInternalBean might have been called already and would cause an exception in the next run
deployed = true;
}
}
/**
* Configure Default Beans.
*/
private void configureDefaultBeans()
{
BeanManagerImpl beanManager = webBeansContext.getBeanManagerImpl();
WebBeansUtil webBeansUtil = webBeansContext.getWebBeansUtil();
// Register Conversation built-in component
beanManager.addInternalBean(webBeansUtil.getConversationBean());
// Register InjectionPoint bean
beanManager.addInternalBean(webBeansUtil.getInjectionPointBean());
//Register Instance Bean
beanManager.addInternalBean(webBeansUtil.getInstanceBean());
//Register Event Bean
beanManager.addInternalBean(webBeansUtil.getEventBean());
//Register Metadata Beans
beanManager.addInternalBean(webBeansUtil.getBeanMetadataBean());
beanManager.addInternalBean(webBeansUtil.getInterceptorMetadataBean());
beanManager.addInternalBean(webBeansUtil.getDecoratorMetadataBean());
beanManager.addInternalBean(webBeansUtil.getInterceptedOrDecoratedBeanMetadataBean());
//REgister Provider Beans
OpenWebBeansJavaEEPlugin beanEeProvider = webBeansContext.getPluginLoader().getJavaEEPlugin();
OpenWebBeansWebPlugin beanWebProvider = webBeansContext.getPluginLoader().getWebPlugin();
if(beanEeProvider != null)
{
addDefaultBean(webBeansContext, "org.apache.webbeans.ee.common.beans.PrincipalBean");
addDefaultBean(webBeansContext, "org.apache.webbeans.ee.beans.ValidatorBean");
addDefaultBean(webBeansContext, "org.apache.webbeans.ee.beans.ValidatorFactoryBean");
addDefaultBean(webBeansContext, "org.apache.webbeans.ee.beans.UserTransactionBean");
}
else if(beanWebProvider != null)
{
addDefaultBean(webBeansContext, "org.apache.webbeans.ee.common.beans.PrincipalBean");
}
}
private void addDefaultBean(WebBeansContext ctx,String className)
{
Bean> bean = null;
Class> beanClass = ClassUtil.getClassFromName(className);
if(beanClass != null)
{
bean = (Bean)newInstance(ctx, beanClass);
}
if(bean != null)
{
ctx.getBeanManagerImpl().addInternalBean(bean);
}
}
/**
* create a new instance of the class
*/
private Object newInstance(WebBeansContext wbc, Class> clazz)
{
try
{
if(System.getSecurityManager() != null)
{
final Constructor> c = webBeansContext.getSecurityService().doPrivilegedGetConstructor(clazz, WebBeansContext.class);
if (c == null)
{
return webBeansContext.getSecurityService().doPrivilegedObjectCreate(clazz);
}
return c.newInstance(wbc);
}
if (clazz.getConstructors().length > 0)
{
try
{
return clazz.getConstructor(new Class>[] { WebBeansContext.class }).newInstance(wbc);
}
catch (final Exception e)
{
return clazz.newInstance();
}
}
return clazz.newInstance();
}
catch(Exception e)
{
Throwable cause = e;
if(e instanceof PrivilegedActionException)
{
cause = e.getCause();
}
String error = "Error occurred while creating an instance of class : " + clazz.getName();
logger.log(Level.SEVERE, error, cause);
throw new WebBeansException(error,cause);
}
}
/**
* Fires event before bean discovery.
*/
private void fireBeforeBeanDiscoveryEvent()
{
BeanManagerImpl manager = webBeansContext.getBeanManagerImpl();
manager.fireLifecycleEvent(new BeforeBeanDiscoveryImpl(webBeansContext));
}
/**
* Fires event after bean discovery.
*/
private void fireAfterBeanDiscoveryEvent()
{
BeanManagerImpl manager = webBeansContext.getBeanManagerImpl();
manager.fireLifecycleEvent(new AfterBeanDiscoveryImpl(webBeansContext));
webBeansContext.getWebBeansUtil().inspectErrorStack(
"There are errors that are added by AfterBeanDiscovery event observers. Look at logs for further details");
}
/**
* Fires event after deployment valdiation.
*/
private void fireAfterDeploymentValidationEvent()
{
BeanManagerImpl manager = webBeansContext.getBeanManagerImpl();
manager.fireLifecycleEvent(new AfterDeploymentValidationImpl(manager));
webBeansContext.getWebBeansUtil().inspectErrorStack(
"There are errors that are added by AfterDeploymentValidation event observers. Look at logs for further details");
}
/**
* Validate all injection points.
*/
private void validateInjectionPoints()
{
logger.fine("Validation of injection points has started.");
webBeansContext.getDecoratorsManager().validateDecoratorClasses();
webBeansContext.getInterceptorsManager().validateInterceptorClasses();
Set> beans = new HashSet>();
//Adding decorators to validate
Set> decorators = webBeansContext.getDecoratorsManager().getDecorators();
beans.addAll(decorators);
logger.fine("Validation of the decorator's injection points has started.");
//Validate Decorators
validate(beans);
beans.clear();
//Adding interceptors to validate
List> interceptors = webBeansContext.getInterceptorsManager().getCdiInterceptors();
for(javax.enterprise.inject.spi.Interceptor interceptor : interceptors)
{
beans.add(interceptor);
}
logger.fine("Validation of the interceptor's injection points has started.");
//Validate Interceptors
validate(beans);
beans.clear();
beans = webBeansContext.getBeanManagerImpl().getBeans();
//Validate Others
validate(beans);
logger.info(OWBLogConst.INFO_0003);
}
/**
* Validates beans.
*
* @param beans deployed beans
*/
private void validate(Set> beans)
{
BeanManagerImpl manager = webBeansContext.getBeanManagerImpl();
if (beans != null && beans.size() > 0)
{
Stack beanNames = new Stack();
for (Bean> bean : beans)
{
if (bean instanceof OwbBean && !((OwbBean)bean).isEnabled())
{
// we skip disabled beans
continue;
}
//don't validate the cdi-api
if (bean.getBeanClass().getName().startsWith(JAVAX_ENTERPRISE_PACKAGE))
{
continue;
}
String beanName = bean.getName();
if(beanName != null)
{
beanNames.push(beanName);
}
if (bean instanceof OwbBean && !(bean instanceof Interceptor) && !(bean instanceof Decorator))
{
OwbBean owbBean = (OwbBean)bean;
if (owbBean.getProducer() instanceof AbstractProducer)
{
AbstractProducer producer = (AbstractProducer)owbBean.getProducer();
AnnotatedType annotatedType;
if (owbBean instanceof InjectionTargetBean)
{
annotatedType = ((InjectionTargetBean)owbBean).getAnnotatedType();
}
else
{
annotatedType = webBeansContext.getAnnotatedElementFactory().newAnnotatedType(owbBean.getReturnType());
}
producer.defineInterceptorStack(owbBean, annotatedType, webBeansContext);
}
}
//Check passivation scope
checkPassivationScope(bean);
//Bean injection points
Set injectionPoints = bean.getInjectionPoints();
//Check injection points
if(injectionPoints != null)
{
for (InjectionPoint injectionPoint : injectionPoints)
{
if(!injectionPoint.isDelegate())
{
manager.validate(injectionPoint);
}
else
{
if(!bean.getBeanClass().isAnnotationPresent(javax.decorator.Decorator.class)
&& !webBeansContext.getDecoratorsManager().containsCustomDecoratorClass(bean.getBeanClass()))
{
throw new WebBeansConfigurationException(
"Delegate injection points can not defined by beans that are not decorator. Injection point : "
+ injectionPoint);
}
}
}
}
}
//Validate Bean names
validateBeanNames(beanNames);
//Clear Names
beanNames.clear();
}
}
private void validateBeanNames(Stack beanNames)
{
if(beanNames.size() > 0)
{
for(String beanName : beanNames)
{
for(String other : beanNames)
{
String part = null;
int i = beanName.lastIndexOf('.');
if(i != -1)
{
part = beanName.substring(0,i);
}
if(beanName.equals(other))
{
InjectionResolver resolver = webBeansContext.getBeanManagerImpl().getInjectionResolver();
Set> beans = resolver.implResolveByName(beanName);
if(beans.size() > 1)
{
beans = resolver.findByAlternatives(beans);
if(beans.size() > 1)
{
InjectionExceptionUtil.throwAmbiguousResolutionExceptionForBeanName(beans, beanName);
}
}
}
else
{
if(part != null)
{
if(part.equals(other))
{
throw new WebBeansConfigurationException("EL name of one bean is of the form x.y, where y is a valid bean EL name, and " +
"x is the EL name of the other bean for the bean name : " + beanName);
}
}
}
}
}
}
}
/**
* Discovers and deploys classes from class path.
*
* @param scanner discovery scanner
* @throws ClassNotFoundException if class not found
*/
protected void deployFromClassPath(ScannerService scanner) throws ClassNotFoundException
{
logger.fine("Deploying configurations from class files has started.");
// Start from the class
Set> classIndex = scanner.getBeanClasses();
//Iterating over each class
if (classIndex != null)
{
AnnotatedElementFactory annotatedElementFactory = webBeansContext.getAnnotatedElementFactory();
for(Class> implClass : classIndex)
{
//Define annotation type
AnnotatedType> annotatedType = annotatedElementFactory.newAnnotatedType(implClass);
if (null != annotatedType)
{
deploySingleAnnotatedType(implClass, annotatedType);
// if the implClass already gets processed as part of the
// standard BDA scanning, then we don't need to 'additionally'
// deploy it anymore.
webBeansContext.getBeanManagerImpl().removeAdditionalAnnotatedType(annotatedType);
}
else
{
if (logger.isLoggable(Level.FINE))
{
logger.fine("Error creating managed bean " + implClass);
}
}
}
}
logger.fine("Deploying configurations from class files has ended.");
}
/**
* Deploys any AnnotatedTypes added to the BeanManager during beforeBeanDiscovery.
*/
private void deployAdditionalAnnotatedTypes()
{
BeanManagerImpl beanManager = webBeansContext.getBeanManagerImpl();
Collection> annotatedTypes = beanManager.getAdditionalAnnotatedTypes();
for(AnnotatedType> type : annotatedTypes)
{
Class implClass = type.getJavaClass();
deploySingleAnnotatedType(implClass, type);
}
}
/**
* Common helper method used to deploy annotated types discovered through
* scanning or during beforeBeanDiscovery.
*
* @param implClass the class of the bean to be deployed
* @param annotatedType the AnnotatedType representing the bean to be deployed
*/
private void deploySingleAnnotatedType(Class implClass, AnnotatedType annotatedType)
{
// Fires ProcessAnnotatedType
ProcessAnnotatedTypeImpl> processAnnotatedEvent =
webBeansContext.getWebBeansUtil().fireProcessAnnotatedTypeEvent(annotatedType);
// if veto() is called
if (processAnnotatedEvent.isVeto())
{
return;
}
Class beanClass = processAnnotatedEvent.getAnnotatedType().getJavaClass();
// EJBs can be defined so test them really before going for a ManagedBean
if (discoverEjb && EJBWebBeansConfigurator.isSessionBean(implClass, webBeansContext))
{
logger.log(Level.FINE, "Found Enterprise Bean with class name : [{0}]", implClass.getName());
defineEnterpriseWebBean((Class
© 2015 - 2025 Weber Informatics LLC | Privacy Policy