/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, 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.verifier.strategy;
// $Id: EJBVerifier11.java 81030 2008-11-14 12:59:42Z dimitris@jboss.org $
import org.jboss.metadata.EntityMetaData;
import org.jboss.metadata.SessionMetaData;
import org.jboss.verifier.Section;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Iterator;
/**
* Concrete implementation of the <code>VerificationStrategy</code> interface.
* This class implements the verification of both session and entity beans for
* Enterprise JavaBeans v1.1 specification.
*
* For more detailed documentation, refer to the
* <a href="http://java.sun.com/products/ejb/docs.html">Enterprise JavaBeans v1.1, Final Release</a>
*
* @see org.jboss.verifier.strategy.AbstractVerifier
*
* @author <a href="mailto:juha.lindfors@jboss.org">Juha Lindfors</a>
* @author Aaron Mulder (ammulder@alumni.princeton.edu)
* @author Vinay Menon (menonv@cpw.co.uk)
* @author Thomas.Diesler@jboss.org
*
* @version $Revision: 81030 $
* @since JDK 1.3
*/
public class EJBVerifier11 extends AbstractVerifier
{
/**
* Constructs the verifier object.
*
* @param context context for application information
*/
public EJBVerifier11(VerificationContext context)
{
super(context);
}
public String getMessageBundle()
{
return "EJB11Messages.properties";
}
/***********************************************************************
*
* IMPLEMENTS VERIFICATION STRATEGY INTERFACE
*
************************************************************************/
/**
* Verifies the session bean class, home interface and remote interface
* against the EJB 1.1 specification.
*
* @param session XML metadata of the session bean
*/
public void checkSession(SessionMetaData session)
{
boolean beanVerified = false;
boolean homeVerified = false;
boolean remoteVerified = false;
beanVerified = verifySessionBean(session);
homeVerified = verifySessionHome(session);
remoteVerified = verifySessionRemote(session);
if (beanVerified && homeVerified && remoteVerified)
{
/*
* Verification for this session bean done. Fire the event
* to tell listeneres everything is ok.
*/
fireBeanVerifiedEvent(session);
}
}
/**
* Verifies the entity bean class, home interface, remote interface and
* primary key class against the EJB 1.1 specification.
*
* @param entity XML metadata of the session bean
*/
public void checkEntity(EntityMetaData entity)
{
boolean pkVerified = false;
boolean beanVerified = false;
boolean homeVerified = false;
boolean remoteVerified = false;
beanVerified = verifyEntityBean(entity);
homeVerified = verifyEntityHome(entity);
remoteVerified = verifyEntityRemote(entity);
pkVerified = verifyPrimaryKey(entity);
if (beanVerified && homeVerified && remoteVerified && pkVerified)
{
/*
* Verification for this entity bean done. Fire the event
* to tell listeneres everything is ok.
*/
fireBeanVerifiedEvent(entity);
}
}
public boolean isCreateMethod(Method m)
{
return m.getName().equals(CREATE_METHOD);
}
public boolean isEjbCreateMethod(Method m)
{
return m.getName().equals(EJB_CREATE_METHOD);
}
/*
*****************************************************************************
*
* VERIFY SESSION BEAN HOME INTERFACE
*
*****************************************************************************
*/
/**
* Verifies the session bean home interface against the EJB 1.1
* specification.
*
* @param session XML metadata of the session bean
*/
private boolean verifySessionHome(SessionMetaData session)
{
/*
* Indicates whether we issued warnings or not during verification.
* This boolean is returned to the caller.
*/
boolean status = true;
String name = session.getHome();
if (name == null)
return false;
try
{
Class home = classloader.loadClass(name);
/*
* The home interface of a stateless session bean MUST have one
* create() method that takes no arguments.
*
* The create() method MUST return the session bean's remote
* interface.
*
* There CAN NOT be other create() methods in the home interface.
*
* Spec 6.8
*/
if (session.isStateless())
{
if (!hasDefaultCreateMethod(home))
{
fireSpecViolationEvent(session, new Section("6.8.a"));
status = false;
}
else
{
Method create = getDefaultCreateMethod(home);
if (!hasRemoteReturnType(session, create))
{
fireSpecViolationEvent(session, create, new Section("6.8.b"));
;
status = false;
}
if (hasMoreThanOneCreateMethods(home))
{
fireSpecViolationEvent(session, new Section("6.8.c"));
status = false;
}
}
}
/*
* The session bean's home interface MUST extend the
* javax.ejb.EJBHome interface.
*
* Spec 6.10.6
*/
if (!hasEJBHomeInterface(home))
{
fireSpecViolationEvent(session, new Section("6.10.6.a"));
status = false;
}
/*
* Method arguments defined in the home interface MUST be
* of valid types for RMI/IIOP.
*
* Method return values defined in the home interface MUST
* be of valid types for RMI/IIOP.
*
* Methods defined in the home interface MUST include
* java.rmi.RemoteException in their throws clause.
*
* Spec 6.10.6
*/
Iterator it = Arrays.asList(home.getMethods()).iterator();
while (it.hasNext())
{
Method method = (Method)it.next();
if (!hasLegalRMIIIOPArguments(method))
{
fireSpecViolationEvent(session, method, new Section("6.10.6.b"));
status = false;
}
if (!hasLegalRMIIIOPReturnType(method))
{
fireSpecViolationEvent(session, method, new Section("6.10.6.c"));
status = false;
}
if (!throwsRemoteException(method))
{
fireSpecViolationEvent(session, method, new Section("6.10.6.d"));
status = false;
}
}
/*
* A session bean's home interface MUST define one or more
* create(...) methods.
*
* Spec 6.10.6
*/
if (!hasCreateMethod(home))
{
fireSpecViolationEvent(session, new Section("6.10.6.e"));
status = false;
}
/*
* Each create(...) method in the session bean's home interface MUST
* have a matching ejbCreate(...) method in the session bean's class.
*
* Each create(...) method in the session bean's home interface MUST
* have the same number and types of arguments to its matching
* ejbCreate(...) method.
*
* The return type for a create(...) method MUST be the session
* bean's remote interface type.
*
* All the exceptions defined in the throws clause of the matching
* ejbCreate(...) method of the enterprise bean class MUST be
* included in the throws clause of a matching create(...) method.
*
* The throws clause of a create(...) method MUST include the
* javax.ejb.CreateException.
*
* Spec 6.10.6
*/
Iterator createMethods = getCreateMethods(home);
try
{
String beanClass = session.getEjbClass();
Class bean = classloader.loadClass(beanClass);
while (createMethods.hasNext())
{
Method create = (Method)createMethods.next();
if (!hasMatchingEJBCreate(bean, create))
{
fireSpecViolationEvent(session, create, new Section("6.10.6.f"));
status = false;
}
if (!hasRemoteReturnType(session, create))
{
fireSpecViolationEvent(session, create, new Section("6.10.6.g"));
status = false;
}
if (hasMatchingEJBCreate(bean, create))
{
Method ejbCreate = getMatchingEJBCreate(bean, create);
if (!hasMatchingExceptions(ejbCreate, create))
{
fireSpecViolationEvent(session, create, new Section("6.10.6.h"));
status = false;
}
}
if (!throwsCreateException(create))
{
fireSpecViolationEvent(session, create, new Section("6.10.6.i"));
status = false;
}
}
}
catch (ClassNotFoundException ignored)
{
}
}
catch (ClassNotFoundException e)
{
/*
* The bean provider MUST specify the fully-qualified name of the
* enterprise bean's home interface in the <home> element.
*
* Spec 16.2
*/
fireSpecViolationEvent(session, new Section("16.2.c"));
status = false;
}
return status;
}
/*
*************************************************************************
*
* VERIFY SESSION BEAN REMOTE INTERFACE
*
*************************************************************************
*/
private boolean verifySessionRemote(SessionMetaData session)
{
/*
* Indicates whether we issued warnings or not during verification.
* This boolean is returned to the caller.
*/
boolean status = true;
String name = session.getRemote();
if (name == null)
return false;
try
{
Class remote = classloader.loadClass(name);
/*
* The remote interface MUST extend the javax.ejb.EJBObject
* interface.
*
* Spec 6.10.5
*/
if (!hasEJBObjectInterface(remote))
{
fireSpecViolationEvent(session, new Section("6.10.5.a"));
status = false;
}
/*
* Method arguments defined in the remote interface MUST be
* of valid types for RMI/IIOP.
*
* Method return values defined in the remote interface MUST
* be of valid types for RMI/IIOP.
*
* Methods defined in the remote interface MUST include
* java.rmi.RemoteException in their throws clause.
*
* Spec 6.10.5
*/
Iterator it = Arrays.asList(remote.getMethods()).iterator();
while (it.hasNext())
{
Method method = (Method)it.next();
if (!hasLegalRMIIIOPArguments(method))
{
fireSpecViolationEvent(session, method, new Section("6.10.5.b"));
status = false;
}
if (!hasLegalRMIIIOPReturnType(method))
{
fireSpecViolationEvent(session, method, new Section("6.10.5.c"));
status = false;
}
if (!throwsRemoteException(method))
{
fireSpecViolationEvent(session, method, new Section("6.10.5.d"));
status = false;
}
}
/*
* For each method defined in the remote interface, there MUST be
* a matching method in the session bean's class. The matching
* method MUST have:
*
* - the same name
* - the same number and types of arguments, and the same
* return type
* - All the exceptions defined in the throws clause of the
* matching method of the session bean class must be defined
* in the throws clause of the method of the remote interface
*
* Spec 6.10.5
*/
String beanName = session.getEjbClass();
Class bean = classloader.loadClass(beanName);
Iterator iterator = Arrays.asList(remote.getDeclaredMethods()).iterator();
while (iterator.hasNext())
{
Method remoteMethod = (Method)iterator.next();
if (!hasMatchingMethod(bean, remoteMethod))
{
fireSpecViolationEvent(session, remoteMethod, new Section("6.10.5.e"));
status = false;
}
if (hasMatchingMethod(bean, remoteMethod))
{
try
{
Method beanMethod = bean.getMethod(remoteMethod.getName(), remoteMethod.getParameterTypes());
if (!hasMatchingReturnType(remoteMethod, beanMethod))
{
fireSpecViolationEvent(session, remoteMethod, new Section("6.10.5.f"));
status = false;
}
if (!hasMatchingExceptions(beanMethod, remoteMethod))
{
fireSpecViolationEvent(session, remoteMethod, new Section("6.10.5.g"));
status = false;
}
}
catch (NoSuchMethodException ignored)
{
}
}
} // while
}
catch (ClassNotFoundException e)
{
/*
* The Bean Provider MUST specify the fully-qualified name of the
* enterprise bean's remote interface in the <remote> element.
*
* Spec 16.2
*/
fireSpecViolationEvent(session, new Section("16.2.d"));
status = false;
}
return status;
}
/*
*************************************************************************
*
* VERIFY SESSION BEAN CLASS
*
*************************************************************************
*/
private boolean verifySessionBean(SessionMetaData session)
{
boolean status = true;
String name = session.getEjbClass();
try
{
Class bean = classloader.loadClass(name);
/*
* A session bean MUST implement, directly or indirectly,
* javax.ejb.SessionBean interface.
*
* Spec 6.5.1
* Spec 6.10.2
*/
if (!hasSessionBeanInterface(bean))
{
fireSpecViolationEvent(session, new Section("6.5.1"));
status = false;
}
/*
* Only a stateful container-managed transaction demarcation
* session bean MAY implement the SessionSynchronization interface.
*
* A stateless Session bean MUST NOT implement the
* SessionSynchronization interface.
*
* Spec 6.5.3
*/
if (hasSessionSynchronizationInterface(bean))
{
if (session.isStateless())
{
fireSpecViolationEvent(session, new Section("6.5.3.a"));
status = false;
}
if (session.isBeanManagedTx())
{
fireSpecViolationEvent(session, new Section("6.5.3.b"));
status = false;
}
}
/*
* A session bean MUST implement AT LEAST one ejbCreate method.
*
* Spec 6.5.5
*/
if (!hasEJBCreateMethod(bean, true))
{
fireSpecViolationEvent(session, new Section("6.5.5"));
status = false;
}
/*
* A session with bean-managed transaction demarcation CANNOT
* implement the SessionSynchronization interface.
*
* Spec 6.6.1 (table 2)
*/
if (hasSessionSynchronizationInterface(bean)
&& session.isBeanManagedTx())
{
fireSpecViolationEvent(session, new Section("6.6.1"));
status = false;
}
/*
* The session bean class MUST be defined as public.
*
* Spec 6.10.2
*/
if (!isPublic(bean))
{
fireSpecViolationEvent(session, new Section("6.10.2.a"));
status = false;
}
/*
* The session bean class MUST NOT be final.
*
* Spec 6.10.2
*/
if (isFinal(bean))
{
fireSpecViolationEvent(session, new Section("6.10.2.b"));
status = false;
}
/*
* The session bean class MUST NOT be abstract.
*
* Spec 6.10.2
*/
if (isAbstract(bean))
{
fireSpecViolationEvent(session, new Section("6.10.2.c"));
status = false;
}
/*
* The session bean class MUST have a public constructor that
* takes no arguments.
*
* Spec 6.10.2
*/
if (!hasDefaultConstructor(bean))
{
fireSpecViolationEvent(session, new Section("6.10.2.d"));
status = false;
}
/*
* The session bean class MUST NOT define the finalize() method.
*
* Spec 6.10.2
*/
if (hasFinalizer(bean))
{
fireSpecViolationEvent(session, new Section("6.10.2.e"));
status = false;
}
/*
* The ejbCreate(...) method signatures MUST follow these rules:
*
* - The method MUST be declared as public
* - The method MUST NOT be declared as final or static
* - The return type MUST be void
* - The method arguments MUST be legal types for RMI/IIOP
*
* Spec 6.10.3
*/
if (hasEJBCreateMethod(bean, true))
{
Iterator it = getEJBCreateMethods(bean);
while (it.hasNext())
{
Method ejbCreate = (Method)it.next();
if (!isPublic(ejbCreate))
{
fireSpecViolationEvent(session, ejbCreate, new Section("6.10.3.a"));
status = false;
}
if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
{
fireSpecViolationEvent(session, ejbCreate, new Section("6.10.3.b"));
status = false;
}
if (!hasVoidReturnType(ejbCreate))
{
fireSpecViolationEvent(session, ejbCreate, new Section("6.10.3.c"));
status = false;
}
if (!hasLegalRMIIIOPArguments(ejbCreate))
{
fireSpecViolationEvent(session, ejbCreate, new Section("6.10.3.d"));
status = false;
}
} // while
}
}
catch (ClassNotFoundException e)
{
/*
* The Bean Provider MUST specify the fully-qualified name of the
* Java class that implements the enterprise bean's business
* methods.
*
* Spec 16.2
*/
fireSpecViolationEvent(session, new Section("16.2.b"));
status = false;
}
return status;
}
/*
*************************************************************************
*
* VERIFY ENTITY BEAN HOME INTERFACE
*
*************************************************************************
*/
private boolean verifyEntityHome(EntityMetaData entity)
{
boolean status = true;
String name = entity.getHome();
if (name == null)
return false;
try
{
Class home = classloader.loadClass(name);
/*
* Entity bean's home interface MUST extend the javax.ejb.EJBHome
* interface.
*
* Spec 9.2.8
*/
if (!hasEJBHomeInterface(home))
{
fireSpecViolationEvent(entity, new Section("9.2.8.a"));
status = false;
}
/*
* The methods defined in the entity bean's home interface MUST
* have valid RMI-IIOP argument types.
*
* The methods defined in the entity bean's home interface MUST
* have valid RMI-IIOP return types.
*
* The methods defined in the entity bean's home interface MUST
* have java.rmi.RemoteException in their throws clause.
*
* Spec 9.2.8
*/
Iterator homeMethods = Arrays.asList(home.getMethods()).iterator();
while (homeMethods.hasNext())
{
Method method = (Method)homeMethods.next();
if (!hasLegalRMIIIOPArguments(method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.8.b"));
status = false;
}
if (!hasLegalRMIIIOPReturnType(method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.8.c"));
status = false;
}
if (!throwsRemoteException(method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.8.d"));
status = false;
}
} // while
/*
* Each method defined in the entity bean's home interface must be
* one of the following:
*
* - a create method
* - a finder method
*
* Spec 9.2.8
*/
homeMethods = Arrays.asList(home.getMethods()).iterator();
while (homeMethods.hasNext())
{
Method method = (Method)homeMethods.next();
// Do not check the methods of the javax.ejb.EJBHome interface
if (method.getDeclaringClass().getName().equals(EJB_HOME_INTERFACE))
continue;
if (!(isCreateMethod(method) || isFinderMethod(method)))
{
fireSpecViolationEvent(entity, method, new Section("9.2.8.e"));
status = false;
}
}
/*
* Each create(...) method in the entity bean's home interface MUST
* have a matching ejbCreate(...) method in the entity bean's class.
*
* Each create(...) method in the entity bean's home interface MUST
* have the same number and types of arguments to its matching
* ejbCreate(...) method.
*
* The return type for a create(...) method MUST be the entity
* bean's remote interface type.
*
* All the exceptions defined in the throws clause of the matching
* ejbCreate(...) and ejbPostCreate(...) methods of the enterprise
* bean class MUST be included in the throws clause of a matching
* create(...) method.
*
* The throws clause of a create(...) method MUST include the
* javax.ejb.CreateException.
*
* Spec 9.2.8
*/
try
{
String beanClass = entity.getEjbClass();
Class bean = classloader.loadClass(beanClass);
Iterator createMethods = getCreateMethods(home);
while (createMethods.hasNext())
{
Method create = (Method)createMethods.next();
if (!hasMatchingEJBCreate(bean, create))
{
fireSpecViolationEvent(entity, create, new Section("9.2.8.f"));
status = false;
}
if (!hasRemoteReturnType(entity, create))
{
fireSpecViolationEvent(entity, create, new Section("9.2.8.g"));
status = false;
}
if (hasMatchingEJBCreate(bean, create)
&& hasMatchingEJBPostCreate(bean, create))
{
Method ejbCreate = getMatchingEJBCreate(bean, create);
Method ejbPostCreate = getMatchingEJBPostCreate(bean, create);
if (!(hasMatchingExceptions(ejbCreate, create)
&& hasMatchingExceptions(ejbPostCreate, create)))
{
fireSpecViolationEvent(entity, create, new Section("9.2.8.h"));
status = false;
}
}
if (!throwsCreateException(create))
{
fireSpecViolationEvent(entity, create, new Section("9.2.8.i"));
status = false;
}
}
}
catch (ClassNotFoundException ignored)
{
}
/*
* Each finder method MUST match one of the ejbFind<METHOD> methods
* defined in the entity bean class.
*
* The matching ejbFind<METHOD> method MUST have the same number and
* types of arguments.
*
* The return type for a find<METHOD> method MUST be the entity
* bean's remote interface type (single-object finder) or a
* collection thereof (for a multi-object finder).
*
* All the exceptions defined in the throws clause of an ejbFind
* method of the entity bean class MUST be included in the throws
* clause of the matching find method of the home interface.
*
* The throws clause of a finder method MUST include the
* javax.ejb.FinderException.
*
* Spec 9.2.8
*/
try
{
String beanClass = entity.getEjbClass();
Class bean = classloader.loadClass(beanClass);
Iterator finderMethods = getFinderMethods(home);
while (finderMethods.hasNext())
{
Method finder = (Method)finderMethods.next();
if ((entity.isBMP()) && (!hasMatchingEJBFind(bean, finder)))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.8.j"));
status = false;
}
if (!(hasRemoteReturnType(entity, finder)
|| isMultiObjectFinder(finder)))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.8.k"));
status = false;
}
if ((entity.isBMP()) && (hasMatchingEJBFind(bean, finder)))
{
Method ejbFind = getMatchingEJBFind(bean, finder);
if (!(hasMatchingExceptions(ejbFind, finder)))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.8.l"));
status = false;
}
}
if (!throwsFinderException(finder))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.8.m"));
status = false;
}
}
}
catch (ClassNotFoundException ignored)
{
}
}
catch (ClassNotFoundException e)
{
/*
* The bean provider MUST specify the fully-qualified name of the
* enterprise bean's home interface in the <home> element.
*
* Spec 16.2
*/
fireSpecViolationEvent(entity, new Section("16.2.c"));
status = false;
}
return status;
}
/*
*************************************************************************
*
* VERIFY ENTITY BEAN REMOTE INTERFACE
*
*************************************************************************
*/
private boolean verifyEntityRemote(EntityMetaData entity)
{
boolean status = true;
String name = entity.getRemote();
if (name == null)
return false;
try
{
Class remote = classloader.loadClass(name);
/*
* Entity bean's remote interface MUST extend
* the javax.ejb.EJBObject interface.
*
* Spec 9.2.7
*/
if (!hasEJBObjectInterface(remote))
{
fireSpecViolationEvent(entity, new Section("9.2.7.a"));
status = false;
}
/*
* The methods defined in the entity bean's remote interface MUST
* have valid RMI-IIOP argument types.
*
* The methods defined in the entity bean's home interface MUST
* have valid RMI-IIOP return types.
*
* The methods defined in the entity bean's home interface MUST
* have java.rmi.RemoteException in their throws clause.
*
* Spec 9.2.7
*/
Iterator remoteMethods = Arrays.asList(remote.getMethods()).iterator();
while (remoteMethods.hasNext())
{
Method method = (Method)remoteMethods.next();
if (!hasLegalRMIIIOPArguments(method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.7.b"));
status = false;
}
if (!hasLegalRMIIIOPReturnType(method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.7.c"));
status = false;
}
if (!hasLegalRMIIIOPExceptionTypes(method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.7.h"));
status = false;
}
if (!throwsRemoteException(method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.7.d"));
status = false;
}
} // while
/*
* For each method defined in the remote interface, there MUST be
* a matching method in the entity bean's class. The matching
* method MUST have:
*
* - The same name.
* - The same number and types of its arguments.
* - The same return type.
* - All the exceptions defined in the throws clause of the
* matching method of the enterprise Bean class must be
* defined in the throws clause of the method of the remote
* interface.
*
* Spec 9.2.7
*/
try
{
String beanClass = entity.getEjbClass();
Class bean = classloader.loadClass(beanClass);
remoteMethods = Arrays.asList(remote.getMethods()).iterator();
while (remoteMethods.hasNext())
{
Method method = (Method)remoteMethods.next();
// Do not check the methods of the javax.ejb.EJBObject interface
if (method.getDeclaringClass().getName().equals(EJB_OBJECT_INTERFACE))
continue;
if (!hasMatchingMethod(bean, method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.7.e"));
status = false;
}
if (hasMatchingMethod(bean, method))
{
try
{
Method beanMethod = bean.getMethod(method.getName(), method.getParameterTypes());
if (!hasMatchingReturnType(beanMethod, method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.7.f"));
status = false;
}
if (!hasMatchingExceptions(beanMethod, method))
{
fireSpecViolationEvent(entity, method, new Section("9.2.7.g"));
status = false;
}
}
catch (NoSuchMethodException ignored)
{
}
}
}
}
catch (ClassNotFoundException ignored)
{
}
}
catch (ClassNotFoundException e)
{
/*
* The Bean Provider MUST specify the fully-qualified name of the
* enterprise bean's remote interface in the <remote> element.
*
* Spec 16.2
*/
fireSpecViolationEvent(entity, new Section("16.2.d"));
status = false;
}
return status;
}
/*
*************************************************************************
*
* VERIFY ENTITY BEAN CLASS
*
*************************************************************************
*/
private boolean verifyEntityBean(EntityMetaData entity)
{
boolean status = true;
String name = entity.getEjbClass();
try
{
Class bean = classloader.loadClass(name);
/*
* The enterprise bean class MUST implement, directly or
* indirectly, the javax.ejb.EntityBean interface.
*
* Spec 9.2.2
*/
if (!hasEntityBeanInterface(bean))
{
fireSpecViolationEvent(entity, new Section("9.2.2.a"));
status = false;
}
/*
* The entity bean class MUST be defined as public.
*
* Spec 9.2.2
*/
if (!isPublic(bean))
{
fireSpecViolationEvent(entity, new Section("9.2.2.b"));
status = false;
}
/*
* The entity bean class MUST NOT be defined as abstract.
*
* Spec 9.2.2
*/
if (isAbstract(bean))
{
fireSpecViolationEvent(entity, new Section("9.2.2.c"));
status = false;
}
/*
* The entity bean class MUST NOT be defined as final.
*
* Spec 9.2.2
*/
if (isFinal(bean))
{
fireSpecViolationEvent(entity, new Section("9.2.2.d"));
status = false;
}
/*
* The entity bean class MUST define a public constructor that
* takes no arguments
*
* Spec 9.2.2
*/
if (!hasDefaultConstructor(bean))
{
fireSpecViolationEvent(entity, new Section("9.2.2.e"));
status = false;
}
/*
* The entity bean class MUST NOT define the finalize() method.
*
* Spec 9.2.2
*/
if (hasFinalizer(bean))
{
fireSpecViolationEvent(entity, new Section("9.2.2.f"));
status = false;
}
/*
* The ejbCreate(...) method signatures MUST follow these rules:
*
* - The method MUST be declared as public
* - The method MUST NOT be declared as final or static
* - The return type MUST be the entity bean's primary key type
* - The method arguments MUST be legal types for RMI/IIOP
* - The method return value type MUST be legal type for RMI/IIOP
*
* Spec 9.2.3
*/
if (hasEJBCreateMethod(bean, false))
{
Iterator it = getEJBCreateMethods(bean);
while (it.hasNext())
{
Method ejbCreate = (Method)it.next();
if (!isPublic(ejbCreate))
{
fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.a"));
status = false;
}
if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
{
fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.b"));
status = false;
}
if (!hasPrimaryKeyReturnType(entity, ejbCreate))
{
fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.c"));
status = false;
}
if (!hasLegalRMIIIOPArguments(ejbCreate))
{
fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.d"));
status = false;
}
if (!hasLegalRMIIIOPReturnType(ejbCreate))
{
fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.e"));
status = false;
}
}
}
/*
* For each ejbCreate(...) method, the entity bean class MUST
* define a matching ejbPostCreate(...) method.
*
* The ejbPostCreate(...) method MUST follow these rules:
*
* - the method MUST be declared as public
* - the method MUST NOT be declared as final or static
* - the return type MUST be void
* - the method arguments MUST be the same as the matching
* ejbCreate(...) method
*
* Spec 9.2.4
*/
if (hasEJBCreateMethod(bean, false))
{
Iterator it = getEJBCreateMethods(bean);
while (it.hasNext())
{
Method ejbCreate = (Method)it.next();
if (!hasMatchingEJBPostCreate(bean, ejbCreate))
{
fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.4.a"));
status = false;
}
if (hasMatchingEJBPostCreate(bean, ejbCreate))
{
Method ejbPostCreate = getMatchingEJBPostCreate(bean, ejbCreate);
if (!isPublic(ejbPostCreate))
{
fireSpecViolationEvent(entity, ejbPostCreate, new Section("9.2.4.b"));
status = false;
}
if (isStatic(ejbPostCreate))
{
fireSpecViolationEvent(entity, ejbPostCreate, new Section("9.2.4.c"));
status = false;
}
if (isFinal(ejbPostCreate))
{
fireSpecViolationEvent(entity, ejbPostCreate, new Section("9.2.4.d"));
status = false;
}
if (!hasVoidReturnType(ejbPostCreate))
{
fireSpecViolationEvent(entity, ejbPostCreate, new Section("9.2.4.e"));
status = false;
}
}
}
}
/*
* Every entity bean MUST define the ejbFindByPrimaryKey method.
*
* The return type for the ejbFindByPrimaryKey method MUST be the
* primary key type.
*
* The ejbFindByPrimaryKey method MUST be a single-object finder.
*
* Spec 9.2.5
*/
if (entity.isBMP() && (!hasEJBFindByPrimaryKey(bean)))
{
fireSpecViolationEvent(entity, new Section("9.2.5.a"));
status = false;
}
if (hasEJBFindByPrimaryKey(bean))
{
Method ejbFindByPrimaryKey = getEJBFindByPrimaryKey(bean);
if (!hasPrimaryKeyReturnType(entity, ejbFindByPrimaryKey))
{
fireSpecViolationEvent(entity, ejbFindByPrimaryKey, new Section("9.2.5.b"));
status = false;
}
if (!isSingleObjectFinder(entity, ejbFindByPrimaryKey))
{
fireSpecViolationEvent(entity, ejbFindByPrimaryKey, new Section("9.2.5.c"));
status = false;
}
}
/*
* A finder method MUST be declared as public.
*
* A finder method MUST NOT be declared as static.
*
* A finder method MUST NOT be declared as final.
*
* The finder method argument types MUST be legal types
* for RMI/IIOP
*
* The finder method return type MUST be either the entity bean's
* primary key type, or java.lang.util.Enumeration interface or
* java.lang.util.Collection interface.
*
* Spec 9.2.5
*/
if (hasFinderMethod(bean))
{
Iterator it = getEJBFindMethods(bean);
while (it.hasNext())
{
Method finder = (Method)it.next();
if (!isPublic(finder))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.5.d"));
status = false;
}
if (isFinal(finder))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.5.e"));
status = false;
}
if (isStatic(finder))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.5.f"));
status = false;
}
if (!hasLegalRMIIIOPArguments(finder))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.5.g"));
status = false;
}
if (!(isSingleObjectFinder(entity, finder)
|| isMultiObjectFinder(finder)))
{
fireSpecViolationEvent(entity, finder, new Section("9.2.5.h"));
status = false;
}
}
}
}
catch (ClassNotFoundException e)
{
/*
* The Bean Provider MUST specify the fully-qualified name of the
* Java class that implements the enterprise bean's business
* methods.
*
* Spec 16.2
*/
fireSpecViolationEvent(entity, new Section("16.2.b"));
status = false;
}
return status;
}
private boolean verifyPrimaryKey(EntityMetaData entity)
{
boolean status = true;
if (entity.getPrimaryKeyClass() == null
|| entity.getPrimaryKeyClass().length() == 0)
{
fireSpecViolationEvent(entity, new Section("16.5.a"));
return false; // We can't get any further if there's no PK class specified!
}
if (entity.getPrimKeyField() == null
|| entity.getPrimKeyField().length() == 0)
{
Class cls = null;
try
{
cls = classloader.loadClass(entity.getPrimaryKeyClass());
if (entity.isCMP())
{
if (!isPublic(cls))
{
fireSpecViolationEvent(entity, new Section("9.4.7.2.a"));
status = false;
}
if (!isAllFieldsPublic(cls))
{
fireSpecViolationEvent(entity, new Section("9.4.7.2.b"));
status = false;
}
if (!hasANonStaticField(cls))
{
fireSpecViolationEvent(entity, new Section("9.4.7.2.c"));
status = false;
}
}
if (!cls.getName().equals("java.lang.Object"))
{
Object one, two;
try
{
one = cls.newInstance();
two = cls.newInstance();
try
{
if (!one.equals(two))
{
fireSpecViolationEvent(entity, new Section("9.2.9.b"));
status = false;
}
}
catch (NullPointerException e)
{
} // That's OK - the implementor expected the fields to have values
try
{
if (one.hashCode() != two.hashCode())
{
fireSpecViolationEvent(entity, new Section("9.2.9.c"));
status = false;
}
}
catch (NullPointerException e)
{
} // That's OK - the implementor expected the fields to have values
}
catch (IllegalAccessException e)
{
// [FIXME] The two error messages below are incorrect.
// The RMI-IDL language mapping does not require
// the value types to have a no args constructor.
// [JPL]
//
//fireSpecViolationEvent(entity, new Section("9.2.9.a"));
//status = false;
}
catch (InstantiationException e)
{
//fireSpecViolationEvent(entity, new Section("9.2.9.a"));
//status = false;
}
}
}
catch (ClassNotFoundException e)
{
fireSpecViolationEvent(entity, new Section("16.2.e"));
status = false; // Can't do any other checks if the class is null!
}
}
else
{
if (entity.isBMP())
{
fireSpecViolationEvent(entity, new Section("9.4.7.1.a"));
status = false;
}
try
{
Class fieldClass = classloader.loadClass(entity.getEjbClass());
Field field = null;
try
{
field = fieldClass.getField(entity.getPrimKeyField());
if (!entity.getPrimaryKeyClass().equals(field.getType().getName()))
{
fireSpecViolationEvent(entity, new Section("9.4.7.1.c"));
status = false;
}
Iterator it = entity.getCMPFields();
boolean found = false;
while (it.hasNext())
{
String fieldName = (String)it.next();
if (fieldName.equals(entity.getPrimKeyField()))
{
found = true;
break;
}
}
if (!found)
{
fireSpecViolationEvent(entity, new Section("9.4.7.1.d"));
status = false;
}
}
catch (NoSuchFieldException e)
{
fireSpecViolationEvent(entity, new Section("9.4.7.1.b"));
status = false;
}
}
catch (ClassNotFoundException e)
{
} // reported elsewhere
}
return status;
}
}
/*
vim:ts=3:sw=3:et
*/