User: mulder
Date: 00/06/06 17:02:53
Modified: src/main/org/jboss/verifier/strategy EJBVerifier11.java
Log:
Add Primary Key validations for Entity Beans.
Revision Changes Path
1.6 +241 -172 jboss/src/main/org/jboss/verifier/strategy/EJBVerifier11.java
Index: EJBVerifier11.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/verifier/strategy/EJBVerifier11.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- EJBVerifier11.java 2000/06/03 21:43:55 1.5
+++ EJBVerifier11.java 2000/06/07 00:02:53 1.6
@@ -13,13 +13,13 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* This package and its source code is available at www.jboss.org
- * $Id: EJBVerifier11.java,v 1.5 2000/06/03 21:43:55 juha Exp $
+ * $Id: EJBVerifier11.java,v 1.6 2000/06/07 00:02:53 mulder Exp $
*/
@@ -27,9 +27,7 @@
import java.util.Iterator;
import java.net.URL;
import java.net.URLClassLoader;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Constructor;
+import java.lang.reflect.*;
// non-standard class dependencies
@@ -53,7 +51,7 @@
* @see << OTHER RELATED CLASSES >>
*
* @author Juha Lindfors ([EMAIL PROTECTED])
- * @version $Revision: 1.5 $
+ * @version $Revision: 1.6 $
* @since JDK 1.3
*/
public class EJBVerifier11 extends AbstractVerifier {
@@ -61,13 +59,13 @@
private VerificationContext context = null;
private VerificationEventFactory factory = null;
private ClassLoader classloader = null;
-
-
+
+
/*
* Constructor
*/
public EJBVerifier11(VerificationContext context) {
-
+
URL[] list = { context.getJarLocation() };
ClassLoader parent = getClass().getClassLoader();
@@ -75,18 +73,18 @@
this.classloader = cl;
this.context = context;
-
+
this.factory = new VerificationEventFactory();
}
+
-
-
-
+
+
public void checkSession(Session session) {
boolean sessionDescriptorVerified = true; // false;
-
+
boolean beanVerified = false;
boolean homeVerified = false;
boolean remoteVerified = false;
@@ -94,44 +92,47 @@
* [TODO] use state pattern instead, this collection of bools is going
* to grow, and managing them will become messy
*/
-
+
//sessionDescriptorVerified = verifySessionDescriptor();
-
+
/*
- * Also, the descriptors should most likely be checked in one place,
+ * Also, the descriptors should most likely be checked in one place,
* instead of sprinkling their check code across the bean class
* checkers..
*/
-
-
- beanVerified = verifySessionBean(session);
+
+
+ beanVerified = verifySessionBean(session);
homeVerified = verifySessionHome(session.getHome());
remoteVerified = verifySessionRemote(session.getRemote());
if ( beanVerified && homeVerified && remoteVerified &&
sessionDescriptorVerified) {
-
+
/*
* Verification for this session bean done. Fire the event
* to tell listeneres everything is ok.
*/
- VerificationEvent event =
+ VerificationEvent event =
factory.createBeanVerifiedEvent(context, session.getEjbClass());
-
+
context.fireBeanChecked(event);
}
}
-
+
public void checkEntity(Entity entity) {
+ boolean pkVerified = false;
+
+ pkVerified = verifyPrimaryKey(entity.getPrimaryKeyClass());
// NO IMPLEMENTATION
}
+
-
-
-
+
+
/*
***********************************************************************
*
@@ -139,26 +140,26 @@
*
***********************************************************************
*/
-
+
public StrategyContext getContext() {
return context;
}
public void checkSessions(Iterator beans) {
- while (beans.hasNext()) {
+ while (beans.hasNext()) {
try {
checkSession((Session)beans.next());
}
catch (ClassCastException e) {
System.err.println(e);
- // THROW INTERNAL ERROR
+ // THROW INTERNAL ERROR
}
}
- }
+ }
public void checkEntities(Iterator beans) {
-
+
while (beans.hasNext()) {
try {
checkEntity((Entity)beans.next());
@@ -168,14 +169,14 @@
// THROW INTERNAL ERROR
}
}
- }
-
+ }
+
public void checkMessageDriven(Iterator beans) {
-
+
// EMPTY IMPLEMENTATION, EJB 2.0 ONLY
}
-
-
+
+
/*
*****************************************************************************
*****************************************************************************
@@ -185,21 +186,21 @@
*****************************************************************************
*****************************************************************************
*/
-
+
private boolean verifySessionHome(String name) {
-
+
// NO IMPLEMENTATION
-
+
return true;
}
-
+
private boolean verifySessionRemote(String name) {
-
+
// NO IMPLEMENTATION
-
+
return true;
}
-
+
private boolean verifySessionBean(Session session) {
/*
@@ -207,14 +208,14 @@
* This boolean is returned to the caller.
*/
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.
@@ -223,48 +224,48 @@
* Spec 6.10.2
*/
if (!hasSessionBeanInterface(bean)) {
-
+
fireSpecViolationEvent(SECTION_6_5_1, name);
-
+
status = false;
}
-
+
/*
* Only a stateful container-managed transaction demarcation
* session bean MAY implement the SessionSynchronization interface.
*
- * A stateless Session bean MUST NOT implement the
+ * A stateless Session bean MUST NOT implement the
* SessionSynchronization interface.
*
* Spec 6.5.3
*/
if (hasSessionSynchronizationInterface(bean))
-
+
if (!isStateful(session)) {
fireSpecViolationEvent(SECTION_6_5_3_a, name);
-
+
status = false;
}
-
+
if (!isContainerManagedTx(session)) {
fireSpecViolationEvent(SECTION_6_5_3_b, name);
-
+
status = false;
}
-
-
+
+
/*
* A session bean MUST implement AT LEAST one ejbCreate method.
*
* Spec 6.5.5
*/
if (!hasEJBCreateMethod(bean)) {
-
+
fireSpecViolationEvent(SECTION_6_5_5, name);
-
+
status = false;
-
+
/*
* [TODO] the ejbCreate signature in bean class must match the
* create methods signature in home interface.
@@ -273,8 +274,8 @@
* didnt find explicit requirement yet
*/
}
+
-
/*
* A session with bean-managed transaction demarcation CANNOT
* implement the SessionSynchronization interface.
@@ -284,9 +285,9 @@
if (hasSessionSynchronizationInterface(bean) &&
isBeanManagedTx(session)) {
fireSpecViolationEvent(SECTION_6_6_1, name);
-
+
status = false;
- }
+ }
/*
* The session bean class MUST be defined as public.
@@ -294,36 +295,36 @@
* Spec 6.10.2
*/
if (!isPublicClass(bean)) {
-
+
fireSpecViolationEvent(SECTION_6_10_2_a, name);
-
+
status = false;
}
-
+
/*
* The session bean class MUST NOT be final.
*
* Spec 6.10.2
*/
if (isFinalClass(bean)) {
-
+
fireSpecViolationEvent(SECTION_6_10_2_b, name);
-
+
status = false;
}
-
+
/*
* The session bean class MUST NOT be abstract.
*
* Spec 6.10.2
*/
if (isAbstractClass(bean)) {
-
+
fireSpecViolationEvent(SECTION_6_10_2_c, name);
-
+
status = false;
}
-
+
/*
* The session bean class MUST have a public constructor that
* takes no arguments.
@@ -331,54 +332,100 @@
* Spec 6.10.2
*/
if (!hasDefaultConstructor(bean)) {
-
+
fireSpecViolationEvent(SECTION_6_10_2_d, name);
-
+
status = false;
}
-
+
/*
* The session bean class MUST NOT define the finalize() method.
*
* Spec 6.10.2
*/
if (hasFinalizer(bean)) {
-
+
fireSpecViolationEvent(SECTION_6_10_2_e, name);
-
+
status = false;
}
-
-
-
+
+
+
}
catch (ClassNotFoundException e) {
-
- VerificationEvent event =
+
+ VerificationEvent event =
factory.createSpecViolationEvent(context, DTD_EJB_CLASS, name);
-
+
context.fireBeanChecked(event);
-
+
+ status = false;
+ }
+
+ return status;
+ }
+
+
+ private boolean verifyPrimaryKey(String className) {
+ boolean status = true;
+ Class cls = null;
+
+ try {
+ cls = Class.forName(className);
+ } catch(Exception e) {
+ context.fireBeanChecked(new VerificationEvent(context, "Primary key
class is not available."));
+ return false; // Can't do any other checks if the class is null!
+ }
+
+ if(!isPublicClass(cls)) {
+ status = false;
+ context.fireBeanChecked(new VerificationEvent(context, "Primary key
class must be public (see section 9.4.7.2)."));
+ }
+
+ if(!isAllFieldsPublic(cls)) {
+ status = false;
+ context.fireBeanChecked(new VerificationEvent(context, "Primary key
fields must all be public (see section 9.4.7.2)."));
+ }
+
+ if(!hasANonStaticField(cls)) {
+ status = false;
+ context.fireBeanChecked(new VerificationEvent(context, "Primary key
must have at least one nonstatic field."));
+ }
+
+ Object one, two;
+ try {
+ one = cls.newInstance();
+ two = cls.newInstance();
+ if(!one.equals(two)) {
+ status = false;
+ context.fireBeanChecked(new VerificationEvent(context, "Primary key
does not implement equals() correctly (see section 9.2.9)."));
+ }
+ if(one.hashCode() != two.hashCode()) {
+ status = false;
+ context.fireBeanChecked(new VerificationEvent(context, "Primary key
does not implement hashCode() correctly (see section 9.2.9)."));
+ }
+ } catch(Exception e) {
status = false;
}
-
+
return status;
}
-
+
-
+
/*
* Searches for an instance of a public ejbCreate method from the class
*/
private boolean hasEJBCreateMethod(Class c) {
-
+
try {
Method[] method = c.getMethods();
-
+
for (int i = 0; i < method.length; ++i) {
-
+
String name = method[i].getName();
-
+
if (name.equals(EJB_CREATE_METHOD))
// check the requirements for ejbCreate methods (spec 6.10.3)
// check for public modifier done by getMethods() call
@@ -386,7 +433,7 @@
if (!isStaticMember(method[i])
&& !isFinalMember(method[i])
&& hasVoidReturnType(method[i]))
-
+
return true;
}
}
@@ -395,160 +442,171 @@
// [TODO] Can be thrown by the getMethods() call if access is
// denied --> createVerifierWarningEvent
}
-
+
return false;
}
-
-
-
+
+
+
/*
* Finds java.ejb.SessionBean interface from the class
*/
private boolean hasSessionBeanInterface(Class c) {
Class[] interfaces = c.getInterfaces();
-
+
for (int i = 0; i < interfaces.length; ++i) {
-
+
if ((SESSIONBEAN_INTERFACE).equals(interfaces[i].getName()))
return true;
}
-
+
return false;
}
+
+
-
-
/*
* Finds javax.ejb.SessionSynchronization interface from the class
*/
private boolean hasSessionSynchronizationInterface(Class c) {
-
+
Class[] interfaces = c.getInterfaces();
-
+
for (int i = 0; i < interfaces.length; ++i) {
-
+
if ((SESSIONSYNCHRONIZATION_INTERFACE).equals(interfaces[i].getName()))
return true;
}
-
+
return false;
}
+
-
private boolean hasDefaultConstructor(Class c) {
try {
- Constructor constructor = c.getConstructor(new Class[] { Void.TYPE });
- }
-
- catch (NoSuchMethodException e) {
- return false;
- }
-
- catch (SecurityException e) {
- System.err.println(e);
- // [TODO] Can be thrown by the getConstructor() call if access is
- // denied --> createVerifierWarningEvent
-
+ c.newInstance();
+ } catch(Exception e) {
return false;
}
-
return true;
}
-
+
private boolean hasFinalizer(Class c) {
-
+
try {
- Method finalizer = c.getDeclaredMethod("finalize", new Class[] {
Void.TYPE });
-
+ Method finalizer = c.getDeclaredMethod("finalize", new Class[0]);
+
if (finalizer.getModifiers() != Modifier.PROTECTED)
return false;
}
-
+
catch (NoSuchMethodException e) {
return false;
}
-
+
catch (SecurityException e) {
System.err.println(e);
// [TODO] Can be thrown by the getDeclaredMethod() call if access is
// denied --> createVerifierWarningEvent
-
+
return false;
}
-
+
return true;
}
-
-
+
+ private boolean isAllFieldsPublic(Class c) {
+ try {
+ Field list[] = c.getFields();
+ for(int i=0; i<list.length; i++)
+ if(!Modifier.isPublic(list[i].getModifiers()))
+ return false;
+ } catch(Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean hasANonStaticField(Class c) {
+ try {
+ Field list[] = c.getFields();
+ for(int i=0; i<list.length; i++)
+ if(!Modifier.isStatic(list[i].getModifiers()))
+ return true;
+ } catch(Exception e) {
+ }
+ return false;
+ }
+
private boolean isStateful(Session session) {
if (STATEFUL_SESSION.equals(session.getSessionType()))
return true;
-
+
return false;
}
+
-
-
+
private boolean isBeanManagedTx(Session session) {
if (BEAN_MANAGED_TX.equals(session.getTransactionType()))
return true;
-
+
return false;
}
-
+
private boolean isContainerManagedTx(Session session) {
-
+
if (CONTAINER_MANAGED_TX.equals(session.getTransactionType()))
return true;
-
+
return false;
}
-
-
+
+
private boolean isPublicClass(Class c) {
-
+
if (c.getModifiers() == Modifier.PUBLIC)
return true;
-
+
return false;
}
-
-
+
+
private boolean isFinalClass(Class c) {
-
+
if (c.getModifiers() == Modifier.FINAL)
return true;
-
+
return false;
}
private boolean isAbstractClass(Class c) {
-
+
if (c.getModifiers() == Modifier.ABSTRACT)
return true;
-
+
return false;
}
-
-
+
+
private void fireSpecViolationEvent(String section, String name) {
- VerificationEvent event =
+ VerificationEvent event =
factory.createSpecViolationEvent(context, section, name);
-
+
context.fireBeanChecked(event);
}
-
-
-
+
+
+
- /*
+ /*
****************************************************************
*
* String constants
@@ -557,33 +615,33 @@
*/
private final static String SESSIONBEAN_INTERFACE =
"javax.ejb.SessionBean";
-
+
private final static String SESSIONSYNCHRONIZATION_INTERFACE =
"javax.ejb.SessionSynchronization";
-
+
private final static String EJB_CREATE_METHOD =
"ejbCreate";
-
-
+
+
/*
* Specification entries
*/
public final static String SECTION_6_5_1 =
- "Section 6.5.1 Required Sessionbean interface";
-
+ "Section 6.5.1 Required Sessionbean interface";
+
public final static String SECTION_6_5_3_a =
"Section 6.5.3 The optional SessionSynchronization interface (stateful)";
-
+
public final static String SECTION_6_5_3_b =
"Section 6.5.3 The optional SessionSynchronization interface (stateless)";
-
+
public final static String SECTION_6_5_5 =
"Section 6.5.5 Session bean's ejbCreate(...) methods";
-
+
public final static String SECTION_6_6_1 =
- "Section 6.6.1 Operations allowed in the methods of a stateful session bean
class";
-
+ "Section 6.6.1 Operations allowed in the methods of a stateful session bean
class";
+
public final static String SECTION_6_10_2_a =
"Section 6.10.2 Session bean class (public class)";
@@ -595,21 +653,32 @@
public final static String SECTION_6_10_2_d =
"Section 6.10.2 Session bean class (public constructor)";
-
+
public final static String SECTION_6_10_2_e =
"Section 6.10.2 Session bean class (no finalizer)";
+
+ public final static String SECTION_9_2_9_a =
+ "Section 9.2.9 Primary key class (equals doesn't work)";
-
+ public final static String SECTION_9_2_9_b =
+ "Section 9.2.9 Primary key class (hashCode doesn't work)";
+
+ public final static String SECTION_9_4_7_2_a =
+ "Section 9.4.7.2 Primary key class (not public)";
+
+ public final static String SECTION_9_4_7_2_b =
+ "Section 9.4.7.2 Primary key class (fields not public)";
+
/*
* Ejb-jar DTD
*/
public final static String DTD_EJB_CLASS =
"Deployment descriptor DTD: ejb-class";
- public final static String BEAN_MANAGED_TX =
+ public final static String BEAN_MANAGED_TX =
"Bean";
-
- public final static String CONTAINER_MANAGED_TX =
+
+ public final static String CONTAINER_MANAGED_TX =
"Container";
public final static String STATEFUL_SESSION =
@@ -617,6 +686,6 @@
public final static String STATELESS_SESSION =
"Stateless";
-
+
}