package org.jboss.seam.ioc.spring;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpSessionActivationListener;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.core.Expressions;
import org.jboss.seam.core.Mutable;
import org.jboss.seam.core.Expressions.ValueExpression;
import org.jboss.seam.intercept.Proxy;
import org.springframework.aop.TargetSource;
/**
* A TargetSource for a seam component instance. Will obtain an instance given a
* name and optionally a scope and create. Used by the SeamFactoryBean to create
* a proxy for a requested seam component instance.
*
* @author youngm
*/
@SuppressWarnings("serial")
public class SeamTargetSource implements TargetSource, Serializable
{
private ScopeType scope;
private String name;
private Boolean create;
private ValueExpression valueExpression;
private Class type;
public SeamTargetSource(String name, ScopeType scope, Boolean create, Class type)
{
this(name, scope, create);
this.type = type;
}
/**
* @param name
* Name of the component: required
* @param scope
* Name of the scope the component is in: optional
* @param create
* Whether to create a new instance if one doesn't already exist:
* optional
*/
public SeamTargetSource(String name, ScopeType scope, Boolean create)
{
if (name == null || "".equals(name))
{
throw new IllegalArgumentException("Name is required.");
}
this.name = name;
this.scope = scope;
this.create = create;
if (name.startsWith("#"))
{
this.valueExpression = Expressions.instance().createValueExpression(name);
}
}
/**
* Returns a component instance for this TargetSource.
*
* @see org.springframework.aop.TargetSource#getTarget()
*/
public Object getTarget() throws Exception
{
if (valueExpression != null)
{
return valueExpression.getValue();
}
else
{
if (scope == null && create == null)
{
return Component.getInstance(name);
}
else if (scope == null)
{
return Component.getInstance(name, create);
}
else if (create == null)
{
return Component.getInstance(name, scope);
}
else
{
return Component.getInstance(name, scope, create);
}
}
}
/**
* Obtains the seam component beanClass or the defined type for this
* TargetSource.
*
* @see org.springframework.aop.TargetSource#getTargetClass()
*/
public Class getTargetClass()
{
if (type != null)
{
return type;
}
Component component = getComponent();
if (component == null)
{
return null;
}
if (component.hasUnwrapMethod())
{
return component.getUnwrapMethod().getReturnType();
}
return component.getBeanClass();
}
public List<Class> getSeamInterfaces()
{
List<Class> interfaces = new ArrayList<Class>();
Component component = getComponent();
// Attempt to piece together all of the possible interfaces to apply
// to our proxy.
if ( component != null && component.isInterceptionEnabled() )
{
if (component.getType().isSessionBean())
{
interfaces.addAll(component.getBusinessInterfaces());
}
else
{
interfaces.add(HttpSessionActivationListener.class);
interfaces.add(Mutable.class);
}
interfaces.add(Proxy.class);
}
return interfaces;
}
/**
* Get the component for this TargetSource
*
* @return component
*/
public Component getComponent()
{
if (valueExpression != null)
{
return null;
}
else
{
// TODO reuse
boolean unmockApplication = false;
if (!Contexts.isApplicationContextActive())
{
Lifecycle.setupApplication();
unmockApplication = true;
}
try
{
Component component = Component.forName(name);
if (component == null)
{
throw new IllegalStateException("Cannot find targetClass for seam component: "
+ name + ". Make sure Seam is being configured before Spring.");
}
return component;
}
finally
{
if (unmockApplication)
{
Lifecycle.cleanupApplication();
}
}
}
}
/**
* @see org.springframework.aop.TargetSource#isStatic()
*/
public boolean isStatic()
{
return false;
}
/**
* Don't think we need to do anything here.
*
* @see org.springframework.aop.TargetSource#releaseTarget(java.lang.Object)
*/
public void releaseTarget(Object target) throws Exception
{
// Do Nothing
}
}