Implement [JACKSON-802]

diff --git a/release-notes/VERSION b/release-notes/VERSION
index 90924b8..ac68299 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -13,6 +13,8 @@
    (reported by Erik G)
   * [JACKSON-794]: JDK 7 has new property for Exceptions ("suppressable"),
     needs to be ignored during deserialization
+  * [JACKSON-802]: Improvements to class loading to use both contextual
+    class loader and Class.forName, as necessary
   * [JACKSON-803]: Problems with Smile, parsing of long names
    (reported by D Lam)
 
diff --git a/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/ClassNameIdResolver.java b/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/ClassNameIdResolver.java
index c8ddace..c9fd65e 100644
--- a/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/ClassNameIdResolver.java
+++ b/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/ClassNameIdResolver.java
@@ -51,12 +51,7 @@
             return t;
         }
         try {
-            /* [JACKSON-350]: Default Class.forName() won't work too well; context class loader
-             *    seems like slightly better choice
-             */
-//          Class<?> cls = Class.forName(id);
-            ClassLoader loader = Thread.currentThread().getContextClassLoader();
-            Class<?> cls = Class.forName(id, true, loader);
+            Class<?> cls =  ClassUtil.findClass(id);
             return _typeFactory.constructSpecializedType(_baseType, cls);
         } catch (ClassNotFoundException e) {
             throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): no such class found");
diff --git a/src/mapper/java/org/codehaus/jackson/map/type/TypeParser.java b/src/mapper/java/org/codehaus/jackson/map/type/TypeParser.java
index 5d8a68f..f53ccb2 100644
--- a/src/mapper/java/org/codehaus/jackson/map/type/TypeParser.java
+++ b/src/mapper/java/org/codehaus/jackson/map/type/TypeParser.java
@@ -3,6 +3,7 @@
 import java.util.*;
 
 import org.codehaus.jackson.type.JavaType;
+import org.codehaus.jackson.map.util.ClassUtil;
 
 /**
  * Simple recursive-descent parser for parsing canonical {@link JavaType}
@@ -70,12 +71,7 @@
     protected Class<?> findClass(String className, MyTokenizer tokens)
     {
         try {
-            /* [JACKSON-350]: Default Class.forName() won't work too well; context class loader
-             *    seems like slightly better choice
-             */
-//          return Class.forName(className);
-            ClassLoader loader = Thread.currentThread().getContextClassLoader();
-            return Class.forName(className, true, loader);
+	    return ClassUtil.findClass(className);
         } catch (Exception e) {
             if (e instanceof RuntimeException) {
                 throw (RuntimeException) e;
diff --git a/src/mapper/java/org/codehaus/jackson/map/util/ClassUtil.java b/src/mapper/java/org/codehaus/jackson/map/util/ClassUtil.java
index a58d486..7b04299 100644
--- a/src/mapper/java/org/codehaus/jackson/map/util/ClassUtil.java
+++ b/src/mapper/java/org/codehaus/jackson/map/util/ClassUtil.java
@@ -211,6 +211,50 @@
             (Class<?>) classOrInstance : classOrInstance.getClass();
         return cls.getName();
     }
+
+    /*
+    /**********************************************************
+    /* Class loading
+    /**********************************************************
+     */
+
+    public static Class<?> findClass(String className) throws ClassNotFoundException
+    {
+        // [JACKSON-597]: support primitive types (and void)
+        if (className.indexOf('.') < 0) {
+            if ("int".equals(className)) return Integer.TYPE;
+            if ("long".equals(className)) return Long.TYPE;
+            if ("float".equals(className)) return Float.TYPE;
+            if ("double".equals(className)) return Double.TYPE;
+            if ("boolean".equals(className)) return Boolean.TYPE;
+            if ("byte".equals(className)) return Byte.TYPE;
+            if ("char".equals(className)) return Character.TYPE;
+            if ("short".equals(className)) return Short.TYPE;
+            if ("void".equals(className)) return Void.TYPE;
+        }
+        // Two-phase lookup: first using context ClassLoader; then default
+        Throwable prob = null;
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+        
+        if (loader != null) {
+            try {
+                return Class.forName(className, true, loader);
+            } catch (Exception e) {
+                prob = getRootCause(e);
+            }
+        }
+        try {
+            return Class.forName(className);
+        } catch (Exception e) {
+            if (prob == null) {
+                prob = getRootCause(e);
+            }
+        }
+        if (prob instanceof RuntimeException) {
+            throw (RuntimeException) prob;
+        }
+        throw new ClassNotFoundException(prob.getMessage(), prob);
+    }
     
     /*
     /**********************************************************