1 package org.codehaus.plexus.classworlds.realm;
2
3 /*
4 * Copyright 2001-2006 Codehaus Foundation.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 /**
20 * Import description entry.
21 *
22 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
23 */
24 class Entry implements Comparable<Entry> {
25
26 final ClassLoader classLoader;
27
28 final String pkgName;
29
30 Entry(ClassLoader realm, String pkgName) {
31 this.classLoader = realm;
32
33 this.pkgName = pkgName;
34 }
35
36 // ------------------------------------------------------------
37 // Instance methods
38 // ------------------------------------------------------------
39
40 /**
41 * Retrieve the class loader.
42 *
43 * @return The class loader.
44 */
45 ClassLoader getClassLoader() {
46 return this.classLoader;
47 }
48
49 /**
50 * Retrieve the package name.
51 *
52 * @return The package name.
53 */
54 String getPackageName() {
55 return this.pkgName;
56 }
57
58 /**
59 * Determine if the class/resource name matches the package
60 * described by this entry.
61 *
62 * @param name The class or resource name to test, must not be <code>null</code>.
63 * @return <code>true</code> if this entry matches the
64 * classname, otherwise <code>false</code>.
65 */
66 boolean matches(String name) {
67 String pkg = getPackageName();
68
69 if (pkg.endsWith(".*")) {
70 String pkgName;
71
72 if (name.indexOf('/') < 0) {
73 // a binary class name, e.g. java.lang.Object
74
75 int index = name.lastIndexOf('.');
76 pkgName = (index < 0) ? "" : name.substring(0, index);
77 } else {
78 // a resource name, e.g. java/lang/Object.class
79
80 int index = name.lastIndexOf('/');
81 pkgName = (index < 0) ? "" : name.substring(0, index).replace('/', '.');
82 }
83
84 return pkgName.length() == pkg.length() - 2 && pkg.regionMatches(0, pkgName, 0, pkgName.length());
85 } else if (pkg.length() > 0) {
86 if (name.indexOf('/') < 0) {
87 // a binary class name, e.g. java.lang.Object
88
89 if (name.startsWith(pkg)) {
90 if (name.length() == pkg.length()) {
91 // exact match of class name
92 return true;
93 } else if (name.charAt(pkg.length()) == '.') {
94 // prefix match of package name
95 return true;
96 } else if (name.charAt(pkg.length()) == '$') {
97 // prefix match of enclosing type
98 return true;
99 }
100 }
101 } else {
102 // a resource name, e.g. java/lang/Object.class
103
104 if (name.equals(pkg)) {
105 // exact match of resource name
106 return true;
107 }
108
109 pkg = pkg.replace('.', '/');
110
111 if (name.startsWith(pkg) && name.length() > pkg.length()) {
112 if (name.charAt(pkg.length()) == '/') {
113 // prefix match of package directory
114 return true;
115 } else if (name.charAt(pkg.length()) == '$') {
116 // prefix match of nested class file
117 return true;
118 } else if (name.length() == pkg.length() + 6 && name.endsWith(".class")) {
119 // exact match of class file
120 return true;
121 }
122 }
123 }
124
125 return false;
126 } else {
127 return true;
128 }
129 }
130
131 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132 // java.lang.Comparable
133 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134
135 /**
136 * Compare this entry to another for relative ordering.
137 * <p/>
138 * <p/>
139 * The natural ordering of Entry objects is reverse-alphabetical
140 * based upon package name.
141 * </p>
142 *
143 * @param that The object to compare.
144 * @return -1 if this object sorts before that object, 0
145 * if they are equal, or 1 if this object sorts
146 * after that object.
147 */
148 public int compareTo(Entry that) {
149 // We are reverse sorting this list, so that
150 // we get longer matches first:
151 //
152 // com.werken.foo.bar
153 // com.werken.foo
154 // com.werken
155
156 return -(getPackageName().compareTo(that.getPackageName()));
157 }
158
159 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
160 // java.lang.Object
161 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
162
163 /**
164 * Test this entry for equality to another.
165 * <p/>
166 * <p/>
167 * Consistent with {@link #compareTo}, this method tests
168 * for equality purely on the package name.
169 * </p>
170 *
171 * @param thatObj The object to compare
172 * @return <code>true</code> if the two objects are
173 * semantically equivalent, otherwise <code>false</code>.
174 */
175 public boolean equals(Object thatObj) {
176 Entry that = (Entry) thatObj;
177
178 return getPackageName().equals(that.getPackageName());
179 }
180
181 /**
182 * <p/>
183 * Consistent with {@link #equals}, this method creates a hashCode
184 * based on the packagename.
185 * </p>
186 */
187 public int hashCode() {
188 return getPackageName().hashCode();
189 }
190
191 public String toString() {
192 return "Entry[import " + getPackageName() + " from realm " + getClassLoader() + "]";
193 }
194 }