/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.metadata;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
import org.w3c.dom.Element;
import org.jboss.deployment.DeploymentException;
import org.jboss.invocation.InvocationType;
/** The combination of the method-permission, container-transaction
*
*
* The method-permission element specifies that one or more security
* roles are allowed to invoke one or more enterprise bean methods. The
* method-permission element consists of an optional description, a list
* of security role names, or an indicator to specify that the methods
* are not to be checked for authorization, and a list of method elements.
* The security roles used in the method-permission element must be
* defined in the security-role element of the deployment descriptor,
* and the methods must be methods defined in the enterprise bean’s component
* and/or home interfaces.
*
*
* The container-transaction element specifies how the container must
* manage transaction scopes for the enterprise bean’s method invocations.
* The element consists of an optional description, a list of
* method elements, and a transaction attribute. The transaction
* attribute is to be applied to all the specified methods.
*
*
* @author Sebastien Alborini
* @author Scott Stark.
* @version $Revision: 57209 $
*/
public class MethodMetaData extends MetaData
{
// Constants -----------------------------------------------------
// These method interface contstants are compatible with the Invocation.XXX values
public static final int ANY_METHOD = -1;
public static String HOME_TYPE = "Home";
public static String LOCAL_HOME_TYPE = "LocalHome";
public static String REMOTE_TYPE = "Remote";
public static String LOCAL_TYPE = "Local";
public static String SERVICE_ENDPOINT_TYPE = "ServiceEndpoint";
private static final ArrayList EMPTY_PARAM_LIST = new ArrayList();
// Attributes ----------------------------------------------------
/** The method-name element contains a name of an enterprise bean method,
* or the asterisk (*) character. The asterisk is used when the element
* denotes all the methods of an enterprise bean’s component and home
* interfaces.
*/
private String methodName;
/** The ejb-name value the method applies to.
*/
private String ejbName;
/** The method-intf element allows a method element to differentiate
* between the methods with the same name and signature that are multiply
* defined across the home and component interfaces (e.g., in both an
* enterprise bean’s remote and local interfaces, or in both an enter-prise
* bean’s home and remote interfaces, etc.)
* The method-intf element must be one of the following:
* Home
* Remote
* LocalHome
* Local
* ServiceEndpoint
*/
private boolean intf = false;
/** One of: InvocationType
*/
private InvocationType methodType = null;
private boolean param = false;
/** The unchecked element specifies that a method is not checked for
* authorization by the container prior to invocation of the method.
* Used in: method-permission
*/
private boolean unchecked = false;
/** The exclude-list element defines a set of methods which the Assembler
* marks to be uncallable. It contains one or more methods. If the method
* permission relation contains methods that are in the exclude list, the
* Deployer should consider those methods to be uncallable.
*/
private boolean excluded = false;
/** The method-params element contains a list of the fully-qualified Java
* type names of the method parameters.
*/
private ArrayList paramList = EMPTY_PARAM_LIST;
/** The trans-attribute element specifies how the container must manage
* the transaction boundaries when delegating a method invocation to an
* enterprise bean’s business method.
* The value of trans-attribute must be one of the following:
* NotSupported
* Supports
* Required
* RequiresNew
* Mandatory
* Never
*/
private byte transactionType;
/** Set of the allowed role names */
private Set roles = new HashSet();
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
public MethodMetaData()
{
}
// Public --------------------------------------------------------
public String getMethodName()
{
return methodName;
}
public String getEjbName()
{
return ejbName;
}
public boolean isHomeMethod()
{
return methodType == InvocationType.HOME;
}
public boolean isRemoteMethod()
{
return methodType == InvocationType.REMOTE;
}
public boolean isLocalHomeMethod()
{
return methodType == InvocationType.LOCALHOME;
}
public boolean isLocalMethod()
{
return methodType == InvocationType.LOCAL;
}
public boolean isServiceEndpointMethod()
{
return methodType == InvocationType.SERVICE_ENDPOINT;
}
/** Return the interface type name.
*
* @return one of "Home", "LocalHome", "Remote", "Local", "ServiceEndpoint",
* or null if no interface was specified.
*/
public String getInterfaceType()
{
String type = null;
if( isHomeMethod() )
type = HOME_TYPE;
if( isLocalHomeMethod() )
type = LOCAL_HOME_TYPE;
if( isRemoteMethod() )
type = REMOTE_TYPE;
if( isLocalMethod() )
type = LOCAL_TYPE;
if( isServiceEndpointMethod() )
type = SERVICE_ENDPOINT_TYPE;
return type;
}
public boolean isUnchecked()
{
return unchecked;
}
public boolean isExcluded()
{
return excluded;
}
public boolean isIntfGiven()
{
return intf;
}
public boolean isParamGiven()
{
return param;
}
/** The method param type names.
* @return
*/
public Iterator getParams()
{
return paramList.iterator();
}
/** The
*
* @return An array of the method parameter type names
*/
public String[] getMethodParams()
{
String[] params = new String[paramList.size()];
paramList.toArray(params);
return params;
}
public byte getTransactionType()
{
return transactionType;
}
public void setTransactionType(byte type)
{
transactionType = type;
}
public Set getRoles()
{
return roles;
}
public void setRoles(Set perm)
{
roles = perm;
}
public void setUnchecked()
{
unchecked = true;
}
public void setExcluded()
{
excluded = true;
}
public boolean patternMatches(String name, Class[] arg, InvocationType iface)
{
return patternMatches(name, getClassNames(arg), iface);
}
public boolean patternMatches(String name, String[] arg, InvocationType iface)
{
// the wildcard matches everything
if (getMethodName().equals("*"))
{
if (methodType != null && methodType != iface)
return false;
return true;
}
if (getMethodName().equals(name) == false)
{
// different names -> no
return false;
}
else
{
// we have the same name, next check the interface type
if (methodType != null && methodType != iface)
return false;
if (isParamGiven() == false)
{
// no param given in descriptor -> ok
return true;
}
else
{
// we *have* to check the parameters
return sameParams(arg);
}
}
}
/**
* @param a method element
*/
public void importEjbJarXml(Element element) throws DeploymentException
{
methodName = getElementContent(getUniqueChild(element, "method-name"));
ejbName = getElementContent(getUniqueChild(element, "ejb-name"));
Element intfElement = getOptionalChild(element, "method-intf");
if (intfElement != null)
{
intf = true;
String methodIntf = getElementContent(intfElement);
if (methodIntf.equals("Home"))
{
methodType = InvocationType.HOME;
}
else if (methodIntf.equals("Remote"))
{
methodType = InvocationType.REMOTE;
}
else if (methodIntf.equals("LocalHome"))
{
methodType = InvocationType.LOCALHOME;
}
else if (methodIntf.equals("Local"))
{
methodType = InvocationType.LOCAL;
}
else if (methodIntf.equals("ServiceEndpoint"))
{
methodType = InvocationType.SERVICE_ENDPOINT;
}
else
{
throw new DeploymentException("method-intf tag should be one of: 'Home', 'Remote', 'LocalHome', 'Local', 'ServiceEndpoint'");
}
}
Element paramsElement = getOptionalChild(element, "method-params");
if (paramsElement != null)
{
param = true;
paramList = new ArrayList();
Iterator paramsIterator = getChildrenByTagName(paramsElement, "method-param");
while (paramsIterator.hasNext())
{
paramList.add(getElementContent((Element) paramsIterator.next()));
}
}
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
private static String[] getClassNames(Class[] source)
{
String out[] = new String[source.length];
for (int i = 0; i < out.length; i++)
{
String brackets = "";
Class cls = source[i];
while (cls.isArray())
{
brackets += "[]";
cls = cls.getComponentType();
}
out[i] = cls.getName() + brackets;
}
return out;
}
private boolean sameParams(String[] arg)
{
if (arg.length != paramList.size()) return false;
for (int i = 0; i < arg.length; i++)
if (!arg[i].equals(paramList.get(i)))
return false;
return true;
}
// Inner classes -------------------------------------------------
}