/**
* EasyBeans
* Copyright (C) 2008 Bull S.A.S.
* Contact: easybeans@ow2.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library 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. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id: EasyBeansNamingContextListener.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/
package org.ow2.easybeans.deployer.web.tomcat;
import java.util.StringTokenizer;
import javax.naming.Context;
import javax.naming.LinkRef;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContextType;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.core.NamingContextListener;
import org.apache.naming.ContextAccessController;
import org.ow2.easybeans.deployment.api.EZBInjectionHolder;
import org.ow2.easybeans.persistence.api.EZBPersistenceUnitManager;
import org.ow2.easybeans.resolver.api.EZBJNDIResolver;
import org.ow2.easybeans.resolver.api.EZBJNDIResolverException;
import org.ow2.util.ee.metadata.common.api.enc.IENCBinding;
import org.ow2.util.ee.metadata.common.api.struct.IJEjbEJB;
import org.ow2.util.ee.metadata.common.api.struct.IJavaxPersistenceContext;
import org.ow2.util.ee.metadata.common.api.struct.IJavaxPersistenceUnit;
import org.ow2.util.ee.metadata.common.impl.enc.ENCBindingHolder;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;
/**
* Naming listener that will allow to add our bindings.
* @author Florent Benoit
*/
public class EasyBeansNamingContextListener extends NamingContextListener {
/**
* Logger.
*/
private Log logger = LogFactory.getLog(EasyBeansNamingContextListener.class);
/**
* ENC Binding holder.
*/
private ENCBindingHolder encBindingHolder = null;
/**
* ENC Injection holder.
*/
private EZBInjectionHolder injectionHolder = null;
/**
* Default Constructor.
*/
public EasyBeansNamingContextListener() {
super();
}
/**
* Sets the enc binding holder to use.
* @param encBindingHolder the given holder object
*/
public void setEncBindingHolder(final ENCBindingHolder encBindingHolder) {
this.encBindingHolder = encBindingHolder;
}
/**
* Sets the injection holder to use.
* @param injectionHolder the given holder object
*/
public void setInjectionHolder(final EZBInjectionHolder injectionHolder) {
this.injectionHolder = injectionHolder;
}
/**
* Acknowledge the occurrence of the specified event.
* @param event LifecycleEvent that has occurred
*/
@Override
public void lifecycleEvent(final LifecycleEvent event) {
// Call super method
super.lifecycleEvent(event);
if (event.getType() == Lifecycle.START_EVENT) {
// No ENC holder
if (this.encBindingHolder == null) {
return;
}
// No ENC holder
if (this.injectionHolder == null) {
return;
}
// Sets writable mode
ContextAccessController.setSecurityToken(getName(), this.container);
ContextAccessController.setWritable(getName(), this.container);
// Gets the java:comp/env context
Context context = getNamingContext();
Context envCtx;
try {
envCtx = (Context) context.lookup("comp/env");
} catch (NamingException e) {
throw new IllegalStateException("Unable to get comp/env subcontext", e);
}
// Needs to bind object
// Persistence context
EZBPersistenceUnitManager persistenceUnitManager = this.injectionHolder.getPersistenceUnitManager();
for (IENCBinding<IJavaxPersistenceContext> binding : this.encBindingHolder.getPersistenceContextBindings()) {
String encName = binding.getName();
String unitName = binding.getValue().getUnitName();
PersistenceContextType type = binding.getValue().getType();
EntityManager em = persistenceUnitManager.getEntityManager(unitName, type);
try {
createSubcontexts(envCtx, encName);
envCtx.rebind(encName, em);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Adding persistence-context 'java:comp/env/" + encName + "'");
}
} catch (NamingException e) {
this.logger.error("Unable to bind persistence-context in ENC", e);
}
}
// Persistence unit
for (IENCBinding<IJavaxPersistenceUnit> binding : this.encBindingHolder.getPersistenceUnitBindings()) {
String encName = binding.getName();
String unitName = binding.getValue().getUnitName();
EntityManagerFactory emf = persistenceUnitManager.getEntityManagerFactory(unitName);
try {
createSubcontexts(envCtx, encName);
envCtx.rebind(encName, emf);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Adding persistence-unit 'java:comp/env/" + encName + "'");
}
} catch (NamingException e) {
this.logger.error("Unable to bind persistence-unit in ENC", e);
}
}
// EJBs
EZBJNDIResolver jndiResolver = this.injectionHolder.getJNDIResolver();
if (jndiResolver != null) {
for (IENCBinding<IJEjbEJB> binding : this.encBindingHolder.getEJBBindings()) {
String encName = binding.getName();
IJEjbEJB jEjbEJB = binding.getValue();
String interfaceName = jEjbEJB.getBeanInterface();
String beanName = jEjbEJB.getBeanName();
String jndiName;
try {
jndiName = jndiResolver.getEJBJNDIUniqueName(interfaceName, beanName);
// Bind a link to this JNDI name
try {
createSubcontexts(envCtx, encName);
envCtx.rebind(encName, new LinkRef(jndiName));
if (this.logger.isDebugEnabled()) {
this.logger.debug("Adding ejb 'java:comp/env/" + encName + "' from JNDIName '" + jndiName
+ "'.");
}
} catch (NamingException e) {
this.logger.error("Unable to bind EJB in ENC", e);
}
} catch (EZBJNDIResolverException e) {
this.logger.error("Cannot get JNDI name for enc name '" + encName + "'", e);
}
}
}
// Set back to read only context
ContextAccessController.setReadOnly(getName());
}
}
/**
* This method is private in the super class...
* Create all intermediate subcontexts on the given context with the given name.
* @param ctx the context on which create sub context
* @param name the name of the entry that may contains subpart
* @throws NamingException if the context are not created
*/
protected void createSubcontexts(final javax.naming.Context ctx, final String name) throws NamingException {
javax.naming.Context currentContext = ctx;
StringTokenizer tokenizer = new StringTokenizer(name, "/");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
if ((!token.equals("")) && (tokenizer.hasMoreTokens())) {
try {
currentContext = currentContext.createSubcontext(token);
} catch (NamingException e) {
// Silent catch. Probably an object is already bound in
// the context.
currentContext = (javax.naming.Context) currentContext.lookup(token);
}
}
}
}
}