KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jarg > PackageHandler


1 /* ====================================================================
2  * Copyright (c) 2002, Hidetoshi Ohuchi <hchacha@users.sourceforge.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the hchacha nor the names of its contributors
17  * may be used to endorse or promote products derived from this
18  * software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  * ====================================================================
33  */

34 package jarg;
35
36 import java.util.Map JavaDoc;
37 import java.util.TreeMap JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.Iterator JavaDoc;
40
41 import org.apache.bcel.classfile.*;
42
43 /**
44  * The class for handling the packages in the jar file.
45  *
46  * @version $Id: PackageHandler.java,v 1.8 2003/01/28 17:30:53 hchacha Exp $
47  * @author Hidetoshi Ohuchi &lt;hchacha@users.sourceforge.net&gt;
48  */

49 class PackageHandler {
50    private Jarg app;
51    String JavaDoc packagename;
52    Map JavaDoc classes = new TreeMap JavaDoc();
53
54    private NameCreater nc;
55    private Map JavaDoc rncls = new HashMap JavaDoc();
56    private Map JavaDoc rnsig = new HashMap JavaDoc();
57    private Map JavaDoc rnfld = new HashMap JavaDoc();
58    private Map JavaDoc rnmth = new HashMap JavaDoc();
59
60    PackageHandler(Jarg app, String JavaDoc packagename) {
61       this.app = app;
62       this.packagename = packagename;
63       this.nc = new NameCreater(packagename);
64    }
65
66    void addClassHandler(ClassHandler clsh) {
67       String JavaDoc key = clsh.classname;
68       this.classes.put(key, clsh);
69       clsh.setPackageHandler(this);
70
71       int cidx = clsh.packagename.length();
72       if (cidx > 0) {
73          cidx ++;
74       }
75       String JavaDoc str = clsh.classname.substring(cidx);
76       this.nc.addName(str);
77    }
78
79    void doCheckUsedClass(PackageCollection pkgcol) {
80       Iterator JavaDoc cit = this.classes.keySet().iterator();
81       while (cit.hasNext()) {
82          String JavaDoc ckey = (String JavaDoc)cit.next();
83          ClassHandler clsh = (ClassHandler)this.classes.get(ckey);
84          clsh.doCheckUsedClass(pkgcol);
85       }
86    }
87
88    void doOptimize() {
89       renmClass();
90       fixMethodOverride();
91       //
92
Iterator JavaDoc cit = this.classes.keySet().iterator();
93       while (cit.hasNext()) {
94          String JavaDoc ckey = (String JavaDoc)cit.next();
95          ClassHandler clsh = (ClassHandler)this.classes.get(ckey);
96          clsh.doOptimize();
97       }
98    }
99
100    private void renmClass() {
101       Iterator JavaDoc cit = this.classes.keySet().iterator();
102       while (cit.hasNext()) {
103          String JavaDoc ckey = (String JavaDoc)cit.next();
104          ClassHandler clsh = (ClassHandler)this.classes.get(ckey);
105          if (!clsh.isNative && clsh.isPackageScope) {
106             renmClass0(clsh);
107          }
108          if (!clsh.isNative) {
109             Field[] flds = clsh.jcls.getFields();
110             for (int i=0; i<flds.length; i++) {
111                renmField0(clsh, flds[i]);
112             }
113          }
114 // if (!clsh.isNative && clsh.isPackageScope) {
115
if (!clsh.isNative) {
116             Method[] mths = clsh.jcls.getMethods();
117             for (int i=0; i<mths.length; i++) {
118                renmMethod0(clsh, mths[i]);
119             }
120          }
121       }
122    }
123
124    private void fixMethodOverride() {
125       Iterator JavaDoc cit = this.classes.keySet().iterator();
126       while (cit.hasNext()) {
127          String JavaDoc ckey = (String JavaDoc)cit.next();
128          ClassHandler clsh = (ClassHandler)this.classes.get(ckey);
129          if (!clsh.isNative) {
130             Method[] mths = clsh.jcls.getMethods();
131             for (int i=0; i<mths.length; i++) {
132                fixMethodOverride0(clsh, mths[i]);
133             }
134          }
135       }
136    }
137
138    private void renmClass0(ClassHandler clsh) {
139       String JavaDoc pkgnm = clsh.packagename;
140       String JavaDoc clsnm = clsh.classname;
141       boolean isOptClass = true;
142       // check for command option
143
if (!app.isRenameClass) {
144          isOptClass = false;
145       }
146       // check for path
147
for (int i=0; i<app.excpPathes.length; i++) {
148          if (pkgnm.startsWith(app.excpPathes[i])) {
149             isOptClass = false;
150             break;
151          }
152       }
153       // check for package
154
if (isOptClass && app.excpPackages.contains(pkgnm)) {
155          isOptClass = false;
156       }
157       if (isOptClass && app.excpClasses.contains(clsnm)) {
158          isOptClass = false;
159       }
160       if (isOptClass) {
161          // rename
162
String JavaDoc oldnm = clsh.classname;
163          String JavaDoc newnm = nc.createNext();
164
165          int cidx = clsh.packagename.length();
166          if (cidx > 0) {
167             cidx ++;
168          }
169          String JavaDoc cnm = clsh.classname.substring(cidx);
170
171          if (cnm.length() <= newnm.length()) {
172             return;
173          }
174
175          if (clsh.packagename != null && clsh.packagename.length() > 0) {
176             newnm = clsh.packagename + "." + newnm;
177          }
178          rncls.put(oldnm, newnm);
179
180          String JavaDoc oldsig = "L" + oldnm.replace('.','/') + ";";
181          String JavaDoc newsig = "L" + newnm.replace('.','/') + ";";
182          rnsig.put(oldsig, newsig);
183
184          clsh.filename = newnm.replace('.','/') + ".class";
185          if (app.isVerboseRN) {
186             System.out.println("rename class " + oldnm + " -> " + newnm);
187          }
188       }
189    }
190
191    private void renmField0(ClassHandler clsh, Field fld) {
192       String JavaDoc clsnm = clsh.classname;
193       String JavaDoc fldnm = fld.getName();
194
195       // rename private field
196
boolean flg = false;
197
198       if (app.isRenameField && !fld.isPrivate() && !fld.isProtected() && !fld.isPublic()) {
199          // only package scope
200
if (!"this".equals(fldnm)
201          && !fldnm.startsWith("this$")
202          && !app.excpFields.contains(fldnm)
203          ) {
204             flg = true;
205          }
206       }
207       if (flg) {
208          String JavaDoc oldnm = clsnm + '!' + fldnm;
209          String JavaDoc newnm = clsh.ncF.createNext();
210
211          if (fldnm.length() <= newnm.length()) {
212             return;
213          }
214
215          rnfld.put(oldnm, newnm);
216
217          if (app.isVerboseRN) {
218             System.out.println("rename field " + clsnm + "!" + fldnm + " -> " + newnm);
219          }
220       }
221    }
222
223    private void renmMethod0(ClassHandler clsh, Method mth) {
224       String JavaDoc clsnm = clsh.classname;
225       String JavaDoc mthnm = mth.getName();
226       String JavaDoc sign = mth.getSignature();
227
228       // rename private field
229
boolean flg = false;
230
231       if (app.isRenameMethod && !mth.isPrivate() && !mth.isProtected() && !mth.isPublic() && !mth.isNative()) {
232          // only package scope
233
if (!"<init>".equals(mthnm)
234          && !"<clinit>".equals(mthnm)
235          && !app.excpMethods.contains(mthnm)
236          ) {
237             flg = true;
238          }
239       }
240       if (flg) {
241 // if (clsh.superclassname != null && clsh.superclassname.startsWith(clsh.packagename)) {
242
// // it is same package this class and super class.
243
// }
244
String JavaDoc oldnm = clsnm + '#' + mthnm + ' ' + sign;
245          String JavaDoc newnm = clsh.ncM.createNext();
246
247          if (mthnm.length() <= newnm.length()) {
248             return;
249          }
250
251          rnmth.put(oldnm, newnm);
252          if (app.isVerboseRN) {
253             System.out.println("rename method " + clsnm + "#" + mthnm + sign + " -> " + newnm);
254          }
255       }
256    }
257
258    private void fixMethodOverride0(ClassHandler clsh, Method mth) {
259       String JavaDoc clsnm = clsh.classname;
260       String JavaDoc mthnm = mth.getName();
261       String JavaDoc sign = mth.getSignature();
262
263       if (app.isRenameMethod && !mth.isPrivate() && !mth.isProtected() && !mth.isPublic() && !mth.isNative()) {
264          String JavaDoc oldnm = clsnm + '#' + mthnm + ' ' + sign;
265          if (rnmth.containsKey(oldnm)) {
266             fixMethodOverride0Chain(clsh, mthnm, sign);
267          }
268       }
269    }
270
271    private void fixMethodOverride0Chain(ClassHandler clsh, String JavaDoc mthnm, String JavaDoc sign) {
272       String JavaDoc clsnm = clsh.classname;
273       String JavaDoc supclsnm = clsh.superclassname;
274       if (supclsnm != null && supclsnm.startsWith(clsh.packagename) && !clsnm.equals(supclsnm)) {
275          // it is same package this class and super class.
276
if (this.classes.containsKey(supclsnm)) {
277             ClassHandler supclsh = (ClassHandler)this.classes.get(supclsnm);
278             fixMethodOverride0Chain(supclsh, mthnm, sign);
279          }
280          String JavaDoc supoldnm = supclsnm + '#' + mthnm + ' ' + sign;
281          if (rnmth.containsKey(supoldnm)) {
282             String JavaDoc supnewnm = (String JavaDoc)rnmth.get(supoldnm);
283             if (!supnewnm.endsWith("R")) {
284                supnewnm = supnewnm + 'R';
285                rnmth.put(supoldnm, supnewnm);
286             }
287             String JavaDoc oldnm = clsnm + '#' + mthnm + ' ' + sign;
288             String JavaDoc newnm = supnewnm;
289             rnmth.put(oldnm, newnm);
290             if (app.isVerboseRN) {
291                System.out.println("fix override method " + clsnm + "#" + mthnm + sign + " -> " + newnm);
292             }
293          }
294       }
295    }
296
297    private String JavaDoc convClassName0(String JavaDoc clsnm) {
298       String JavaDoc newnm = (String JavaDoc)rncls.get(clsnm);
299       if (newnm != null) {
300          return newnm;
301       }
302       return clsnm;
303    }
304
305    String JavaDoc convClassName(String JavaDoc clsnm) {
306       if (clsnm.indexOf('/') >= 0) {
307          clsnm = clsnm.replace('/','.');
308       }
309       if (clsnm.startsWith("[")) {
310          // case of the array
311
int idxst = clsnm.indexOf('L');
312          if (idxst < 0) {
313             // case of the primitive array
314
return clsnm;
315          } else {
316             // case of the class array
317
String JavaDoc ss = clsnm.substring(idxst+1, clsnm.length()-1);
318             String JavaDoc nn = convClassName0(ss);
319             String JavaDoc r = clsnm.substring(0, idxst+1) + nn + ";";
320             return r;
321          }
322       } else {
323          // case of the class
324
return convClassName0(clsnm);
325       }
326    }
327
328    private String JavaDoc convSignature0(String JavaDoc sign) {
329       String JavaDoc newsig = (String JavaDoc)rnsig.get(sign);
330       if (newsig != null) {
331          return newsig;
332       }
333       return sign;
334    }
335
336    String JavaDoc convSignature(String JavaDoc sign) {
337       if (sign.startsWith("[")) {
338          // case of the array
339
int idxst = sign.indexOf('L');
340          if (idxst < 0) {
341             // case of the primitive array
342
return sign;
343          } else {
344             // case of the class array
345
String JavaDoc ss = sign.substring(idxst);
346             String JavaDoc nn = convSignature0(ss);
347             String JavaDoc r = sign.substring(0, idxst) + nn;
348             return r;
349          }
350       } else if (sign.startsWith("L")) {
351          // case of the class
352
return convSignature0(sign);
353       } else {
354          // case of the primitive
355
return sign;
356       }
357    }
358
359    String JavaDoc convSignatureM(String JavaDoc sign) {
360       // ()V
361
int idxst = 0, idxed = 0;
362
363       for (;;) {
364          idxst = sign.indexOf('L', idxed);
365          if (idxst < 0) {
366             break;
367          }
368          idxed = sign.indexOf(';', idxst);
369          String JavaDoc s1 = sign.substring(idxst, idxed+1);
370          String JavaDoc ss = convSignature0(s1);
371          if (!s1.equals(ss)) {
372             sign = sign.substring(0, idxst) + ss + sign.substring(idxed+1);
373             idxed = sign.indexOf(';', idxst);
374          }
375       }
376       return sign;
377    }
378
379    String JavaDoc convFieldName(String JavaDoc clsnm, String JavaDoc fldnm) {
380       String JavaDoc clsfldnm = clsnm + '!' + fldnm;
381       String JavaDoc newnm = (String JavaDoc)rnfld.get(clsfldnm);
382       if (newnm != null) {
383          return newnm;
384       }
385       return fldnm;
386    }
387
388    String JavaDoc convMethodName(String JavaDoc clsnm, String JavaDoc mthnm, String JavaDoc signature) {
389       String JavaDoc clsmthnm = clsnm + '#' + mthnm + ' ' + signature;
390       String JavaDoc newnm = (String JavaDoc)rnmth.get(clsmthnm);
391       if (newnm != null) {
392          return newnm;
393       }
394       return mthnm;
395    }
396 }
397
Popular Tags