KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > make > ClassDependency


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.make;
31
32 import com.caucho.util.Crc64;
33 import com.caucho.vfs.PersistentDependency;
34
35 import java.lang.reflect.Field JavaDoc;
36 import java.lang.reflect.Method JavaDoc;
37 import java.lang.reflect.Modifier JavaDoc;
38 import java.util.Arrays JavaDoc;
39 import java.util.Comparator JavaDoc;
40 import java.util.logging.Level JavaDoc;
41 import java.util.logging.Logger JavaDoc;
42
43 /**
44  * Representing a class that might change.
45  */

46 public class ClassDependency implements PersistentDependency {
47   private final static Logger JavaDoc log
48     = Logger.getLogger(ClassDependency.class.getName());
49   
50   private Class JavaDoc _cl;
51
52   private boolean _checkFields = true;
53   private boolean _checkStatic = true;
54   private boolean _checkProtected = true;
55   private boolean _checkPrivate = true;
56
57   private boolean _isDigestModified;
58   private long _newDigest;
59
60   /**
61    * Creates the class dependency.
62    */

63   public ClassDependency(Class JavaDoc cl)
64   {
65     _cl = cl;
66   }
67
68   /**
69    * Create a new dependency with a given digest.
70    *
71    * @param cl the source class
72    * @param digest the MD5 digest
73    */

74   public ClassDependency(Class JavaDoc cl, long digest)
75   {
76     _cl = cl;
77
78     long newDigest = getDigest();
79
80     if (newDigest != digest) {
81       if (log.isLoggable(Level.FINE))
82         log.fine(_cl.getName() + " digest is modified (old=" + digest + ",new=" + newDigest + ")");
83
84       _isDigestModified = true;
85     }
86   }
87   
88   /**
89    * Returns true if the underlying resource has changed.
90    */

91   public boolean isModified()
92   {
93     return _isDigestModified;
94   }
95
96   /**
97    * Calculates a MD5 digest of the class.
98    */

99   public long getDigest()
100   {
101     try {
102       if (_newDigest != 0)
103     return _newDigest;
104       
105       if (_cl == null)
106         return -1;
107
108       long digest = 37;
109
110       digest = addDigest(digest, _cl);
111       
112       _newDigest = digest;
113     } catch (Throwable JavaDoc e) {
114       log.log(Level.FINER, e.toString(), e);
115
116       _newDigest = -1;
117     }
118
119     return _newDigest;
120   }
121
122   /**
123    * Calculates a MD5 digest of the class.
124    */

125   private long addDigest(long digest, Class JavaDoc cl)
126     throws Exception JavaDoc
127   {
128     if (_cl == null)
129       return digest;
130
131     digest = addDigest(digest, cl.getName());
132
133     digest = addDigest(digest, cl.getModifiers());
134
135     Class JavaDoc superClass = cl.getSuperclass();
136     if (superClass != null
137     && superClass.getName().startsWith("java.")
138     && ! superClass.getName().startsWith("javax.")) {
139       digest = addDigest(digest, superClass);
140     }
141
142     Class JavaDoc []interfaces = cl.getInterfaces();
143     Arrays.sort(interfaces, ClassComparator.CMP);
144     for (int i = 0; i < interfaces.length; i++)
145       digest = addDigest(digest, interfaces[i].getName());
146
147     if (_checkFields) {
148       Field JavaDoc []fields = cl.getDeclaredFields();
149
150       Arrays.sort(fields, FieldComparator.CMP);
151
152       for (int i = 0; i < fields.length; i++) {
153     int modifiers = fields[i].getModifiers();
154       
155     if (Modifier.isPrivate(modifiers) && ! _checkPrivate)
156       continue;
157     if (Modifier.isProtected(modifiers) && ! _checkProtected)
158       continue;
159           
160     digest = addDigest(digest, fields[i].getName());
161     digest = addDigest(digest, fields[i].getModifiers());
162     digest = addDigest(digest, fields[i].getType().getName());
163       }
164     }
165
166     Method JavaDoc []methods = cl.getDeclaredMethods();
167     Arrays.sort(methods, MethodComparator.CMP);
168       
169     for (int i = 0; i < methods.length; i++) {
170       Method JavaDoc method = methods[i];
171       int modifiers = method.getModifiers();
172
173       if (Modifier.isPrivate(modifiers) && ! _checkPrivate)
174     continue;
175       if (Modifier.isProtected(modifiers) && ! _checkProtected)
176     continue;
177       if (Modifier.isStatic(modifiers) && ! _checkStatic)
178     continue;
179           
180       digest = addDigest(digest, method.getName());
181       digest = addDigest(digest, method.getModifiers());
182       digest = addDigest(digest, method.getName());
183
184       Class JavaDoc []param = method.getParameterTypes();
185       for (int j = 0; j < param.length; j++)
186     digest = addDigest(digest, param[j].getName());
187
188       digest = addDigest(digest, method.getReturnType().getName());
189
190       Class JavaDoc []exn = method.getExceptionTypes();
191       Arrays.sort(exn, ClassComparator.CMP);
192       for (int j = 0; j < exn.length; j++)
193     digest = addDigest(digest, exn[j].getName());
194     }
195
196     return digest;
197   }
198
199   /**
200    * Returns a string which will recreate the dependency.
201    */

202   public String JavaDoc getJavaCreateString()
203   {
204     return ("new com.caucho.make.ClassDependency(" +
205             _cl.getName().replace('$', '.') + ".class, " + getDigest() + "L)");
206   }
207   
208   /**
209    * Adds the int to the digest.
210    */

211   private static long addDigest(long digest, long v)
212   {
213     digest = Crc64.generate(digest, (byte) (v >> 24));
214     digest = Crc64.generate(digest, (byte) (v >> 16));
215     digest = Crc64.generate(digest, (byte) (v >> 8));
216     digest = Crc64.generate(digest, (byte) v);
217
218     return digest;
219   }
220   
221   /**
222    * Adds the string to the digest using a UTF8 encoding.
223    */

224   private static long addDigest(long digest, String JavaDoc string)
225   {
226     return Crc64.generate(digest, string);
227   }
228
229   public int hashCode()
230   {
231     return _cl.hashCode();
232   }
233
234   public boolean equals(Object JavaDoc o)
235   {
236     if (o == this)
237       return true;
238     
239     if (! (o instanceof ClassDependency))
240       return false;
241
242     ClassDependency depend = (ClassDependency) o;
243
244     return _cl.equals(depend._cl);
245   }
246
247   static class ClassComparator implements Comparator JavaDoc<Class JavaDoc> {
248     static final ClassComparator CMP = new ClassComparator();
249     
250     public int compare(Class JavaDoc a, Class JavaDoc b)
251     {
252       if (a == b)
253     return 0;
254       else if (a == null)
255     return -1;
256       else if (b == null)
257     return 1;
258
259       return a.getName().compareTo(b.getName());
260     }
261   }
262
263   static class FieldComparator implements Comparator JavaDoc<Field JavaDoc> {
264     static final FieldComparator CMP = new FieldComparator();
265     
266     public int compare(Field JavaDoc a, Field JavaDoc b)
267     {
268       if (a == b)
269     return 0;
270       else if (a == null)
271     return -1;
272       else if (b == null)
273     return 1;
274
275       int cmp = a.getName().compareTo(b.getName());
276       if (cmp != 0)
277     return cmp;
278       
279       cmp = a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName());
280       if (cmp != 0)
281     return cmp;
282       
283       return a.getType().getName().compareTo(b.getType().getName());
284     }
285   }
286
287   static class MethodComparator implements Comparator JavaDoc<Method JavaDoc> {
288     static final MethodComparator CMP = new MethodComparator();
289     
290     public int compare(Method JavaDoc a, Method JavaDoc b)
291     {
292       if (a == b)
293     return 0;
294       else if (a == null)
295     return -1;
296       else if (b == null)
297     return 1;
298
299       int cmp = a.getName().compareTo(b.getName());
300       if (cmp != 0)
301     return cmp;
302
303       Class JavaDoc []paramA = a.getParameterTypes();
304       Class JavaDoc []paramB = b.getParameterTypes();
305
306       if (paramA.length < paramB.length)
307     return -1;
308       else if (paramB.length < paramA.length)
309     return 1;
310
311       for (int i = 0; i < paramA.length; i++) {
312     cmp = paramA[i].getName().compareTo(paramB[i].getName());
313     if (cmp != 0)
314       return cmp;
315       }
316       
317       cmp = a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName());
318       if (cmp != 0)
319     return cmp;
320       
321       return a.getReturnType().getName().compareTo(b.getReturnType().getName());
322     }
323   }
324 }
325
Popular Tags