Fixes the java.utils.Arrays.ArrayList problem.  Do not create a covariant array for a subtype that is not visible to other types in the same package.  Updated logging for exposure information.

Review by: mmendez, spoon (pair prog)

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2873 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java
index 3a9bf67..a347f8a 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/SerializableTypeOracleBuilder.java
@@ -502,7 +502,7 @@
    * the same package.
    */
   private static boolean isAccessibleToClassesInSamePackage(JClassType type) {
-    if (type.isPrivate()) {
+    if (type.isPrivate() || type.isLocalType()) {
       return false;
     }
 
@@ -761,6 +761,21 @@
         if (leafClass != null) {
           JClassType[] leafSubtypes = leafClass.getErasedType().getSubtypes();
           for (JClassType leafSubtype : leafSubtypes) {
+            if (leafSubtype.isRawType() != null) {
+              /*
+               * Convert from a generic type into a parameterization of the said
+               * generic type where each argument is the type argument. The goal
+               * is have checkTypeInstantiable not check the type parameters.
+               */
+              JGenericType leafGenericSub = leafSubtype.isRawType().getBaseType();
+              leafSubtype = typeOracle.getParameterizedType(leafGenericSub,
+                  leafGenericSub.getTypeParameters());
+            }
+
+            if (!isAccessibleToClassesInSamePackage(leafSubtype)) {
+              continue;
+            }
+
             JArrayType covariantArray = getArrayType(typeOracle,
                 isArray.getRank(), leafSubtype);
             checkTypeInstantiable(localLogger, covariantArray, true, path);
@@ -879,6 +894,11 @@
           Path subtypePath = createSubtypePath(path, subtype, originalType);
           boolean subInstantiable = checkTypeInstantiableNoSubtypes(
               subtypeLogger, subtype, true, subtypePath);
+          if (!subInstantiable) {
+            // If the subtype is not instantiable do not check the arguments.
+            continue;
+          }
+
           JGenericType genericSub = subtype.isGenericType();
           if (genericSub != null) {
             TreeLogger paramsLogger = subtypeLogger.branch(TreeLogger.DEBUG,
@@ -914,7 +934,7 @@
              * included. In order to be certain, we would need to perform a full
              * unification between the query type and subtype.
              */
-            if (subInstantiable && isParameterized != null) {
+            if (isParameterized != null) {
               HashSet<JTypeParameter> typeParamsInQueryType = new HashSet<JTypeParameter>();
               recordTypeParametersIn(isParameterized, typeParamsInQueryType);
 
@@ -1098,6 +1118,7 @@
       final JArrayType arrayType, boolean isSpeculative, final Path parent) {
     TreeLogger branch = logger.branch(TreeLogger.DEBUG,
         "Analyzing component type:", null);
+
     return checkTypeInstantiable(branch, arrayType.getComponentType(),
         isSpeculative, createArrayComponentPath(arrayType, parent));
   }
@@ -1132,7 +1153,9 @@
     JField[] fields = classOrInterface.getFields();
     if (fields.length > 0) {
       TreeLogger localLogger = logger.branch(TreeLogger.DEBUG,
-          "Analyzing Fields:", null);
+          "Analyzing the fields of type '"
+              + classOrInterface.getParameterizedQualifiedSourceName()
+              + "' that qualify for serialization", null);
 
       for (JField field : fields) {
         if (!qualfiesForSerialization(localLogger, field)) {
@@ -1211,19 +1234,38 @@
     Path path = createTypeArgumentPath(parent, baseType, paramIndex, typeArg);
     int exposure = getTypeParameterExposure(baseType, paramIndex);
     switch (exposure) {
-      case EXPOSURE_DIRECT:
-        return checkTypeInstantiable(logger, typeArg, true, path)
+      case EXPOSURE_DIRECT: {
+        TreeLogger branch = logger.branch(
+            TreeLogger.DEBUG,
+            "Checking type argument "
+                + paramIndex
+                + " of type '"
+                + baseType.getParameterizedQualifiedSourceName()
+                + "' because it is directly exposed in this type or in one of its subtypes");
+        return checkTypeInstantiable(branch, typeArg, true, path)
             || mightNotBeExposed(baseType, paramIndex);
-
+      }
       case EXPOSURE_NONE:
         // Ignore this argument
+        logger.branch(TreeLogger.DEBUG, "Ignoring type argument " + paramIndex
+            + " of type '" + baseType.getParameterizedQualifiedSourceName()
+            + "' because it is not exposed in this or any subtype");
         return true;
 
-      default:
+      default: {
         assert (exposure >= EXPOSURE_MIN_BOUNDED_ARRAY);
-        return checkTypeInstantiable(logger, getArrayType(typeOracle, exposure,
+        TreeLogger branch = logger.branch(
+            TreeLogger.DEBUG,
+            "Checking type argument "
+                + paramIndex
+                + " of type '"
+                + baseType.getParameterizedQualifiedSourceName()
+                + "' because it is exposed as an array with a maximum dimension of "
+                + exposure + " in this type or one of its subtypes");
+        return checkTypeInstantiable(branch, getArrayType(typeOracle, exposure,
             typeArg), true, path)
             || mightNotBeExposed(baseType, paramIndex);
+      }
     }
   }
 
@@ -1357,7 +1399,6 @@
   }
 
   /**
-   * 
    * Returns a map from each parameter in the subtype to the set of parameters,
    * if any, in the supertype which constrain that parameter.
    */