KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > clirr > core > ClassSelector


1 //////////////////////////////////////////////////////////////////////////////
2
// Clirr: compares two versions of a java library for binary compatibility
3
// Copyright (C) 2003 - 2005 Lars Kühne
4
//
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
9
//
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
14
//
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
//////////////////////////////////////////////////////////////////////////////
19
package net.sf.clirr.core;
20
21 import org.apache.bcel.classfile.JavaClass;
22
23 import java.util.ArrayList JavaDoc;
24 import java.util.Iterator JavaDoc;
25
26 /**
27  * Given a JavaClass object, determines whether or not it is "selected",
28  * based on its class or package. This is used to select subsets of the
29  * classes available in a classpath for comparison or testing purposes.
30  *
31  * @author Simon Kitching
32  */

33 public final class ClassSelector implements ClassFilter
34 {
35     /** Class for implementing an enumeration. */
36     public static final class Mode
37     {
38         private Mode()
39         {
40         }
41     }
42
43     /** positive selection. */
44     public static final Mode MODE_IF = new Mode();
45     /** negative selection. */
46     public static final Mode MODE_UNLESS = new Mode();
47
48     private Mode mode;
49
50     private ArrayList JavaDoc packages = new ArrayList JavaDoc();
51     private ArrayList JavaDoc packageTrees = new ArrayList JavaDoc();
52     private ArrayList JavaDoc classes = new ArrayList JavaDoc();
53
54     /**
55      * Create a selector.
56      * <p>
57      * When mode is MODE_IF then a class is "selected" if-and-only-if
58      * the class matches one of the criteria defined via the addXXX methods.
59      * In other words, the criteria specify which classes are included
60      * (selected) in the resulting class set.
61      * <p>
62      * When mode is MODE_UNLESS, then a class is "selected" unless the class
63      * matches one of the criteria defined via the addXXX methods. In other
64      * words, the criteria specify which classes are excluded from the
65      * resulting class set.
66      */

67     public ClassSelector(Mode mode)
68     {
69         this.mode = mode;
70     }
71
72     /**
73      * Matches any class which is in the named package.
74      */

75     public void addPackage(String JavaDoc packageName)
76     {
77         packages.add(packageName);
78     }
79
80     /**
81      * Matches any class which is in the named package or any subpackage of it.
82      */

83     public void addPackageTree(String JavaDoc packageName)
84     {
85         packages.add(packageName);
86     }
87
88     /**
89      * Matches the class with exactly this name, plus any of its inner classes.
90      */

91     public void addClass(String JavaDoc classname)
92     {
93         classes.add(classname);
94     }
95
96     /**
97      * Return true if this class is one selected by the criteria stored
98      * in this object.
99      */

100     public boolean isSelected(JavaClass clazz)
101     {
102         if (isAnonymousInnerClass(clazz))
103         {
104             return false;
105         }
106
107         boolean matches = matchesCriteria(clazz);
108         if (mode == MODE_IF)
109         {
110             return matches;
111         }
112         else // mode == MODE_UNLESS
113
{
114             return !matches;
115         }
116     }
117
118     /**
119      * Return true if this class is an anonymous inner class.
120      * Not even developers working on a package would be interested
121      * in API changes in these classes...
122      */

123     private boolean isAnonymousInnerClass(JavaClass clazz)
124     {
125         String JavaDoc name = clazz.getClassName();
126         int dollarPos = name.indexOf('$');
127         if (dollarPos == -1)
128         {
129             return false;
130         }
131
132         for (int i = dollarPos + 1; i < name.length(); ++i)
133         {
134             if (!Character.isDigit(name.charAt(i)))
135             {
136                 return false;
137             }
138         }
139
140         // ok, we have a class name which contains a dollar sign, and
141
// every subsequent character is a digit.
142
return true;
143     }
144
145     /**
146      * Return true if this class matches one of the criteria stored
147      * in this object.
148      */

149     private boolean matchesCriteria(JavaClass clazz)
150     {
151         String JavaDoc packageName = clazz.getPackageName();
152         if (packages.contains(packageName))
153         {
154             return true;
155         }
156
157         for (Iterator JavaDoc i = packageTrees.iterator(); i.hasNext();)
158         {
159             String JavaDoc entry = (String JavaDoc) i.next();
160             if (packageName.startsWith(entry))
161             {
162                 if (packageName.length() == entry.length())
163                 {
164                     // they are exactly equal
165
return true;
166                 }
167
168                 if (packageName.charAt(entry.length()) == '.')
169                 {
170                     return true;
171                 }
172
173                 // else packagename is like "com.acmegadgets" and entryname
174
// is like "com.acme", which is not a match, so keep looking.
175
}
176         }
177
178         String JavaDoc className = clazz.getClassName();
179         for (Iterator JavaDoc i = classes.iterator(); i.hasNext();)
180         {
181             String JavaDoc entry = (String JavaDoc) i.next();
182
183             if (className.startsWith(entry))
184             {
185                 if (className.length() == entry.length())
186                 {
187                     // they are exactly equal
188
return true;
189                 }
190
191                 if (className.charAt(entry.length()) == '$')
192                 {
193                     // this is an inner class of the named class
194
return true;
195                 }
196             }
197         }
198
199         return false;
200     }
201 }
202
203
Popular Tags