com.caucho.config.cfg.BeanConfig Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of resin-kernel Show documentation
Show all versions of resin-kernel Show documentation
Kernel for Resin Java Application Server
The newest version!
/*
* Copyright (c) 1998-2012 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.config.cfg;
import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.MessageDriven;
import javax.ejb.Startup;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.NormalScope;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Scope;
import javax.inject.Singleton;
import com.caucho.config.ConfigException;
import com.caucho.config.Names;
import com.caucho.config.inject.BeanBuilder;
import com.caucho.config.inject.DefaultLiteral;
import com.caucho.config.inject.InjectManager;
import com.caucho.config.program.ConfigProgram;
import com.caucho.config.program.ContainerProgram;
import com.caucho.config.program.PropertyStringProgram;
import com.caucho.config.program.PropertyValueProgram;
import com.caucho.config.type.TypeFactory;
import com.caucho.config.xml.XmlBeanConfig;
import com.caucho.config.xml.XmlCookie;
import com.caucho.inject.Module;
import com.caucho.naming.Jndi;
import com.caucho.util.L10N;
/**
* Backward-compat configuration for the xml web bean component.
*/
@Module
public class BeanConfig {
private static final L10N L = new L10N(BeanConfig.class);
private String _filename;
private int _line;
private String _uri;
private String _jndiName;
private String _mbeanName;
private Class> _beanConfigClass;
private XmlBeanConfig _customBean;
private InjectManager _cdiManager;
private Class> _cl;
private String _name;
private ArrayList _qualifierList
= new ArrayList();
private ArrayList _stereotypeList
= new ArrayList();
private Class> _scope;
private ArrayList _newArgs;
private ContainerProgram _init;
private AnnotatedType> _annotatedType;
private Annotated _extAnnotated;
protected Bean> _bean;
// XXX: temp for osgi
private boolean _isService;
public BeanConfig()
{
_cdiManager = InjectManager.create();
if (getDefaultScope() != null)
setScope(getDefaultScope());
setService(isDefaultService());
}
public InjectManager getBeanManager()
{
return _cdiManager;
}
protected String getDefaultScope()
{
return "singleton";
}
protected boolean isDefaultService()
{
return true;
}
/**
* Returns the component's EL binding name.
*/
public void setName(String name)
{
_name = name;
}
/**
* Gets the component's EL binding name.
*/
public String getName()
{
return _name;
}
/**
* backwards compat
*/
public void setType(Class> cl)
{
setClass(cl);
}
/**
* Sets the component implementation class.
*/
public void setClass(Class> cl)
{
_cl = cl;
// env/1072
/*
if (_name == null)
_name = Introspector.decapitalize(cl.getSimpleName());
/*/
Class> type = getBeanConfigClass();
if (type != null && ! type.isAssignableFrom(cl))
throw new ConfigException(L.l("'{0}' is not a valid instance of '{1}'",
cl.getName(), type.getName()));
}
public Class> getClassType()
{
if (_customBean != null)
return _customBean.getClassType();
else
return _cl;
}
public Bean> getComponent()
{
return _bean;
}
/**
* Adds a component binding.
*/
public void addBinding(Annotation binding)
{
_qualifierList.add(binding);
}
public ArrayList getBindingList()
{
return _qualifierList;
}
public ArrayList getStereotypeList()
{
return _stereotypeList;
}
/**
* Sets the scope attribute.
*/
public void setScope(String scope)
{
if ("singleton".equals(scope)) {
_scope = javax.inject.Singleton.class;
// addAnnotation(new AnnotationLiteral() {});
}
else if ("dependent".equals(scope))
_scope = Dependent.class;
else if ("request".equals(scope))
_scope = RequestScoped.class;
else if ("session".equals(scope))
_scope = SessionScoped.class;
else if ("application".equals(scope))
_scope = ApplicationScoped.class;
else if ("conversation".equals(scope))
_scope = ConversationScoped.class;
else {
Class> cl = null;
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
cl = Class.forName(scope, false, loader);
} catch (ClassNotFoundException e) {
}
setScopeType(cl);
}
}
public void setScopeType(Class> cl)
{
if (cl == null)
throw new ConfigException(L.l("'{0}' is an invalid scope. The scope must be a valid @Scope annotation."));
if (! Annotation.class.isAssignableFrom(cl))
throw new ConfigException(L.l("'{0}' is an invalid scope. The scope must be a valid @Scope annotation."));
if (! cl.isAnnotationPresent(Scope.class)
&& ! cl.isAnnotationPresent(NormalScope.class))
throw new ConfigException(L.l("'{0}' is an invalid scope. The scope must be a valid @Scope annotation."));
_scope = cl;
}
/**
* Sets any new values
*/
public void addParam(ConfigProgram param)
{
if (_newArgs == null)
_newArgs = new ArrayList();
_newArgs.add(param);
}
/**
* Sets the init program.
*/
public void setInit(ContainerProgram init)
{
if (_init == null)
_init = new ContainerProgram();
_init.addProgram(init);
}
public void addInitProgram(ConfigProgram program)
{
if (_init == null)
_init = new ContainerProgram();
_init.addProgram(program);
}
public ContainerProgram getInit()
{
return _init;
}
/**
* Adds an init property
*/
public void addStringProperty(String name, String value)
{
if (_init == null)
_init = new ContainerProgram();
_init.addProgram(new PropertyStringProgram(name, value));
}
/**
* Adds an init property
*/
public void addProperty(String name, Object value)
{
if (_init == null)
_init = new ContainerProgram();
_init.addProgram(new PropertyValueProgram(name, value));
}
/**
* Adds an init property
*/
public void addOptionalStringProperty(String name, String value)
{
if (_init == null)
_init = new ContainerProgram();
_init.addProgram(0, new PropertyStringProgram(name, value, true));
}
/**
* Returns the configured component factory.
*/
private Bean getComponentFactory()
{
return _bean;
}
// XXX: temp for OSGI
private boolean isService()
{
return _isService;
}
public void setService(boolean isService)
{
_isService = isService;
}
/**
* Resin Config location
*/
public void setConfigLocation(String filename, int line)
{
_filename = filename;
_line = line;
}
public String getFilename()
{
return _filename;
}
public int getLine()
{
return _line;
}
public void setJndiName(String jndiName)
{
_jndiName = jndiName;
if (getName() == null)
setName(jndiName);
}
public void setMbeanName(String mbeanName)
{
_mbeanName = mbeanName;
}
public String getMBeanName()
{
return _mbeanName;
}
public void setMbeanClass(Class cl)
{
setMbeanInterface(cl);
}
public void setMbeanInterface(Class> cl)
{
}
public Class> getBeanConfigClass()
{
return _beanConfigClass;
}
public void setBeanConfigClass(Class> cl)
{
_beanConfigClass = cl;
}
/**
* uri-style configuration like the jms-queue url="memory:"
*/
public void setUri(String uri)
{
Class> beanConfigClass = getBeanConfigClass();
if (beanConfigClass == null) {
throw new ConfigException(L.l("'{0}' does not support the 'uri' attribute because its bean-config-class is undefined",
getClass().getName()));
}
_uri = uri;
String scheme;
String properties = "";
int p = uri.indexOf(':');
if (p >= 0) {
scheme = uri.substring(0, p);
properties = uri.substring(p + 1);
}
else
scheme = uri;
TypeFactory factory = TypeFactory.create();
setClass(factory.getDriverClassByUrl(beanConfigClass, uri));
String []props = properties.split("[;]");
for (String prop : props) {
if (prop.length() == 0)
continue;
String []values = prop.split("[=]");
if (values.length != 2)
throw new ConfigException(L.l("'{0}' is an invalid URI. Bean URI syntax is 'scheme:prop1=value1;prop2=value2'", uri));
addStringProperty(values[0], values[1]);
}
}
/**
* Returns the uri
*/
public String getUri()
{
return _uri;
}
public void addCustomBean(XmlBeanConfig> customBean)
{
_customBean = customBean;
}
protected String getTagName()
{
return "bean";
}
protected boolean isStartup()
{
return _scope == Singleton.class;
}
@PostConstruct
public void init()
{
if (_customBean != null) {
// server/1a37
// _customBean.initComponent();
return;
}
if (_cl == null) {
throw new ConfigException(L.l("<{0}> requires a class attribute",
getTagName()));
}
introspect();
InjectManager beanManager = InjectManager.create();
BeanBuilder builder = beanManager.createBeanFactory(_cl);
if (builder == null)
return;
_annotatedType = builder.getAnnotatedType();
if (_name != null) {
// server/2n00
if (! Map.class.isAssignableFrom(_cl))
addOptionalStringProperty("name", _name);
}
if (getCdiNamed() != null) {
// env/02s7
builder.name(getCdiNamed());
}
if (_annotatedType.isAnnotationPresent(javax.ejb.Singleton.class)
|| _annotatedType.isAnnotationPresent(Stateful.class)
|| _annotatedType.isAnnotationPresent(Stateless.class)
|| _annotatedType.isAnnotationPresent(MessageDriven.class)) {
throw new ConfigException(L.l("{0} cannot be configured by because it has an EJB annotation. Use CDI syntax instead.",
_annotatedType));
}
// server/21q1
if (isStartup()
&& ! _annotatedType.isAnnotationPresent(Stateful.class)
&& ! _annotatedType.isAnnotationPresent(Stateless.class)
&& ! _annotatedType.isAnnotationPresent(MessageDriven.class)) {
builder.annotation(new StartupLiteral());
}
for (Annotation qualifier : _qualifierList) {
builder.qualifier(qualifier);
}
if (_name != null) {
builder.qualifier(Names.create(_name));
}
if (_qualifierList.size() == 0)
builder.qualifier(DefaultLiteral.DEFAULT);
for (Annotation stereotype : _stereotypeList) {
builder.stereotype(stereotype.annotationType());
}
if (_scope != null) {
builder.scope(_scope);
// comp.setScope(_beanManager.getScopeContext(_scope));
}
if (Singleton.class == _scope) {
builder.annotation(new StartupLiteral());
}
builder.annotation(_cdiManager.generateXmlCookie());
if (_init != null)
builder.init(_init);
_bean = builder.bean();
_extAnnotated = builder.getExtendedAnnotated();
introspectPostInit();
deploy();
try {
if (_bean == null) {
}
else if (_jndiName != null) {
Jndi.bindDeepShort(_jndiName, _bean);
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw ConfigException.create(e);
}
}
protected String getCdiNamed()
{
return _name;
}
/**
* Introspection after the init has been set and before the @PostConstruct
* for additional interception
*/
protected void introspectPostInit()
{
}
protected void deploy()
{
if (_bean != null) {
// ejb/1030, env/1070
// getBeanManager().addBean(_bean, _extAnnotated);
getBeanManager().addBeanDiscover(_bean, _extAnnotated);
}
}
public Object getObject()
{
if (_bean != null) {
CreationalContext> env = _cdiManager.createCreationalContext(_bean);
Object value = _cdiManager.getReference(_bean, _bean.getBeanClass(), env);
return value;
}
else
return null;
}
public Object createObjectNoInit()
{
if (_bean != null) {
CreationalContext> env = _cdiManager.createCreationalContext(_bean);
// XXX:
return _cdiManager.getReference(_bean, (Class>) null, env);
// return _bean.createNoInit();
}
else
return null;
}
private void introspect()
{
if (_scope == null) {
for (Annotation ann : _cl.getDeclaredAnnotations()) {
if (ann.annotationType().isAnnotationPresent(Scope.class)
|| ann.annotationType().isAnnotationPresent(NormalScope.class)) {
if (_scope != null) {
throw new ConfigException(L.l("{0}: multiple scope annotations are forbidden ({1} and {2}).",
_cl.getName(),
_scope.getSimpleName(),
ann.annotationType().getSimpleName()));
}
_scope = ann.annotationType();
}
}
}
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + _cl + "]";
}
static class StartupLiteral extends AnnotationLiteral implements Startup {
}
}