/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.metadata;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.jboss.deployment.DeploymentException;
/**
* The top level meta data from the jboss.xml and ejb-jar.xml descriptor.
*
* @author Sebastien Alborini
* @author Peter Antman
* @author Scott Stark
* @author Christian Riege
*
* @version $Revision: 1.29.2.3 $
*/
public class ApplicationMetaData
extends MetaData
{
public static final int EJB_1x = 1;
public static final int EJB_2x = 2;
private URL url;
// verion of the dtd used to create ejb-jar.xml
private int ejbVersion;
private ArrayList beans = new ArrayList();
/**
* List of relations in this application.
* Items are instance of RelationMetaData.
*/
private ArrayList relationships = new ArrayList();
private ArrayList securityRoles = new ArrayList();
private HashMap configurations = new HashMap();
private HashMap invokerBindings = new HashMap();
private HashMap resources = new HashMap();
private HashMap plugins = new HashMap();
/** The user defined JMX name for the EJBModule */
private String jmxName;
/** The security-domain value assigned to the application */
private String securityDomain;
/** The unauthenticated-principal value assigned to the application */
private String unauthenticatedPrincipal;
private boolean enforceEjbRestrictions;
public ApplicationMetaData(URL u)
{
url = u;
}
public ApplicationMetaData()
{
}
public URL getUrl()
{
return url;
}
public void setUrl(URL u)
{
url = u;
}
public boolean isEJB1x()
{
return ejbVersion == 1;
}
public boolean isEJB2x()
{
return ejbVersion == 2;
}
/**
*/
public Iterator getEnterpriseBeans()
{
return beans.iterator();
}
/**
* Get an EJB by its declared <ejb-name> tag
*
* @param ejbName EJB to return
*
* @return BeanMetaData pertaining to the given ejb-name,
* null if none found
*/
public BeanMetaData getBeanByEjbName( String ejbName )
{
Iterator iterator = getEnterpriseBeans();
while (iterator.hasNext())
{
BeanMetaData current = (BeanMetaData) iterator.next();
if( current.getEjbName().equals(ejbName) )
{
return current;
}
}
// not found
return null;
}
/**
* Get the container managed relations in this application.
* Items are instance of RelationMetaData.
*/
public Iterator getRelationships()
{
return relationships.iterator();
}
public Iterator getConfigurations()
{
return configurations.values().iterator();
}
public ConfigurationMetaData getConfigurationMetaDataByName(String name)
{
return (ConfigurationMetaData)configurations.get(name);
}
public Iterator getInvokerProxyBindings()
{
return invokerBindings.values().iterator();
}
public InvokerProxyBindingMetaData getInvokerProxyBindingMetaDataByName(
String name)
{
return (InvokerProxyBindingMetaData)invokerBindings.get(name);
}
public String getResourceByName(String name)
{
// if not found, the container will use default
return (String)resources.get(name);
}
public void addPluginData(String pluginName, Object pluginData)
{
plugins.put(pluginName, pluginData);
}
public Object getPluginData(String pluginName)
{
return plugins.get(pluginName);
}
public String getJmxName()
{
return jmxName;
}
public String getSecurityDomain()
{
return securityDomain;
}
public String getUnauthenticatedPrincipal()
{
return unauthenticatedPrincipal;
}
public boolean getEnforceEjbRestrictions()
{
return enforceEjbRestrictions;
}
/**
* Import data provided by ejb-jar.xml
*
* @throws DeploymentException When there was an error encountered
* while parsing ejb-jar.xml
*/
public void importEjbJarXml( Element element )
throws DeploymentException
{
// EJB version is determined by the doc type that was used to
// verify the ejb-jar.xml.
DocumentType docType = element.getOwnerDocument().getDoctype();
if( docType == null )
{
// No good, EJB 1.1/2.0 requires a DOCTYPE declaration
throw new DeploymentException( "ejb-jar.xml must define a " +
"valid DOCTYPE!" );
}
String publicId = docType.getPublicId();
if( publicId == null )
{
// We need a public Id
throw new DeploymentException( "The DOCTYPE declaration in " +
"ejb-jar.xml must define a PUBLIC id" );
}
// Check for a known public Id
if( publicId.startsWith(
"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0") )
{
ejbVersion = 2;
}
else if( publicId.startsWith(
"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1") )
{
ejbVersion = 1;
}
else
{
// Unknown
throw new DeploymentException( "Unknown PUBLIC id in " +
"ejb-jar.xml: " + publicId );
}
// find the beans
Element enterpriseBeans = getUniqueChild(element, "enterprise-beans");
// Entity Beans
HashMap schemaNameMap = new HashMap();
Iterator iterator = getChildrenByTagName(enterpriseBeans, "entity");
while (iterator.hasNext())
{
Element currentEntity = (Element)iterator.next();
EntityMetaData entityMetaData = new EntityMetaData(this);
try
{
entityMetaData.importEjbJarXml(currentEntity);
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in ejb-jar.xml " +
"for Entity Bean " + entityMetaData.getEjbName() + ": " +
e.getMessage());
}
// Ensure unique-ness of
String abstractSchemaName = entityMetaData.getAbstractSchemaName();
if( abstractSchemaName != null )
{
if( schemaNameMap.containsKey(abstractSchemaName) )
{
//
throw new DeploymentException( entityMetaData.getEjbName() +
": Duplicate abstract-schema name '" + abstractSchemaName +
"'. Already defined for Entity '" +
((EntityMetaData)schemaNameMap.get(abstractSchemaName)).getEjbName() + "'." );
}
schemaNameMap.put( abstractSchemaName, entityMetaData );
}
beans.add( entityMetaData );
}
// Session Beans
iterator = getChildrenByTagName(enterpriseBeans, "session");
while (iterator.hasNext())
{
Element currentSession = (Element)iterator.next();
SessionMetaData sessionMetaData = new SessionMetaData(this);
try
{
sessionMetaData.importEjbJarXml(currentSession);
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in ejb-jar.xml for " +
"Session Bean " + sessionMetaData.getEjbName() + ": " +
e.getMessage() );
}
beans.add(sessionMetaData);
}
// Message Driven Beans
iterator = getChildrenByTagName(enterpriseBeans, "message-driven");
while (iterator.hasNext())
{
Element currentMessageDriven = (Element)iterator.next();
MessageDrivenMetaData messageDrivenMetaData =
new MessageDrivenMetaData( this );
try
{
messageDrivenMetaData.importEjbJarXml( currentMessageDriven );
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in ejb-jar.xml for " +
"Message Driven Bean " +
messageDrivenMetaData.getEjbName() + ": " + e.getMessage());
}
beans.add(messageDrivenMetaData);
}
// Enforce unique-ness of declared ejb-name Elements
Set ejbNames = new HashSet();
Iterator beanIt = beans.iterator();
while( beanIt.hasNext() )
{
BeanMetaData bmd = (BeanMetaData)beanIt.next();
String beanName = bmd.getEjbName();
if( ejbNames.contains(beanName) )
{
throw new DeploymentException( "Duplicate definition of an " +
"EJB with name '" + beanName + "'." );
}
ejbNames.add( beanName );
}
// Relationships
Element relationshipsElement = getOptionalChild(element,
"relationships");
if(relationshipsElement != null)
{
// used to assure that a relationship name is not reused
Set relationNames = new HashSet();
iterator = getChildrenByTagName(relationshipsElement,
"ejb-relation");
while(iterator.hasNext())
{
Element relationElement = (Element)iterator.next();
RelationMetaData relationMetaData = new RelationMetaData();
try
{
relationMetaData.importEjbJarXml(relationElement);
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in ejb-jar.xml " +
"for relation " + relationMetaData.getRelationName() +
": " + e.getMessage() );
}
// if the relationship has a name, assure that it has not
// already been used
String relationName = relationMetaData.getRelationName();
if( relationName != null )
{
if( relationNames.contains(relationName) )
{
throw new DeploymentException("ejb-relation-name must " +
"be unique in ejb-jar.xml file: ejb-relation-name is " +
relationName );
}
relationNames.add( relationName );
}
relationships.add(relationMetaData);
}
}
// read the assembly descriptor (optional)
Element assemblyDescriptor = getOptionalChild( element,
"assembly-descriptor");
if( assemblyDescriptor != null )
{
// set the security roles (optional)
iterator = getChildrenByTagName(assemblyDescriptor, "security-role");
while (iterator.hasNext())
{
Element securityRole = (Element)iterator.next();
try
{
String role = getElementContent( getUniqueChild(securityRole,
"role-name") );
securityRoles.add(role);
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in ejb-jar.xml " +
"for security-role: " + e.getMessage() );
}
}
// set the method permissions (optional)
iterator = getChildrenByTagName(assemblyDescriptor,
"method-permission");
try
{
while (iterator.hasNext())
{
Element methodPermission = (Element)iterator.next();
// Look for the unchecked element
Element unchecked = getOptionalChild(methodPermission,
"unchecked");
boolean isUnchecked = false;
Set roles = null;
if( unchecked != null )
{
isUnchecked = true;
}
else
{
// Get the role-name elements
roles = new HashSet();
Iterator rolesIterator = getChildrenByTagName(
methodPermission, "role-name");
while( rolesIterator.hasNext() )
{
roles.add(getElementContent(
(Element)rolesIterator.next()) );
}
if( roles.size() == 0 )
throw new DeploymentException("An unchecked " +
"element or one or more role-name elements " +
"must be specified in method-permission");
}
// find the methods
Iterator methods = getChildrenByTagName(methodPermission,
"method");
while (methods.hasNext())
{
// load the method
MethodMetaData method = new MethodMetaData();
method.importEjbJarXml((Element)methods.next());
if( isUnchecked )
{
method.setUnchecked();
}
else
{
method.setRoles(roles);
}
// give the method to the right bean
BeanMetaData bean = getBeanByEjbName(method.getEjbName());
if( bean == null )
{
throw new DeploymentException( method.getEjbName() +
" doesn't exist" );
}
bean.addPermissionMethod(method);
}
}
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in ejb-jar.xml, " +
"in method-permission: " + e.getMessage() );
}
// set the container transactions (optional)
iterator = getChildrenByTagName(assemblyDescriptor,
"container-transaction");
try
{
while (iterator.hasNext())
{
Element containerTransaction = (Element)iterator.next();
// find the type of the transaction
byte transactionType;
String type = getElementContent( getUniqueChild(
containerTransaction, "trans-attribute") );
if( type.equalsIgnoreCase("NotSupported") ||
type.equalsIgnoreCase("Not_Supported") )
{
transactionType = TX_NOT_SUPPORTED;
}
else if( type.equalsIgnoreCase("Supports") )
{
transactionType = TX_SUPPORTS;
}
else if( type.equalsIgnoreCase("Required") )
{
transactionType = TX_REQUIRED;
}
else if( type.equalsIgnoreCase("RequiresNew") ||
type.equalsIgnoreCase("Requires_New") )
{
transactionType = TX_REQUIRES_NEW;
}
else if( type.equalsIgnoreCase("Mandatory") )
{
transactionType = TX_MANDATORY;
}
else if( type.equalsIgnoreCase("Never") )
{
transactionType = TX_NEVER;
}
else
{
throw new DeploymentException( "invalid " +
" : " + type);
}
// find the methods
Iterator methods = getChildrenByTagName(
containerTransaction, "method" );
while (methods.hasNext())
{
// load the method
MethodMetaData method = new MethodMetaData();
method.importEjbJarXml((Element)methods.next());
method.setTransactionType(transactionType);
// give the method to the right bean
BeanMetaData bean = getBeanByEjbName(method.getEjbName());
if( bean == null )
{
throw new DeploymentException( "bean " +
method.getEjbName() + " doesn't exist" );
}
bean.addTransactionMethod(method);
}
}
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in ejb-jar.xml, " +
"in : " + e.getMessage());
}
// Get the exclude-list methods
Element excludeList = getOptionalChild(assemblyDescriptor,
"exclude-list");
if( excludeList != null )
{
iterator = getChildrenByTagName(excludeList, "method");
while (iterator.hasNext())
{
Element methodInf = (Element) iterator.next();
// load the method
MethodMetaData method = new MethodMetaData();
method.importEjbJarXml(methodInf);
method.setExcluded();
// give the method to the right bean
BeanMetaData bean = getBeanByEjbName(method.getEjbName());
if (bean == null)
{
throw new DeploymentException( "bean " +
method.getEjbName() + " doesn't exist" );
}
bean.addExcludedMethod(method);
}
}
}
}
public void importJbossXml(Element element)
throws DeploymentException
{
Iterator iterator;
// all the tags are optional
// Get the enforce-ejb-restrictions
Element enforce = getOptionalChild(element, "enforce-ejb-restrictions");
if( enforce != null )
{
String tmp = getElementContent(enforce);
enforceEjbRestrictions = Boolean.valueOf(tmp).booleanValue();
}
// Get any user defined JMX name
Element jmxNameElement = getOptionalChild(element,
"jmx-name");
if( jmxNameElement != null )
{
jmxName = getElementContent(jmxNameElement);
}
// Get the security domain name
Element securityDomainElement = getOptionalChild(element,
"security-domain");
if( securityDomainElement != null )
{
securityDomain = getElementContent(securityDomainElement);
}
// Get the unauthenticated-principal name
Element unauth = getOptionalChild(element,
"unauthenticated-principal");
if( unauth != null )
{
unauthenticatedPrincipal = getElementContent(unauth);
}
// find the invoker configurations
Element invokerConfs = getOptionalChild(element,
"invoker-proxy-bindings");
if (invokerConfs != null)
{
iterator = getChildrenByTagName(invokerConfs,
"invoker-proxy-binding");
while (iterator.hasNext())
{
Element invoker = (Element)iterator.next();
String invokerName = getElementContent(getUniqueChild(
invoker, "name"));
// find the configuration if it has already been defined
// (allow jboss.xml to modify a standard conf)
InvokerProxyBindingMetaData invokerMetaData =
getInvokerProxyBindingMetaDataByName(invokerName);
// create it if necessary
if (invokerMetaData == null)
{
invokerMetaData = new InvokerProxyBindingMetaData(invokerName);
invokerBindings.put(invokerName, invokerMetaData);
}
try
{
invokerMetaData.importJbossXml(invoker);
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in jboss.xml " +
"for invoker-proxy-binding " + invokerMetaData.getName() +
": " + e.getMessage() );
}
}
}
// find the container configurations (we need them first to use
// them in the beans)
Element confs = getOptionalChild(element, "container-configurations");
if (confs != null)
{
iterator = getChildrenByTagName(confs, "container-configuration");
while (iterator.hasNext())
{
Element conf = (Element)iterator.next();
String confName = getElementContent(getUniqueChild(conf,
"container-name"));
String parentConfName = conf.getAttribute("extends");
if( parentConfName != null && parentConfName.trim().length() == 0 )
{
parentConfName = null;
}
// Allow the configuration to inherit from a standard
// configuration. This is determined by looking for a
// configuration matching the name given by the extends
// attribute, or if extends was not specified, an
// existing configuration with the same.
ConfigurationMetaData configurationMetaData = null;
if( parentConfName != null )
{
configurationMetaData = getConfigurationMetaDataByName(
parentConfName);
if( configurationMetaData == null )
{
throw new DeploymentException( "Failed to find " +
"parent config=" + parentConfName );
}
// Make a copy of the existing configuration
configurationMetaData =
(ConfigurationMetaData) configurationMetaData.clone();
configurations.put( confName, configurationMetaData );
}
if( configurationMetaData == null )
{
configurationMetaData =
getConfigurationMetaDataByName(confName);
}
// Create a new configuration if none was found
if( configurationMetaData == null )
{
configurationMetaData = new ConfigurationMetaData(confName);
configurations.put(confName, configurationMetaData);
}
try
{
configurationMetaData.importJbossXml(conf);
} catch (DeploymentException e)
{
throw new DeploymentException( "Error in jboss.xml " +
"for container-configuration " +
configurationMetaData.getName() + ": " + e.getMessage());
}
}
}
// update the enterprise beans
Element entBeans = getOptionalChild(element, "enterprise-beans");
if( entBeans != null )
{
String ejbName = null;
try
{
// Entity Beans
iterator = getChildrenByTagName( entBeans, "entity" );
while( iterator.hasNext() )
{
Element bean = (Element) iterator.next();
ejbName = getElementContent(getUniqueChild(bean, "ejb-name"));
BeanMetaData beanMetaData = getBeanByEjbName(ejbName);
if (beanMetaData == null)
{
throw new DeploymentException("found in jboss.xml " +
"but not in ejb-jar.xml");
}
beanMetaData.importJbossXml(bean);
}
// Session Beans
iterator = getChildrenByTagName(entBeans, "session");
while (iterator.hasNext())
{
Element bean = (Element) iterator.next();
ejbName = getElementContent(getUniqueChild(bean, "ejb-name"));
BeanMetaData beanMetaData = getBeanByEjbName(ejbName);
if (beanMetaData == null)
{
throw new DeploymentException("found in jboss.xml " +
"but not in ejb-jar.xml");
}
beanMetaData.importJbossXml(bean);
}
// Message Driven Beans
iterator = getChildrenByTagName(entBeans, "message-driven");
while (iterator.hasNext())
{
Element bean = (Element) iterator.next();
ejbName = getElementContent(getUniqueChild(bean, "ejb-name"));
BeanMetaData beanMetaData = getBeanByEjbName(ejbName);
if (beanMetaData == null)
{
throw new DeploymentException("found in jboss.xml " +
"but not in ejb-jar.xml");
}
beanMetaData.importJbossXml(bean);
}
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in jboss.xml for " +
"Bean " + ejbName + ": " + e.getMessage() );
}
}
// set the resource managers
Element resmans = getOptionalChild(element, "resource-managers");
if( resmans != null )
{
iterator = getChildrenByTagName(resmans, "resource-manager");
try
{
while (iterator.hasNext())
{
Element resourceManager = (Element)iterator.next();
String resName = getElementContent(getUniqueChild(
resourceManager, "res-name"));
String jndi = getElementContent(getOptionalChild(
resourceManager, "res-jndi-name"));
String url = getElementContent(getOptionalChild(
resourceManager, "res-url"));
if( jndi != null && url == null )
{
resources.put(resName, jndi);
}
else if( jndi == null && url != null )
{
resources.put(resName, url);
}
else
{
throw new DeploymentException( resName +
" : expected res-url or res-jndi-name tag" );
}
}
}
catch (DeploymentException e)
{
throw new DeploymentException( "Error in jboss.xml, in " +
"resource-manager: " + e.getMessage() );
}
}
}
}
/*
vim:ts=3:sw=3:et
*/