[jboss-cvs] JBossAS SVN: r82318 - in projects/ejb3/trunk/common/src: main/java/org/jboss/ejb3/common/classloader and 4 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Dec 16 11:23:19 EST 2008
Author: jaikiran
Date: 2008-12-16 11:23:19 -0500 (Tue, 16 Dec 2008)
New Revision: 82318
Added:
projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/classloader/
projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/classloader/PrimitiveAwareClassLoader.java
projects/ejb3/trunk/common/src/test/java/org/jboss/ejb3/test/common/classloader/
projects/ejb3/trunk/common/src/test/java/org/jboss/ejb3/test/common/classloader/unit/
projects/ejb3/trunk/common/src/test/java/org/jboss/ejb3/test/common/classloader/unit/PrimitiveAwareClassLoaderTestCase.java
Modified:
projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/lang/SerializableMethod.java
Log:
EJBTHREE-1626 : A PrimitiveAwareClassLoader to avoid duplicated logic to check primitive types while loading classes
Added: projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/classloader/PrimitiveAwareClassLoader.java
===================================================================
--- projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/classloader/PrimitiveAwareClassLoader.java (rev 0)
+++ projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/classloader/PrimitiveAwareClassLoader.java 2008-12-16 16:23:19 UTC (rev 82318)
@@ -0,0 +1,109 @@
+/*
+ * 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.ejb3.common.classloader;
+
+/**
+ * PrimitiveAwareClassLoader
+ *
+ * This is more of a hack to avoid checking for primitives at multiple places
+ * while loading a class from a name. <br/>
+ *
+ * The {@link PrimitiveAwareClassLoader} will first check whether the request
+ * is to load a primitive. If it's a primitive then it returns back the appropriate
+ * {@link Class} corresponding to the primitive. For all other requests, it redirects
+ * the request to the parent classloader.
+ *
+ * @author Jaikiran Pai
+ * @version $Revision: $
+ */
+public class PrimitiveAwareClassLoader extends ClassLoader
+{
+
+ /**
+ *
+ * @param parent Parent classloader
+ */
+ public PrimitiveAwareClassLoader(ClassLoader parent)
+ {
+ super(parent);
+ }
+
+ /**
+ * As recommended in {@link ClassLoader#findClass(java.lang.String)}, the findClass method
+ * should be overriden by the custom classloaders. This method will first check whether
+ * the requested <code>name</code> is a primitive. If yes, it returns the appropriate {@link Class}
+ * for the primitive. If not, then it lets the parent handle it.
+ *
+ */
+ @Override
+ protected java.lang.Class<?> findClass(String name) throws ClassNotFoundException
+ {
+
+ /*
+ * Handle Primitives
+ */
+ if (name.equals(void.class.getName()))
+ {
+ return void.class;
+ }
+ if (name.equals(byte.class.getName()))
+ {
+ return byte.class;
+ }
+ if (name.equals(short.class.getName()))
+ {
+ return short.class;
+ }
+ if (name.equals(int.class.getName()))
+ {
+ return int.class;
+ }
+ if (name.equals(long.class.getName()))
+ {
+ return long.class;
+ }
+ if (name.equals(char.class.getName()))
+ {
+ return char.class;
+ }
+ if (name.equals(boolean.class.getName()))
+ {
+ return boolean.class;
+ }
+ if (name.equals(float.class.getName()))
+ {
+ return float.class;
+ }
+ if (name.equals(double.class.getName()))
+ {
+ return double.class;
+ }
+
+ // Now that we know, its not a primitive, lets just allow
+ // the parent to handle the request.
+ // Note that we are intentionally using Class.forName(name,boolean,cl)
+ // to handle issues with loading array types in Java 6 http://bugs.sun.com/view_bug.do?bug_id=6434149
+ return Class.forName(name, false, this.getParent());
+
+ }
+
+}
Property changes on: projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/classloader/PrimitiveAwareClassLoader.java
___________________________________________________________________
Name: svn:executable
+ *
Modified: projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/lang/SerializableMethod.java
===================================================================
--- projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/lang/SerializableMethod.java 2008-12-16 15:41:50 UTC (rev 82317)
+++ projects/ejb3/trunk/common/src/main/java/org/jboss/ejb3/common/lang/SerializableMethod.java 2008-12-16 16:23:19 UTC (rev 82318)
@@ -27,6 +27,7 @@
import java.util.Arrays;
import java.util.List;
+import org.jboss.ejb3.common.classloader.PrimitiveAwareClassLoader;
import org.jboss.logging.Logger;
/**
@@ -295,53 +296,15 @@
{
// Perform assertions
assert cl != null : ClassLoader.class.getSimpleName() + " must be defined.";
+
- /*
- * Handle Primitives
- */
- if (name.equals(void.class.getName()))
- {
- return void.class;
- }
- if (name.equals(byte.class.getName()))
- {
- return byte.class;
- }
- if (name.equals(short.class.getName()))
- {
- return short.class;
- }
- if (name.equals(int.class.getName()))
- {
- return int.class;
- }
- if (name.equals(long.class.getName()))
- {
- return long.class;
- }
- if (name.equals(char.class.getName()))
- {
- return char.class;
- }
- if (name.equals(boolean.class.getName()))
- {
- return boolean.class;
- }
- if (name.equals(float.class.getName()))
- {
- return float.class;
- }
- if (name.equals(double.class.getName()))
- {
- return double.class;
- }
-
// Load the Class described by the Method
Class<?> clazz = null;
try
{
- clazz = Class.forName(name, false, cl);
+ // use the PrimitiveAwareClassLoader to avoid any primitive check here, in this method.
+ clazz = new PrimitiveAwareClassLoader(cl).loadClass(name);
}
catch (ClassNotFoundException cnfe)
{
Added: projects/ejb3/trunk/common/src/test/java/org/jboss/ejb3/test/common/classloader/unit/PrimitiveAwareClassLoaderTestCase.java
===================================================================
--- projects/ejb3/trunk/common/src/test/java/org/jboss/ejb3/test/common/classloader/unit/PrimitiveAwareClassLoaderTestCase.java (rev 0)
+++ projects/ejb3/trunk/common/src/test/java/org/jboss/ejb3/test/common/classloader/unit/PrimitiveAwareClassLoaderTestCase.java 2008-12-16 16:23:19 UTC (rev 82318)
@@ -0,0 +1,234 @@
+/*
+ * 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.ejb3.test.common.classloader.unit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.jboss.ejb3.common.classloader.PrimitiveAwareClassLoader;
+import org.jboss.logging.Logger;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * PrimitiveAwareClassLoaderTestCase
+ *
+ * Test case for {@link PrimitiveAwareClassLoader}
+ *
+ * @author Jaikiran Pai
+ * @version $Revision: $
+ */
+public class PrimitiveAwareClassLoaderTestCase
+{
+
+ private static final Map<String, Class<?>> nameToClassMapping = new HashMap<String, Class<?>>();
+
+ /**
+ * Logger
+ */
+ private static Logger logger = Logger.getLogger(PrimitiveAwareClassLoaderTestCase.class);
+
+ /**
+ * The instance of the classloader which we will be testing
+ */
+ private PrimitiveAwareClassLoader primitiveAwareClassLoader;
+
+ @BeforeClass
+ public static void beforeClass()
+ {
+ nameToClassMapping.put("void", void.class);
+ nameToClassMapping.put("boolean", boolean.class);
+ nameToClassMapping.put("int", int.class);
+ nameToClassMapping.put("long", long.class);
+ nameToClassMapping.put("float", float.class);
+ nameToClassMapping.put("double", double.class);
+ nameToClassMapping.put("char", char.class);
+ nameToClassMapping.put("byte", byte.class);
+ nameToClassMapping.put("short", short.class);
+ }
+
+ @Before
+ public void before()
+ {
+
+ this.primitiveAwareClassLoader = new PrimitiveAwareClassLoader(Thread.currentThread().getContextClassLoader());
+ }
+
+ /**
+ * Test that {@link Class} corresponding to the primitives are
+ * returned correctly through the {@link PrimitiveAwareClassLoader#loadClass(String)}
+ *
+ * @throws Throwable
+ */
+ @Test
+ public void testPrimitiveLoadThroughLoadClass() throws Throwable
+ {
+ // load all type of primitives (9 in all)
+ Iterator<Map.Entry<String, Class<?>>> primitives = nameToClassMapping.entrySet().iterator();
+ while (primitives.hasNext())
+ {
+ Map.Entry<String, Class<?>> primitive = primitives.next();
+ // test our classloader
+ Class<?> klass = primitiveAwareClassLoader.loadClass(primitive.getKey());
+ // ensure that it returned the right class
+ assertNotNull("loadClass from " + PrimitiveAwareClassLoader.class.getName() + " returned null", klass);
+ assertEquals("loadClass returned " + klass + " for " + primitive.getKey(), klass, primitive.getValue());
+ }
+
+ }
+
+ /**
+ * Test that the correct {@link Class} is returned for a primitive when
+ * {@link Class#forName(String, boolean, ClassLoader)} is used.
+ *
+ * @throws Throwable
+ */
+ @Test
+ public void testPrimitiveLoadThroughForName() throws Throwable
+ {
+
+ // load non-primitives through Class.forName()
+ // There's no support for loading the primitives through Class.forName
+ // using the PrimitiveAwareClassLoader (see EJBTHREE-1626 for comments).
+ // So no need to test that.
+
+ Class<?> klass = Class.forName("java.lang.Double", false, primitiveAwareClassLoader);
+ // ensure that it returned the right class
+ assertNotNull("Class.forName returned null with " + primitiveAwareClassLoader.getClass().getName(), klass);
+ assertEquals("Class.forName returned " + klass + " for java.lang.Double", java.lang.Double.class, klass);
+
+ }
+
+ /**
+ * Test that the non-primitive classes are loaded as usual when the
+ * {@link PrimitiveAwareClassLoader} is used.
+ *
+ * @throws Throwable
+ */
+ @Test
+ public void testOtherClassLoad() throws Throwable
+ {
+ // load Integer
+ Class<?> integerClass = this.primitiveAwareClassLoader.loadClass(Integer.class.getName());
+ assertNotNull("Integer class was not loaded. loadClass returned null", integerClass);
+ assertEquals("Incorrect class loaded for " + Integer.class.getName(), integerClass, Integer.class);
+
+ // load Double
+ Class<?> doubleClass = this.primitiveAwareClassLoader.loadClass(Double.class.getName());
+ assertNotNull("Double class was not loaded. loadClass returned null", doubleClass);
+ assertEquals("Incorrect class loaded for " + Double.class.getName(), doubleClass, Double.class);
+
+ // load Float
+ Class<?> floatClass = this.primitiveAwareClassLoader.loadClass(Float.class.getName());
+ assertNotNull("Float class was not loaded. loadClass returned null", floatClass);
+ assertEquals("Incorrect class loaded for " + Float.class.getName(), floatClass, Float.class);
+
+ // load Byte
+ Class<?> byteClass = this.primitiveAwareClassLoader.loadClass(Byte.class.getName());
+ assertNotNull("Byte class was not loaded. loadClass returned null", byteClass);
+ assertEquals("Incorrect class loaded for " + Byte.class.getName(), byteClass, Byte.class);
+
+ // load Character
+ Class<?> characterClass = this.primitiveAwareClassLoader.loadClass(Character.class.getName());
+ assertNotNull("Character class was not loaded. loadClass returned null", characterClass);
+ assertEquals("Incorrect class loaded for " + Character.class.getName(), characterClass, Character.class);
+
+ // load String
+ Class<?> stringClass = this.primitiveAwareClassLoader.loadClass(String.class.getName());
+ assertNotNull("String class was not loaded. loadClass returned null", stringClass);
+ assertEquals("Incorrect class loaded for " + String.class.getName(), stringClass, String.class);
+
+ // lets try one from outside the java.lang package
+ Class<?> bigDecimalClass = this.primitiveAwareClassLoader.loadClass(java.math.BigDecimal.class.getName());
+ assertNotNull("BigDecimal class was not loaded. loadClass returned null", bigDecimalClass);
+ assertEquals("Incorrect class loaded for " + BigDecimal.class.getName(), bigDecimalClass, BigDecimal.class);
+
+ // lets try loading this testcase
+ Class<?> thisTestCaseClass = this.primitiveAwareClassLoader.loadClass(this.getClass().getName());
+ assertNotNull(this.getClass().getName() + " class was not loaded. loadClass returned null", thisTestCaseClass);
+ assertEquals("Incorrect class loaded for " + this.getClass().getName(), thisTestCaseClass, this.getClass());
+
+ }
+
+ /**
+ * Test that arrays are loaded correctly.
+ *
+ * @throws Throwable
+ */
+ @Test
+ public void testLoadArray() throws Throwable
+ {
+
+ // lets load an primitive array
+ Class<?> primitiveClass = this.primitiveAwareClassLoader.loadClass(int[].class.getName());
+ assertNotNull("int array was not loaded", primitiveClass);
+ assertEquals("Incorrect class loaded for int array", int[].class, primitiveClass);
+ logger.debug("Successfully loaded primitve array");
+
+ // lets load an object array
+ Class<?> klass = this.primitiveAwareClassLoader.loadClass(String[].class.getName());
+ assertNotNull("String array could not be loaded", klass);
+ assertEquals("Incorrect class loaded for string array", String[].class, klass);
+ logger.debug("Successfully loaded object array");
+
+ }
+
+ /**
+ * Tests that the {@link PrimitiveAwareClassLoader} loads the primitives considering their
+ * case. The classloader should throw a {@link ClassNotFoundException} if "Int" is being requested
+ * for load instead of "int".
+ * @throws Throwable
+ */
+ @Test
+ public void testCaseSensitiveLoad() throws Throwable
+ {
+ // try with all type of primitives (9 in all)
+ Iterator<Map.Entry<String, Class<?>>> primitives = nameToClassMapping.entrySet().iterator();
+ while (primitives.hasNext())
+ {
+ Map.Entry<String, Class<?>> primitive = primitives.next();
+ try
+ {
+ String upperCaseName = primitive.getKey().toUpperCase();
+ // test our classloader
+ Class<?> klass = primitiveAwareClassLoader.loadClass(upperCaseName);
+ fail(PrimitiveAwareClassLoader.class.getName() + " is not case sensitive. Loaded " + klass + " for "
+ + upperCaseName);
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ // expected, so continue
+ continue;
+ }
+
+ }
+
+ }
+
+}
Property changes on: projects/ejb3/trunk/common/src/test/java/org/jboss/ejb3/test/common/classloader/unit/PrimitiveAwareClassLoaderTestCase.java
___________________________________________________________________
Name: svn:executable
+ *
More information about the jboss-cvs-commits
mailing list