package org.jboss.seam.ioc.spring;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.core.Events;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
/**
* Allows for the creation of seam scoped component in spring. Seam
* scopes are automatically made available if the
* SeamScopePostProcessor is declared in the current
* BeanFactory. <seam:configure-scopes/>
*
* @author youngm
* @see SeamScopePostProcessor
*/
public class SeamScope
implements Scope
{
private static final LogProvider log = Logging.getLogProvider(SeamScope.class);
private ScopeType scope;
public SeamScope(ScopeType scope)
{
this.scope = scope;
}
/**
* Gets an instance of a Seam component providing the current ObjectFactory if needed.
*
* @see org.springframework.beans.factory.config.Scope#get(java.lang.String,
* org.springframework.beans.factory.ObjectFactory)
*/
public Object get(String name, ObjectFactory objectFactory)
{
try
{
SpringComponent.setObjectFactory(objectFactory);
Component component = SpringComponent.forSpringBeanName(name);
return Component.getInstance(component.getName(), scope, true);
}
finally
{
SpringComponent.setObjectFactory(null);
}
}
/**
* Not used yet.
*
* @see org.springframework.beans.factory.config.Scope#getConversationId()
*/
public String getConversationId()
{
return null;
}
/**
* @see org.springframework.beans.factory.config.Scope#registerDestructionCallback(java.lang.String,
* java.lang.Runnable)
*/
public void registerDestructionCallback(String name, Runnable callback)
{
SpringComponent.forSpringBeanName(name).registerDestroyCallback(name, callback);
}
/**
* On remove destroys the seam component.
*
* @see org.springframework.beans.factory.config.Scope#remove(java.lang.String)
*/
public Object remove(String name) {
// copied from Component.callDestory should be able to reuse. Needed because if remove is called then for some
// reason spring doesn't use the destroy callback.
log.debug("destroying: " + name);
Component component = SpringComponent.forSpringBeanName(name);
Object bean = null;
if (component != null)
{
bean = scope.getContext().get(component.getName());
if (bean != null) // in a portal environment, this is possible
{
if (Events.exists())
{
Events.instance().raiseEvent("org.jboss.seam.preDestroy." + name);
}
try
{
if (component.hasDestroyMethod())
{
component.callComponentMethod(bean, component.getDestroyMethod());
}
}
catch (Exception e)
{
log.warn("Could not destroy component: " + component.getName(), e);
}
}
scope.getContext().remove(component.getName());
}
return bean;
}
}