//$Id: Init.java 9717 2008-12-04 08:09:30Z dan.j.allen $
package org.jboss.seam.core;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.jboss.seam.Component;
import org.jboss.seam.Namespace;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.async.AsynchronousInterceptor;
import org.jboss.seam.bpm.BusinessProcessInterceptor;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.core.Expressions.MethodExpression;
import org.jboss.seam.core.Expressions.ValueExpression;
import org.jboss.seam.ejb.RemoveInterceptor;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.jboss.seam.persistence.EntityManagerProxyInterceptor;
import org.jboss.seam.persistence.HibernateSessionProxyInterceptor;
import org.jboss.seam.persistence.ManagedEntityInterceptor;
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.SecurityInterceptor;
import org.jboss.seam.transaction.RollbackInterceptor;
import org.jboss.seam.transaction.TransactionInterceptor;
import org.jboss.seam.util.Resources;
import org.jboss.seam.webservice.WSSecurityInterceptor;
/**
* A Seam component that holds Seam configuration settings
*
* @author Gavin King
*/
@Scope(ScopeType.APPLICATION)
@BypassInterceptors
@Name("org.jboss.seam.core.init")
@Install(value=false, precedence=BUILT_IN)
public class Init
{
public static List<String> DEFAULT_INTERCEPTORS = new ArrayList<String>(Arrays.asList(
SynchronizationInterceptor.class.getName(),
AsynchronousInterceptor.class.getName(),
RemoveInterceptor.class.getName(),
HibernateSessionProxyInterceptor.class.getName(),
EntityManagerProxyInterceptor.class.getName(),
MethodContextInterceptor.class.getName(),
EventInterceptor.class.getName(),
ConversationalInterceptor.class.getName(),
BusinessProcessInterceptor.class.getName(),
ConversationInterceptor.class.getName(),
BijectionInterceptor.class.getName(),
RollbackInterceptor.class.getName(),
TransactionInterceptor.class.getName(),
WSSecurityInterceptor.class.getName(),
SecurityInterceptor.class.getName()
));
private LogProvider log = Logging.getLogProvider(Init.class);
private Namespace rootNamespace = new Namespace(null);
private Collection<Namespace> globalImports = new ArrayList<Namespace>();
//private boolean isClientSideConversations = false;
private boolean jbpmInstalled;
private String jndiPattern;
private boolean debug;
private boolean myFacesLifecycleBug;
private boolean transactionManagementEnabled = true;
private boolean distributable = false;
private List<String> interceptors = new ArrayList<String>(DEFAULT_INTERCEPTORS);
private Map<String, List<ObserverMethod>> observerMethods = new HashMap<String, List<ObserverMethod>>();
private Map<String, List<ObserverMethodExpression>> observerMethodBindings = new HashMap<String, List<ObserverMethodExpression>>();
private Map<String, FactoryMethod> factories = new HashMap<String, FactoryMethod>();
private Map<String, FactoryExpression> factoryMethodExpressions = new HashMap<String, FactoryExpression>();
private Map<String, FactoryExpression> factoryValueExpressions = new HashMap<String, FactoryExpression>();
private Set<String> autocreateVariables = new HashSet<String>();
private Set<String> installedFilters = new HashSet<String>();
private Set<String> resourceProviders = new HashSet<String>();
private Set<String> permissionResolvers = new HashSet<String>();
private Set<String> hotDeployableComponents = new HashSet<String>();
private Map<String, String> converters = new HashMap<String, String>();
private Map<String, String> validators = new HashMap<String, String>();
private Map<Class, String> convertersByClass = new HashMap<Class, String>();
private long timestamp;
private long warTimestamp;
private File[] hotDeployPaths;
public static Init instance()
{
if ( !Contexts.isApplicationContextActive() )
{
throw new IllegalStateException("No active application scope");
}
Init init = (Init) Contexts.getApplicationContext().get(Init.class);
//commented out because of some test cases:
/*if (init==null)
{
throw new IllegalStateException("No Init exists");
}*/
return init;
}
/*public boolean isClientSideConversations()
{
return isClientSideConversations;
}
public void setClientSideConversations(boolean isClientSideConversations)
{
this.isClientSideConversations = isClientSideConversations;
}*/
public static class FactoryMethod {
private Method method;
private Component component;
private ScopeType scope;
FactoryMethod(Method method, Component component)
{
this.method = method;
this.component = component;
scope = method.getAnnotation(org.jboss.seam.annotations.Factory.class).scope();
}
public ScopeType getScope()
{
return scope;
}
public Component getComponent()
{
return component;
}
public Method getMethod()
{
return method;
}
@Override
public String toString()
{
return "FactoryMethod(" + method + ')';
}
}
public static class FactoryExpression
{
private String expression;
private ScopeType scope;
FactoryExpression(String expression, ScopeType scope)
{
this.expression = expression;
this.scope = scope;
}
public MethodExpression getMethodBinding()
{
//TODO: figure out some way to cache this!!
return Expressions.instance().createMethodExpression(expression);
}
public ValueExpression getValueBinding()
{
//TODO: figure out some way to cache this!!
return Expressions.instance().createValueExpression(expression);
}
public ScopeType getScope()
{
return scope;
}
@Override
public String toString()
{
return "FactoryBinding(" + expression + ')';
}
}
public FactoryMethod getFactory(String variable)
{
return factories.get(variable);
}
public FactoryExpression getFactoryMethodExpression(String variable)
{
return factoryMethodExpressions.get(variable);
}
public FactoryExpression getFactoryValueExpression(String variable)
{
return factoryValueExpressions.get(variable);
}
private void checkDuplicateFactory(String variable)
{
if ( factories.containsKey(variable) )
{
throw new IllegalStateException("duplicate factory for: " + variable + " (duplicate is specified in a component)");
}
checkDuplicateFactoryExpressions(variable);
}
private void checkDuplicateFactoryExpressions(String variable)
{
if ( factoryMethodExpressions.containsKey(variable) || factoryValueExpressions.containsKey(variable) )
{
throw new IllegalStateException("duplicate factory for: " + variable + " (duplicate is specified in components.xml)");
}
}
private void checkDuplicateFactory(String variable, Component component)
{
if (factories.containsKey(variable))
{
String otherComponentName = factories.get(variable).getComponent().getName();
String componentName = component.getName();
if (componentName != null && !componentName.equals(otherComponentName))
{
throw new IllegalStateException("duplicate factory for: " + variable + " (duplicates are specified in " + componentName + " and " + otherComponentName + ")");
}
}
checkDuplicateFactoryExpressions(variable);
}
/**
* makes sure appropriate namespaces exist for a name. isComponent indicates the
* name is for a component type, in which case we don't create a namespace for the
* last part
*/
public Namespace initNamespaceForName(String name, boolean isComponent) {
Namespace namespace = getRootNamespace();
StringTokenizer tokens = new StringTokenizer(name, ".");
while (tokens.hasMoreTokens()) {
String token = tokens.nextToken();
if (tokens.hasMoreTokens() || !isComponent) {
//we don't want to create a namespace for a componentName
namespace = namespace.getOrCreateChild(token);
}
}
return namespace;
}
public void addFactoryMethod(String variable, Method method, Component component)
{
checkDuplicateFactory(variable, component);
factories.put(variable, new FactoryMethod(method, component));
initNamespaceForName(variable, true);
}
public void addFactoryMethodExpression(String variable, String methodBindingExpression, ScopeType scope)
{
checkDuplicateFactory(variable);
factoryMethodExpressions.put(variable, new FactoryExpression(methodBindingExpression, scope));
initNamespaceForName(variable, true);
}
public void addFactoryValueExpression(String variable, String valueBindingExpression, ScopeType scope)
{
checkDuplicateFactory(variable);
factoryValueExpressions.put(variable, new FactoryExpression(valueBindingExpression, scope));
initNamespaceForName(variable, true);
}
public static class ObserverMethod
{
private Method method;
private Component component;
private boolean create;
ObserverMethod(Method method, Component component, boolean create)
{
this.method = method;
this.component = component;
this.create = create;
}
public Component getComponent()
{
return component;
}
public Method getMethod()
{
return method;
}
public boolean isCreate()
{
return create;
}
@Override
public String toString()
{
return "ObserverMethod(" + method + ')';
}
@Override
public boolean equals(Object obj)
{
if (!(obj instanceof ObserverMethod)) return false;
ObserverMethod other = (ObserverMethod) obj;
return this.component.equals(other.component) &&
Arrays.equals(this.method.getParameterTypes(), other.method.getParameterTypes()) &&
this.method.getName().equals(other.getMethod().getName());
}
}
public static class ObserverMethodExpression
{
private MethodExpression methodBinding;
ObserverMethodExpression(MethodExpression method)
{
this.methodBinding = method;
}
public MethodExpression getMethodBinding()
{
return methodBinding;
}
@Override
public String toString()
{
return "ObserverMethodBinding(" + methodBinding + ')';
}
}
public List<ObserverMethod> getObserverMethods(String eventType)
{
return observerMethods.get(eventType);
}
public List<ObserverMethodExpression> getObserverMethodExpressions(String eventType)
{
return observerMethodBindings.get(eventType);
}
public void addObserverMethod(String eventType, Method method, Component component, boolean create)
{
List<ObserverMethod> observerList = observerMethods.get(eventType);
if (observerList==null)
{
observerList = new ArrayList<ObserverMethod>();
observerMethods.put(eventType, observerList);
}
ObserverMethod observerMethod = new ObserverMethod(method, component, create);
if (!observerList.contains(observerMethod))
{
observerList.add( observerMethod );
}
}
public void addObserverMethodExpression(String eventType, MethodExpression methodBinding)
{
List<ObserverMethodExpression> observerList = observerMethodBindings.get(eventType);
if (observerList==null)
{
observerList = new ArrayList<ObserverMethodExpression>();
observerMethodBindings.put(eventType, observerList);
}
observerList.add( new ObserverMethodExpression(methodBinding) );
}
/**
* Remove any observer methods registered on the component. Needed to clean
* out old observer methods on hot deploy
* @param component
*/
public void removeObserverMethods(Component component)
{
// TODO Better implementation ;-)
for (String eventType : observerMethods.keySet())
{
List<ObserverMethod> observerMethodsToRemove = new ArrayList<ObserverMethod>();
for (ObserverMethod observerMethod : observerMethods.get(eventType))
{
if (observerMethod.getComponent().equals(component))
{
observerMethodsToRemove.add(observerMethod);
}
}
observerMethods.get(eventType).removeAll(observerMethodsToRemove);
}
}
public boolean isJbpmInstalled()
{
return jbpmInstalled;
}
public String getJndiPattern()
{
return jndiPattern;
}
public void setJndiPattern(String jndiPattern)
{
this.jndiPattern = jndiPattern;
}
public boolean isDebug()
{
return debug;
}
public void setDebug(boolean debug)
{
this.debug = debug;
}
/**
* The debug page is considered available if debug JAR is on the classpath
* and Seam is running in debug mode (to prevent it from being enabling in
* the event the JAR is inadvertently packaged).
*/
public boolean isDebugPageAvailable()
{
return debug && Resources.getResource("META-INF/resources/debug.xhtml", null) != null;
}
public boolean isMyFacesLifecycleBug()
{
return myFacesLifecycleBug;
}
public void setMyFacesLifecycleBug(boolean myFacesLifecycleBugExists)
{
this.myFacesLifecycleBug = myFacesLifecycleBugExists;
}
public void setJbpmInstalled(boolean jbpmInstalled)
{
this.jbpmInstalled = jbpmInstalled;
}
public boolean isAutocreateVariable(String name)
{
return autocreateVariables.contains(name);
}
public void addAutocreateVariable(String name)
{
autocreateVariables.add(name);
}
public Namespace getRootNamespace()
{
return rootNamespace;
}
public void importNamespace(String namespaceName)
{
Namespace namespace = getRootNamespace();
StringTokenizer tokens = new StringTokenizer(namespaceName, ".");
while ( tokens.hasMoreTokens() )
{
namespace = namespace.getOrCreateChild( tokens.nextToken() );
}
globalImports.add(namespace);
}
public void addInstalledFilter(String name)
{
installedFilters.add(name);
}
public Set<String> getInstalledFilters()
{
return installedFilters;
}
public void addResourceProvider(String name)
{
resourceProviders.add(name);
}
public Set<String> getResourceProviders()
{
return resourceProviders;
}
public void addPermissionResolver(String name)
{
permissionResolvers.add(name);
}
public Set<String> getPermissionResolvers()
{
return permissionResolvers;
}
public Set<String> getHotDeployableComponents()
{
return hotDeployableComponents;
}
public void addHotDeployableComponent(String name)
{
this.hotDeployableComponents.add(name);
}
public Map<String, String> getConverters()
{
return converters;
}
public Map<Class, String> getConvertersByClass()
{
return convertersByClass;
}
public Map<String, String> getValidators()
{
return validators;
}
public boolean hasHotDeployableComponents()
{
return hotDeployPaths!=null;
}
public File[] getHotDeployPaths()
{
return hotDeployPaths;
}
public void setHotDeployPaths(File[] hotDeployJars)
{
this.hotDeployPaths = hotDeployJars;
}
public long getTimestamp()
{
return timestamp;
}
public void setTimestamp(long timestamp)
{
this.timestamp = timestamp;
}
public long getWarTimestamp()
{
return warTimestamp;
}
public void setWarTimestamp(long warTimestamp)
{
this.warTimestamp = warTimestamp;
}
public boolean isTransactionManagementEnabled()
{
return transactionManagementEnabled;
}
public void setTransactionManagementEnabled(boolean transactionManagementEnabled)
{
this.transactionManagementEnabled = transactionManagementEnabled;
}
public boolean isSecurityEnabled()
{
return Identity.isSecurityEnabled();
}
public void setSecurityEnabled(boolean securityEnabled)
{
Identity.setSecurityEnabled(securityEnabled);
}
public Collection<Namespace> getGlobalImports()
{
return globalImports;
}
public List<String> getInterceptors()
{
return interceptors;
}
public void setInterceptors(List<String> interceptors)
{
this.interceptors = interceptors;
}
public boolean isDistributable()
{
return distributable;
}
public void setDistributable(boolean distributable)
{
this.distributable = distributable;
}
/**
* Sanity check to warn users if they have disabled core interceptors
*/
public void checkDefaultInterceptors()
{
for (String defaultInterceptor : DEFAULT_INTERCEPTORS)
{
if (!interceptors.contains(defaultInterceptor))
{
log.warn("The built-in interceptor " + defaultInterceptor + " is missing. This application may not function as expected");
}
}
if (distributable && !interceptors.contains(ManagedEntityInterceptor.class.getName()))
{
interceptors.add(ManagedEntityInterceptor.class.getName());
}
}
}