package org.jboss.metadata;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import org.jboss.deployment.DeploymentException;
import org.jboss.invocation.InvocationType;
import org.jboss.mx.util.ObjectNameFactory;
import org.jboss.security.AnybodyPrincipal;
import org.jboss.security.NobodyPrincipal;
import org.jboss.security.SimplePrincipal;
import org.jboss.webservice.metadata.ServiceRefMetaData;
import org.w3c.dom.Element;
import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
public abstract class BeanMetaData
extends MetaData
{
public static final char SESSION_TYPE = 'S';
public static final char ENTITY_TYPE = 'E';
public static final char MDB_TYPE = 'M';
public static final String LOCAL_INVOKER_PROXY_BINDING = "LOCAL";
private ApplicationMetaData application;
private String ejbName;
private String homeClass;
private String remoteClass;
private String localHomeClass;
private String localClass;
protected String serviceEndpointClass;
private String ejbClass;
protected char beanType;
protected boolean containerManagedTx = true;
private ArrayList environmentEntries = new ArrayList();
private HashMap ejbReferences = new HashMap();
private HashMap ejbLocalReferences = new HashMap();
private HashMap serviceReferences = new HashMap();
private ArrayList securityRoleReferences = new ArrayList();
private SecurityIdentityMetaData securityIdentity = null;
private HashMap resourceReferences = new HashMap();
private HashMap resourceEnvReferences = new HashMap();
private HashMap messageDestinationReferences = new HashMap();
private ArrayList methodAttributes = new ArrayList();
private ConcurrentReaderHashMap cachedMethodAttributes = new ConcurrentReaderHashMap();
private ArrayList permissionMethods = new ArrayList();
private ArrayList transactionMethods = new ArrayList();
private ConcurrentReaderHashMap methodTx = new ConcurrentReaderHashMap();
private ArrayList excludedMethods = new ArrayList();
protected HashMap invokerBindings = null;
private ClusterConfigMetaData clusterConfig = null;
private String jndiName;
private String localJndiName;
protected String configurationName;
private ConfigurationMetaData configuration;
private String securityProxy;
protected boolean clustered = false;
protected boolean callByValue = false;
private Collection depends = new LinkedList();
private IorSecurityConfigMetaData iorSecurityConfig;
protected EjbPortComponentMetaData portComponent;
private boolean exceptionRollback = false;
public BeanMetaData(ApplicationMetaData app, char beanType)
{
this.application = app;
this.beanType = beanType;
}
public boolean isSession()
{
return beanType == SESSION_TYPE;
}
public boolean isMessageDriven()
{
return beanType == MDB_TYPE;
}
public boolean isEntity()
{
return beanType == ENTITY_TYPE;
}
public String getHome()
{
return homeClass;
}
public String getRemote()
{
return remoteClass;
}
public String getLocalHome()
{
return localHomeClass;
}
public String getLocal()
{
return localClass;
}
public String getServiceEndpoint()
{
return serviceEndpointClass;
}
public EjbPortComponentMetaData getPortComponent()
{
return portComponent;
}
public String getEjbClass()
{
return ejbClass;
}
public String getEjbName()
{
return ejbName;
}
public boolean isContainerManagedTx()
{
return containerManagedTx;
}
public boolean isBeanManagedTx()
{
return !containerManagedTx;
}
public Iterator getEjbReferences()
{
return ejbReferences.values().iterator();
}
public Iterator getEjbLocalReferences()
{
return ejbLocalReferences.values().iterator();
}
protected abstract void defaultInvokerBindings();
public Iterator getInvokerBindings()
{
if (invokerBindings == null)
{
String[] defaultNames = configuration.getInvokers();
if (defaultNames.length > 0)
{
invokerBindings = new HashMap();
for (int count = 0; count < defaultNames.length; count++)
{
invokerBindings.put(defaultNames[count], getJndiName());
}
}
else
{
defaultInvokerBindings();
}
}
return invokerBindings.keySet().iterator();
}
public String getInvokerBinding(String invokerName)
{
if (invokerBindings == null)
{
defaultInvokerBindings();
}
return (String) invokerBindings.get(invokerName);
}
public EjbRefMetaData getEjbRefByName(String name)
{
return (EjbRefMetaData) ejbReferences.get(name);
}
public EjbLocalRefMetaData getEjbLocalRefByName(String name)
{
return (EjbLocalRefMetaData) ejbLocalReferences.get(name);
}
public Iterator getEnvironmentEntries()
{
return environmentEntries.iterator();
}
public Iterator getSecurityRoleReferences()
{
return securityRoleReferences.iterator();
}
public Iterator getResourceReferences()
{
return resourceReferences.values().iterator();
}
public Iterator getResourceEnvReferences()
{
return resourceEnvReferences.values().iterator();
}
public Iterator getMessageDestinationReferences()
{
return messageDestinationReferences.values().iterator();
}
public HashMap getServiceReferences()
{
return serviceReferences;
}
public String getJndiName()
{
if (jndiName == null)
{
jndiName = ejbName;
}
return jndiName;
}
public String getLocalJndiName()
{
if (localJndiName == null)
{
localJndiName = "local/" + ejbName + '@' + System.identityHashCode(ejbName);
}
return localJndiName;
}
public String getContainerObjectNameJndiName()
{
return getHome() != null ? getJndiName() : getLocalJndiName();
}
public String getConfigurationName()
{
if (configurationName == null)
{
configurationName = getDefaultConfigurationName();
}
return configurationName;
}
public ConfigurationMetaData getContainerConfiguration()
{
if (configuration == null)
{
String configName = getConfigurationName();
configuration = application.getConfigurationMetaDataByName(configName);
if (configuration == null)
throw new IllegalStateException("Container config not found " + configName);
}
return configuration;
}
public String getSecurityProxy()
{
return securityProxy;
}
public SecurityIdentityMetaData getSecurityIdentityMetaData()
{
return securityIdentity;
}
public ApplicationMetaData getApplicationMetaData()
{
return application;
}
public abstract String getDefaultConfigurationName();
public Iterator getTransactionMethods()
{
return transactionMethods.iterator();
}
public Iterator getPermissionMethods()
{
return permissionMethods.iterator();
}
public Iterator getExcludedMethods()
{
return excludedMethods.iterator();
}
public void addTransactionMethod(MethodMetaData method)
{
transactionMethods.add(method);
}
public void addPermissionMethod(MethodMetaData method)
{
if (method.isUnchecked())
{
permissionMethods.add(0, method);
}
else
{
permissionMethods.add(method);
}
}
public void addExcludedMethod(MethodMetaData method)
{
excludedMethods.add(method);
}
public byte getMethodTransactionType(String methodName, Class[] params, InvocationType iface)
{
byte result = TX_UNKNOWN;
MethodMetaData bestMatch = null;
Iterator iterator = getTransactionMethods();
while (iterator.hasNext())
{
MethodMetaData m = (MethodMetaData) iterator.next();
if (m.patternMatches(methodName, params, iface)) {
if (bestMatch == null)
{
bestMatch = m;
}
else
{
if (bestMatch.getMethodName().equals("*"))
{
bestMatch = m;
}
if (m.getMethodParams().length > 0)
{
bestMatch = m;
break;
}
}
}
}
if (bestMatch != null)
{
result = bestMatch.getTransactionType();
}
return result;
}
public byte getTransactionMethod(Method m, InvocationType iface)
{
if (m == null)
return MetaData.TX_SUPPORTS;
Byte b = (Byte)methodTx.get(m);
if (b != null) return b.byteValue();
byte result = getMethodTransactionType(m.getName(), m.getParameterTypes(), iface);
if (result == MetaData.TX_UNKNOWN)
result = MetaData.TX_REQUIRED;
methodTx.put(m, new Byte(result));
return result;
}
public Collection getDepends()
{
Collection allDepends = new LinkedList(depends);
allDepends.addAll(getContainerConfiguration().getDepends());
return allDepends;
}
private MethodAttributes methodAttributesForMethod(String methodName)
{
if (methodName == null)
methodName = "*null*";
MethodAttributes ma =
(MethodAttributes) cachedMethodAttributes.get(methodName);
if (ma == null)
{
Iterator iterator = methodAttributes.iterator();
while (iterator.hasNext() && ma == null)
{
ma = (MethodAttributes) iterator.next();
if (!ma.patternMatches(methodName))
{
ma = null;
}
}
if (ma == null)
{
ma = MethodAttributes.kDefaultMethodAttributes;
}
cachedMethodAttributes.put(methodName, ma);
}
return ma;
}
public boolean isMethodReadOnly(String methodName)
{
return methodAttributesForMethod(methodName).readOnly;
}
public boolean isMethodReadOnly(Method method)
{
if (method == null)
{
return false;
}
return methodAttributesForMethod(method.getName()).readOnly;
}
public int getTransactionTimeout(String methodName)
{
return methodAttributesForMethod(methodName).txTimeout;
}
public int getTransactionTimeout(Method method)
{
if (method == null)
return 0;
return getTransactionTimeout(method.getName());
}
public Set getMethodPermissions(String methodName, Class[] params,
InvocationType iface)
{
Set result = new HashSet();
Iterator iterator = getExcludedMethods();
while (iterator.hasNext())
{
MethodMetaData m = (MethodMetaData) iterator.next();
if (m.patternMatches(methodName, params, iface))
{
result.add(NobodyPrincipal.NOBODY_PRINCIPAL);
return result;
}
}
iterator = getPermissionMethods();
while (iterator.hasNext())
{
MethodMetaData m = (MethodMetaData) iterator.next();
if (m.patternMatches(methodName, params, iface))
{
if (m.isUnchecked())
{
result.clear();
result.add(AnybodyPrincipal.ANYBODY_PRINCIPAL);
break;
}
else
{
Iterator rolesIterator = m.getRoles().iterator();
while (rolesIterator.hasNext())
{
String roleName = (String) rolesIterator.next();
result.add(new SimplePrincipal(roleName));
}
}
}
}
if( this.isExcludeMissingMethods() == false )
{
if (result.isEmpty())
{
result.add(AnybodyPrincipal.ANYBODY_PRINCIPAL);
}
}
return result;
}
public boolean hasMethodPermission(String methodName, Class[] params,
InvocationType iface)
{
Iterator iterator = getExcludedMethods();
while (iterator.hasNext())
{
MethodMetaData m = (MethodMetaData) iterator.next();
if (m.patternMatches(methodName, params, iface))
{
return true;
}
}
iterator = getPermissionMethods();
while (iterator.hasNext())
{
MethodMetaData m = (MethodMetaData) iterator.next();
if (m.patternMatches(methodName, params, iface))
{
return true;
}
}
return false;
}
public boolean isClustered()
{
return this.clustered;
}
public boolean isCallByValue()
{
return callByValue;
}
public boolean isExcludeMissingMethods()
{
return application.isExcludeMissingMethods();
}
public ClusterConfigMetaData getClusterConfigMetaData()
{
if (clusterConfig == null)
{
clusterConfig = getContainerConfiguration().getClusterConfigMetaData();
if (clusterConfig == null)
{
clusterConfig = new ClusterConfigMetaData();
}
clusterConfig.init(this);
}
return this.clusterConfig;
}
public IorSecurityConfigMetaData getIorSecurityConfigMetaData()
{
return iorSecurityConfig;
}
public boolean getExceptionRollback()
{
return exceptionRollback;
}
public void importEjbJarXml(Element element)
throws DeploymentException
{
ejbName = getElementContent(getUniqueChild(element, "ejb-name"));
if (isMessageDriven() == false)
{
homeClass = getElementContent(getOptionalChild(element, "home"));
remoteClass = getElementContent(getOptionalChild(element, "remote"));
localHomeClass = getElementContent(getOptionalChild(element,
"local-home"));
localClass = getElementContent(getOptionalChild(element, "local"));
}
ejbClass = getElementContent(getUniqueChild(element, "ejb-class"));
Iterator iterator = getChildrenByTagName(element, "env-entry");
while (iterator.hasNext())
{
Element envEntry = (Element) iterator.next();
EnvEntryMetaData envEntryMetaData = new EnvEntryMetaData();
envEntryMetaData.importEjbJarXml(envEntry);
environmentEntries.add(envEntryMetaData);
}
iterator = getChildrenByTagName(element, "ejb-ref");
while (iterator.hasNext())
{
Element ejbRef = (Element) iterator.next();
EjbRefMetaData ejbRefMetaData = new EjbRefMetaData();
ejbRefMetaData.importEjbJarXml(ejbRef);
ejbReferences.put(ejbRefMetaData.getName(), ejbRefMetaData);
}
iterator = getChildrenByTagName(element, "ejb-local-ref");
while (iterator.hasNext())
{
Element ejbLocalRef = (Element) iterator.next();
EjbLocalRefMetaData ejbLocalRefMetaData = new EjbLocalRefMetaData();
ejbLocalRefMetaData.importEjbJarXml(ejbLocalRef);
ejbLocalReferences.put(ejbLocalRefMetaData.getName(),
ejbLocalRefMetaData);
}
iterator = MetaData.getChildrenByTagName(element, "service-ref");
while (iterator.hasNext())
{
Element serviceRef = (Element) iterator.next();
ServiceRefMetaData refMetaData = new ServiceRefMetaData(application.getResourceCl());
refMetaData.importStandardXml(serviceRef);
serviceReferences.put(refMetaData.getServiceRefName(), refMetaData);
}
iterator = getChildrenByTagName(element, "security-role-ref");
while (iterator.hasNext())
{
Element secRoleRef = (Element) iterator.next();
SecurityRoleRefMetaData securityRoleRefMetaData = new SecurityRoleRefMetaData();
securityRoleRefMetaData.importEjbJarXml(secRoleRef);
securityRoleReferences.add(securityRoleRefMetaData);
}
Element securityIdentityElement = getOptionalChild(element,
"security-identity");
if (securityIdentityElement != null)
{
securityIdentity = new SecurityIdentityMetaData();
securityIdentity.importEjbJarXml(securityIdentityElement);
}
iterator = getChildrenByTagName(element, "resource-ref");
while (iterator.hasNext())
{
Element resourceRef = (Element) iterator.next();
ResourceRefMetaData resourceRefMetaData = new ResourceRefMetaData();
resourceRefMetaData.importEjbJarXml(resourceRef);
resourceReferences.put(resourceRefMetaData.getRefName(),
resourceRefMetaData);
}
iterator = getChildrenByTagName(element, "resource-env-ref");
while (iterator.hasNext())
{
Element resourceRef = (Element) iterator.next();
ResourceEnvRefMetaData refMetaData = new ResourceEnvRefMetaData();
refMetaData.importEjbJarXml(resourceRef);
resourceEnvReferences.put(refMetaData.getRefName(), refMetaData);
}
iterator = getChildrenByTagName(element, "message-destination-ref");
while (iterator.hasNext())
{
Element messageDestinationRef = (Element) iterator.next();
MessageDestinationRefMetaData messageDestinationRefMetaData = new MessageDestinationRefMetaData();
messageDestinationRefMetaData.importEjbJarXml(messageDestinationRef);
messageDestinationReferences.put(messageDestinationRefMetaData.getRefName(), messageDestinationRefMetaData);
}
}
public void importJbossXml(Element element) throws DeploymentException
{
jndiName = getElementContent(getOptionalChild(element, "jndi-name"));
localJndiName = getElementContent(getOptionalChild(element, "local-jndi-name"));
String callByValueElt = getElementContent(getOptionalChild(element, "call-by-value"), (callByValue ? "True" : "False"));
callByValue = callByValueElt.equalsIgnoreCase("True");
configurationName = getElementContent(getOptionalChild(element, "configuration-name"));
if (configurationName != null && getApplicationMetaData().getConfigurationMetaDataByName(configurationName) == null)
{
throw new DeploymentException("configuration '" + configurationName + "' not found in standardjboss.xml or jboss.xml");
}
securityProxy = getElementContent(getOptionalChild(element, "security-proxy"), securityProxy);
exceptionRollback = MetaData.getOptionalChildBooleanContent(element, "exception-on-rollback", false);
Iterator iterator = getChildrenByTagName(element, "resource-ref");
while (iterator.hasNext())
{
Element resourceRef = (Element) iterator.next();
String resRefName = getElementContent(getUniqueChild(resourceRef, "res-ref-name"));
ResourceRefMetaData resourceRefMetaData = (ResourceRefMetaData) resourceReferences.get(resRefName);
if (resourceRefMetaData == null)
{
throw new DeploymentException("resource-ref " + resRefName + " found in jboss.xml but not in ejb-jar.xml");
}
resourceRefMetaData.importJbossXml(resourceRef);
}
iterator = getChildrenByTagName(element, "resource-env-ref");
while (iterator.hasNext())
{
Element resourceRef = (Element) iterator.next();
String resRefName = getElementContent(getUniqueChild(resourceRef, "resource-env-ref-name"));
ResourceEnvRefMetaData refMetaData = (ResourceEnvRefMetaData) resourceEnvReferences.get(resRefName);
if (refMetaData == null)
{
throw new DeploymentException("resource-env-ref " + resRefName + " found in jboss.xml but not in ejb-jar.xml");
}
refMetaData.importJbossXml(resourceRef);
}
iterator = getChildrenByTagName(element, "message-destination-ref");
while (iterator.hasNext())
{
Element messageDestinationRef = (Element) iterator.next();
String messageDestinationRefName = getElementContent(getUniqueChild(messageDestinationRef, "message-destination-ref-name"));
MessageDestinationRefMetaData messageDestinationRefMetaData = (MessageDestinationRefMetaData) messageDestinationReferences.get(messageDestinationRefName);
if (messageDestinationRefMetaData == null)
throw new DeploymentException("message-destination-ref " + messageDestinationRefName + " found in jboss.xml but not in ejb-jar.xml");
messageDestinationRefMetaData.importJbossXml(messageDestinationRef);
}
iterator = getChildrenByTagName(element, "ejb-ref");
while (iterator.hasNext())
{
Element ejbRef = (Element) iterator.next();
String ejbRefName = getElementContent(getUniqueChild(ejbRef, "ejb-ref-name"));
EjbRefMetaData ejbRefMetaData = getEjbRefByName(ejbRefName);
if (ejbRefMetaData == null)
{
throw new DeploymentException("ejb-ref " + ejbRefName + " found in jboss.xml but not in ejb-jar.xml");
}
ejbRefMetaData.importJbossXml(ejbRef);
}
iterator = getChildrenByTagName(element, "ejb-local-ref");
while (iterator.hasNext())
{
Element ejbLocalRef = (Element) iterator.next();
String ejbLocalRefName = getElementContent(getUniqueChild(ejbLocalRef, "ejb-ref-name"));
EjbLocalRefMetaData ejbLocalRefMetaData = getEjbLocalRefByName(ejbLocalRefName);
if (ejbLocalRefMetaData == null)
{
throw new DeploymentException("ejb-local-ref " + ejbLocalRefName + " found in jboss.xml but not in ejb-jar.xml");
}
ejbLocalRefMetaData.importJbossXml(ejbLocalRef);
}
iterator = MetaData.getChildrenByTagName(element, "service-ref");
while (iterator.hasNext())
{
Element serviceRef = (Element) iterator.next();
String serviceRefName = MetaData.getUniqueChildContent(serviceRef, "service-ref-name");
ServiceRefMetaData refMetaData = (ServiceRefMetaData)serviceReferences.get(serviceRefName);
if (refMetaData == null)
{
throw new DeploymentException("service-ref " + serviceRefName + " found in jboss.xml but not in ejb-jar.xml");
}
refMetaData.importJBossXml(serviceRef);
}
Element securityIdentityElement = getOptionalChild(element, "security-identity");
if (securityIdentityElement != null)
{
if( securityIdentity == null )
throw new DeploymentException(ejbName+", security-identity in jboss.xml has no match in ejb-jar.xml");
String runAsPrincipal = getElementContent(getUniqueChild(securityIdentityElement,
"run-as-principal"), securityIdentity.getRunAsPrincipalName());
securityIdentity.setRunAsPrincipalName(runAsPrincipal);
}
Element mas = getOptionalChild(element, "method-attributes");
if (mas != null)
{
iterator = getChildrenByTagName(mas, "method");
while (iterator.hasNext())
{
MethodAttributes ma = new MethodAttributes();
Element maNode = (Element) iterator.next();
ma.pattern = getElementContent(getUniqueChild(maNode, "method-name"));
ma.readOnly = getOptionalChildBooleanContent(maNode, "read-only");
ma.idempotent = getOptionalChildBooleanContent(maNode, "idempotent");
String txTimeout = getOptionalChildContent(maNode, "transaction-timeout");
try
{
if( txTimeout != null && txTimeout.length() > 0 )
ma.txTimeout = Integer.parseInt(txTimeout);
}
catch (Exception ignore)
{
log.debug("Ignoring transaction-timeout '" + txTimeout + "'", ignore);
}
methodAttributes.add(ma);
}
}
Element inv = getOptionalChild(element, "invoker-bindings");
if (inv != null)
{
iterator = getChildrenByTagName(inv, "invoker");
invokerBindings = new HashMap();
while (iterator.hasNext())
{
Element node = (Element) iterator.next();
String invokerBindingName = getUniqueChildContent(node, "invoker-proxy-binding-name");
String jndiBinding = getOptionalChildContent(node, "jndi-name");
if (jndiBinding == null)
{
jndiBinding = getJndiName(); }
invokerBindings.put(invokerBindingName, jndiBinding);
Iterator ejbrefiterator = getChildrenByTagName(node, "ejb-ref");
while (ejbrefiterator.hasNext())
{
Element ejbRef = (Element) ejbrefiterator.next();
String ejbRefName = getElementContent(getUniqueChild(ejbRef, "ejb-ref-name"));
EjbRefMetaData ejbRefMetaData = getEjbRefByName(ejbRefName);
if (ejbRefMetaData == null)
{
throw new DeploymentException("ejb-ref " + ejbRefName + " found in jboss.xml but not in ejb-jar.xml");
}
ejbRefMetaData.importJbossXml(invokerBindingName, ejbRef);
}
}
}
String clusteredElt = getElementContent(getOptionalChild(element, "clustered"), (clustered ? "True" : "False"));
clustered = clusteredElt.equalsIgnoreCase("True");
Element clusterConfigElement = getOptionalChild(element, "cluster-config");
if (clusterConfigElement != null)
{
this.clusterConfig = new ClusterConfigMetaData();
clusterConfig.init(this);
clusterConfig.importJbossXml(clusterConfigElement);
}
for (Iterator dependsElements = getChildrenByTagName(element, "depends"); dependsElements.hasNext();)
{
Element dependsElement = (Element) dependsElements.next();
String dependsName = getElementContent(dependsElement);
depends.add(ObjectNameFactory.create(dependsName));
}
Element iorSecurityConfigEl = getOptionalChild(element, "ior-security-config");
if(iorSecurityConfigEl != null)
{
iorSecurityConfig = new IorSecurityConfigMetaData(iorSecurityConfigEl);
}
}
}