FileDocCategorySizeDatePackage
ObjectStreamClassUtil_1_3.javaAPI DocJava SE 5 API18220Fri Aug 26 14:54:28 BST 2005com.sun.corba.se.impl.orbutil

ObjectStreamClassUtil_1_3

public final class ObjectStreamClassUtil_1_3 extends Object

Fields Summary
private static Comparator
compareClassByName
private static Comparator
compareMemberByName
private static Method
hasStaticInitializerMethod
Constructors Summary
Methods Summary
private static long_computeSerialVersionUID(java.lang.Class cl)

	ByteArrayOutputStream devnull = new ByteArrayOutputStream(512);

	long h = 0;
	try {
	    MessageDigest md = MessageDigest.getInstance("SHA");
	    DigestOutputStream mdo = new DigestOutputStream(devnull, md);
	    DataOutputStream data = new DataOutputStream(mdo);


	    data.writeUTF(cl.getName());

	    int classaccess = cl.getModifiers();
	    classaccess &= (Modifier.PUBLIC | Modifier.FINAL |
			    Modifier.INTERFACE | Modifier.ABSTRACT);

	    /* Workaround for javac bug that only set ABSTRACT for
	     * interfaces if the interface had some methods.
	     * The ABSTRACT bit reflects that the number of methods > 0.
	     * This is required so correct hashes can be computed
	     * for existing class files.
	     * Previously this hack was previously present in the VM.
	     */
            Method[] method = cl.getDeclaredMethods();
	    if ((classaccess & Modifier.INTERFACE) != 0) {
		classaccess &= (~Modifier.ABSTRACT);
		if (method.length > 0) {
		    classaccess |= Modifier.ABSTRACT;
		}
	    }

	    data.writeInt(classaccess);

	    /*
	     * Get the list of interfaces supported,
	     * Accumulate their names their names in Lexical order
	     * and add them to the hash
	     */
            if (!cl.isArray()) {
                /* In 1.2fcs, getInterfaces() was modified to return
                 * {java.lang.Cloneable, java.io.Serializable} when
                 * called on array classes.  These values would upset
                 * the computation of the hash, so we explicitly omit
                 * them from its computation.
                 */

	        Class interfaces[] = cl.getInterfaces();
	        Arrays.sort(interfaces, compareClassByName);

	        for (int i = 0; i < interfaces.length; i++) {
		    data.writeUTF(interfaces[i].getName());
	        }
	    }

	    /* Sort the field names to get a deterministic order */
            Field[] field = cl.getDeclaredFields();
	    Arrays.sort(field, compareMemberByName);

	    for (int i = 0; i < field.length; i++) {
		Field f = field[i];

		/* Include in the hash all fields except those that are
		 * private transient and private static.
		 */
		int m = f.getModifiers();
		if (Modifier.isPrivate(m) &&
		    (Modifier.isTransient(m) || Modifier.isStatic(m)))
		    continue;

		data.writeUTF(f.getName());
		data.writeInt(m);
		data.writeUTF(getSignature(f.getType()));
	    }

	    // need to find the java replacement for hasStaticInitializer
	    if (hasStaticInitializer(cl)) {
	 	data.writeUTF("<clinit>");
	 	data.writeInt(Modifier.STATIC); // TBD: what modifiers does it have
	 	data.writeUTF("()V");
	    }

	    /*
	     * Get the list of constructors including name and signature
	     * Sort lexically, add all except the private constructors
	     * to the hash with their access flags
	     */

	    MethodSignature[] constructors =
		MethodSignature.removePrivateAndSort(cl.getDeclaredConstructors());
	    for (int i = 0; i < constructors.length; i++) {
		MethodSignature c = constructors[i];
		String mname = "<init>";
		String desc = c.signature;
		desc = desc.replace('/", '.");
		data.writeUTF(mname);
		data.writeInt(c.member.getModifiers());
		data.writeUTF(desc);
	    }

	    /* Include in the hash all methods except those that are
	     * private transient and private static.
	     */
	    MethodSignature[] methods =
		MethodSignature.removePrivateAndSort(method);
	    for (int i = 0; i < methods.length; i++ ) {
		MethodSignature m = methods[i];
		String desc = m.signature;
		desc = desc.replace('/", '.");
		data.writeUTF(m.member.getName());
		data.writeInt(m.member.getModifiers());
		data.writeUTF(desc);
	    }

	    /* Compute the hash value for this class.
	     * Use only the first 64 bits of the hash.
	     */
	    data.flush();
	    byte hasharray[] = md.digest();
	    for (int i = 0; i < Math.min(8, hasharray.length); i++) {
		h += (long)(hasharray[i] & 255) << (i * 8);
	    }
	} catch (IOException ignore) {
	    /* can't happen, but be deterministic anyway. */
	    h = -1;
	} catch (NoSuchAlgorithmException complain) {
	    throw new SecurityException(complain.getMessage());
	}
	return h;
    
public static longcomputeSerialVersionUID(java.lang.Class cl)

	
	long csuid = ObjectStreamClass.getSerialVersionUID(cl);
	if (csuid == 0)
	    return csuid; // for non-serializable/proxy classes

	csuid = (ObjectStreamClassUtil_1_3.getSerialVersion(csuid, cl).longValue());
	return csuid;
    
public static longcomputeStructuralUID(boolean hasWriteObject, java.lang.Class cl)

	ByteArrayOutputStream devnull = new ByteArrayOutputStream(512);
		
	long h = 0;
	try {

	    if ((!java.io.Serializable.class.isAssignableFrom(cl)) ||
		(cl.isInterface())){
		return 0;
	    }
			
	    if (java.io.Externalizable.class.isAssignableFrom(cl)) {
		return 1;
	    }

	    MessageDigest md = MessageDigest.getInstance("SHA");
	    DigestOutputStream mdo = new DigestOutputStream(devnull, md);
	    DataOutputStream data = new DataOutputStream(mdo);

	    //In the old case, for the caller class, the write Method wasn't considered
	    // for rep-id calculations correctly, but for parent classes it was taken
	    // into account.  That is the reason there is the klude of getting the write
	    // Object method in there

	    // Get SUID of parent
	    Class parent = cl.getSuperclass();
	    if ((parent != null) && (parent != java.lang.Object.class)) {
	        boolean hasWriteObjectFlag = false;
	        Class [] args = {java.io.ObjectOutputStream.class};
                Method hasWriteObjectMethod = ObjectStreamClassUtil_1_3.getDeclaredMethod(parent, "writeObject", args,
	               Modifier.PRIVATE, Modifier.STATIC);
	        if (hasWriteObjectMethod != null)
	            hasWriteObjectFlag = true; 
		data.writeLong(ObjectStreamClassUtil_1_3.computeStructuralUID(hasWriteObjectFlag, parent));
	    }

	    if (hasWriteObject)
	        data.writeInt(2);
	    else
	        data.writeInt(1);

	    /* Sort the field names to get a deterministic order */
	    Field[] field = ObjectStreamClassUtil_1_3.getDeclaredFields(cl);
	    Arrays.sort(field, compareMemberByName);
			
	    for (int i = 0; i < field.length; i++) {
		Field f = field[i];
				
				/* Include in the hash all fields except those that are
				 * transient or static.
				 */
		int m = f.getModifiers();
		if (Modifier.isTransient(m) || Modifier.isStatic(m))
		    continue;
				
		data.writeUTF(f.getName());
		data.writeUTF(getSignature(f.getType()));
	    }
			
	    /* Compute the hash value for this class.
	     * Use only the first 64 bits of the hash.
	     */
	    data.flush();
	    byte hasharray[] = md.digest();
	    int minimum = Math.min(8, hasharray.length);
	    for (int i = minimum; i > 0; i--) {
		h += (long)(hasharray[i] & 255) << (i * 8);
	    }
	} catch (IOException ignore) {
	    /* can't happen, but be deterministic anyway. */
	    h = -1;
	} catch (NoSuchAlgorithmException complain) {
	    throw new SecurityException(complain.getMessage());
	}
	return h;
    
private static java.lang.reflect.Field[]getDeclaredFields(java.lang.Class clz)

        return (Field[]) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                return clz.getDeclaredFields();
            }
        });
    
private static java.lang.reflect.MethodgetDeclaredMethod(java.lang.Class cl, java.lang.String methodName, java.lang.Class[] args, int requiredModifierMask, int disallowedModifierMask)

        return (Method) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                Method method = null;
                try {
                    method =
                        cl.getDeclaredMethod(methodName, args);
                        int mods = method.getModifiers();
                        if ((mods & disallowedModifierMask) != 0 ||
                            (mods & requiredModifierMask) != requiredModifierMask) {
                            method = null;
                        } 
	                //if (!Modifier.isPrivate(mods) ||
	                //    Modifier.isStatic(mods)) {
	                //    method = null;
	                //}
                } catch (NoSuchMethodException e) {
                // Since it is alright if methodName does not exist,
                // no need to do anything special here.
                }
                return method;
	    }
	});
    
private static java.lang.LonggetSerialVersion(long csuid, java.lang.Class cl)

        return (Long) AccessController.doPrivileged(new PrivilegedAction() {
          public Object run() {
	    long suid;
	    try {
                final Field f = cl.getDeclaredField("serialVersionUID");
	        int mods = f.getModifiers();
	        if (Modifier.isStatic(mods) && 
                    Modifier.isFinal(mods) && Modifier.isPrivate(mods)) {
	            suid = csuid;
	         } else {
		    suid = _computeSerialVersionUID(cl);
	         }
	      } catch (NoSuchFieldException ex) {
	          suid = _computeSerialVersionUID(cl);
              //} catch (IllegalAccessException ex) {
              //     suid = _computeSerialVersionUID(cl);
              }
	      return new Long(suid);
	   }
	});
    
private static java.lang.StringgetSignature(java.lang.Class clazz)
Compute the JVM signature for the class.

	String type = null;
	if (clazz.isArray()) {
	    Class cl = clazz;
	    int dimensions = 0;
	    while (cl.isArray()) {
		dimensions++;
		cl = cl.getComponentType();
	    }
	    StringBuffer sb = new StringBuffer();
	    for (int i = 0; i < dimensions; i++) {
		sb.append("[");
	    }
	    sb.append(getSignature(cl));
	    type = sb.toString();
	} else if (clazz.isPrimitive()) {
	    if (clazz == Integer.TYPE) {
		type = "I";
	    } else if (clazz == Byte.TYPE) {
		type = "B";
	    } else if (clazz == Long.TYPE) {
		type = "J";
	    } else if (clazz == Float.TYPE) {
		type = "F";
	    } else if (clazz == Double.TYPE) {
		type = "D";
	    } else if (clazz == Short.TYPE) {
		type = "S";
	    } else if (clazz == Character.TYPE) {
		type = "C";
	    } else if (clazz == Boolean.TYPE) {
		type = "Z";
	    } else if (clazz == Void.TYPE) {
		type = "V";
	    }
	} else {
	    type = "L" + clazz.getName().replace('.", '/") + ";";
	}
	return type;
    
private static java.lang.StringgetSignature(java.lang.reflect.Method meth)

	StringBuffer sb = new StringBuffer();

	sb.append("(");

	Class[] params = meth.getParameterTypes(); // avoid clone
	for (int j = 0; j < params.length; j++) {
	    sb.append(getSignature(params[j]));
	}
	sb.append(")");
	sb.append(getSignature(meth.getReturnType()));
	return sb.toString();
    
private static java.lang.StringgetSignature(java.lang.reflect.Constructor cons)

	StringBuffer sb = new StringBuffer();

	sb.append("(");

	Class[] params = cons.getParameterTypes(); // avoid clone
	for (int j = 0; j < params.length; j++) {
	    sb.append(getSignature(params[j]));
	}
	sb.append(")V");
	return sb.toString();
    
private static booleanhasStaticInitializer(java.lang.Class cl)
Returns true if the given class defines a static initializer method, false otherwise.

                      
         
        if (hasStaticInitializerMethod == null) {
            Class classWithThisMethod = null;
            
            try {
                try {
                    // When using rip-int with Merlin or when this is a Merlin
                    // workspace, the method we want is in sun.misc.ClassReflector
                    // and absent from java.io.ObjectStreamClass.
                    //
                    // When compiling rip-int with JDK 1.3.x, we have to get it
                    // from java.io.ObjectStreamClass.
                    classWithThisMethod = Class.forName("sun.misc.ClassReflector");
                } catch (ClassNotFoundException cnfe) {
                    // Do nothing.  This is either not a Merlin workspace,
                    // or rip-int is being compiled with something other than
                    // Merlin, probably JDK 1.3.  Fall back on java.io.ObjectStreaClass.
                }
                if (classWithThisMethod == null)
                    classWithThisMethod = java.io.ObjectStreamClass.class;
                
                hasStaticInitializerMethod =
                    classWithThisMethod.getDeclaredMethod("hasStaticInitializer",
                                                          new Class[] { Class.class });
            } catch (NoSuchMethodException ex) {
            }
            
            if (hasStaticInitializerMethod == null) {
                throw new InternalError("Can't find hasStaticInitializer method on "
                                        + classWithThisMethod.getName());
            }
            hasStaticInitializerMethod.setAccessible(true);
        }
        try {
            Boolean retval = (Boolean)
                hasStaticInitializerMethod.invoke(null, new Object[] { cl });
            return retval.booleanValue();
        } catch (Exception ex) {
            throw new InternalError("Error invoking hasStaticInitializer: "
                                    + ex);
        }