KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > SerialVersionUID


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */

15
16 package javassist;
17
18 import java.io.*;
19 import javassist.bytecode.*;
20 import java.util.*;
21 import java.security.*;
22
23 /**
24  * Utility for calculating serialVersionUIDs for Serializable classes.
25  *
26  * @author Bob Lee (crazybob@crazybob.org)
27  * @author modified by Shigeru Chiba
28  */

29 public class SerialVersionUID {
30
31     /**
32      * Adds serialVersionUID if one does not already exist. Call this before
33      * modifying a class to maintain serialization compatability.
34      */

35     public static void setSerialVersionUID(CtClass clazz)
36         throws CannotCompileException, NotFoundException
37     {
38         // check for pre-existing field.
39
try {
40             clazz.getDeclaredField("serialVersionUID");
41             return;
42         }
43         catch (NotFoundException e) {}
44
45         // check if the class is serializable.
46
if (!isSerializable(clazz))
47             return;
48             
49         // add field with default value.
50
CtField field = new CtField(CtClass.longType, "serialVersionUID",
51                                     clazz);
52         field.setModifiers(Modifier.PRIVATE | Modifier.STATIC |
53                            Modifier.FINAL);
54         clazz.addField(field, calculateDefault(clazz) + "L");
55     }
56
57     /**
58      * Does the class implement Serializable?
59      */

60     private static boolean isSerializable(CtClass clazz)
61         throws NotFoundException
62     {
63         ClassPool pool = clazz.getClassPool();
64         return clazz.subtypeOf(pool.get("java.io.Serializable"));
65     }
66     
67     /**
68      * Calculate default value. See Java Serialization Specification, Stream
69      * Unique Identifiers.
70      */

71     static long calculateDefault(CtClass clazz)
72         throws CannotCompileException
73     {
74         try {
75             ByteArrayOutputStream bout = new ByteArrayOutputStream();
76             DataOutputStream out = new DataOutputStream(bout);
77             ClassFile classFile = clazz.getClassFile();
78             
79             // class name.
80
String JavaDoc javaName = javaName(clazz);
81             out.writeUTF(javaName);
82             
83             // class modifiers.
84
out.writeInt(clazz.getModifiers() & (Modifier.PUBLIC |
85                 Modifier.FINAL | Modifier.INTERFACE | Modifier.ABSTRACT));
86            
87             // interfaces.
88
String JavaDoc[] interfaces = classFile.getInterfaces();
89             for (int i = 0; i < interfaces.length; i++)
90                 interfaces[i] = javaName(interfaces[i]);
91
92             Arrays.sort(interfaces);
93             for (int i = 0; i < interfaces.length; i++)
94                 out.writeUTF(interfaces[i]);
95             
96             // fields.
97
CtField[] fields = clazz.getDeclaredFields();
98             Arrays.sort(fields, new Comparator() {
99                 public int compare(Object JavaDoc o1, Object JavaDoc o2) {
100                     CtField field1 = (CtField)o1;
101                     CtField field2 = (CtField)o2;
102                     return field1.getName().compareTo(field2.getName());
103                 }
104             });
105
106             for (int i = 0; i < fields.length; i++) {
107                 CtField field = (CtField) fields[i];
108                 int mods = field.getModifiers();
109                 if (((mods & Modifier.PRIVATE) == 0) ||
110                     ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0)) {
111                     out.writeUTF(field.getName());
112                     out.writeInt(mods);
113                     out.writeUTF(field.getFieldInfo2().getDescriptor());
114                 }
115             }
116
117             // static initializer.
118
if (classFile.getStaticInitializer() != null) {
119                 out.writeUTF("<clinit>");
120                 out.writeInt(Modifier.STATIC);
121                 out.writeUTF("()V");
122             }
123
124             // constructors.
125
CtConstructor[] constructors = clazz.getDeclaredConstructors();
126             Arrays.sort(constructors, new Comparator() {
127                 public int compare(Object JavaDoc o1, Object JavaDoc o2) {
128                     CtConstructor c1 = (CtConstructor)o1;
129                     CtConstructor c2 = (CtConstructor)o2;
130                     return c1.getMethodInfo2().getDescriptor().compareTo(
131                                         c2.getMethodInfo2().getDescriptor());
132                 }
133             });
134
135             for (int i = 0; i < constructors.length; i++) {
136                 CtConstructor constructor = constructors[i];
137                 int mods = constructor.getModifiers();
138                 if ((mods & Modifier.PRIVATE) == 0) {
139                     out.writeUTF("<init>");
140                     out.writeInt(mods);
141                     out.writeUTF(constructor.getMethodInfo2()
142                                  .getDescriptor().replace('/', '.'));
143                 }
144             }
145
146             // methods.
147
CtMethod[] methods = clazz.getDeclaredMethods();
148             Arrays.sort(methods, new Comparator() {
149                 public int compare(Object JavaDoc o1, Object JavaDoc o2) {
150                     CtMethod m1 = (CtMethod)o1;
151                     CtMethod m2 = (CtMethod)o2;
152                     int value = m1.getName().compareTo(m2.getName());
153                     if (value == 0)
154                         value = m1.getMethodInfo2().getDescriptor()
155                             .compareTo(m2.getMethodInfo2().getDescriptor());
156
157                     return value;
158                 }
159             });
160
161             for (int i = 0; i < methods.length; i++) {
162                 CtMethod method = methods[i];
163                 int mods = method.getModifiers();
164                 if ((mods & Modifier.PRIVATE) == 0) {
165                     out.writeUTF(method.getName());
166                     out.writeInt(mods);
167                     out.writeUTF(method.getMethodInfo2()
168                                  .getDescriptor().replace('/', '.'));
169                 }
170             }
171
172             // calculate hash.
173
out.flush();
174             MessageDigest digest = MessageDigest.getInstance("SHA");
175             byte[] digested = digest.digest(bout.toByteArray());
176             long hash = 0;
177             for (int i = Math.min(digested.length, 8) - 1; i >= 0; i--)
178                 hash = (hash << 8) | (digested[i] & 0xFF);
179
180             return hash;
181         }
182         catch (IOException e) {
183             throw new CannotCompileException(e);
184         }
185         catch (NoSuchAlgorithmException e) {
186             throw new CannotCompileException(e);
187         }
188     }
189
190     private static String JavaDoc javaName(CtClass clazz) {
191         return Descriptor.toJavaName(Descriptor.toJvmName(clazz));
192     }
193
194     private static String JavaDoc javaName(String JavaDoc name) {
195         return Descriptor.toJavaName(Descriptor.toJvmName(name));
196     }
197 }
198
Popular Tags