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.isEmpty()) {
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 //noinspection RedundantIfStatement
97 if (name.charAt(pkg.length()) == '$') {
98 // prefix match of enclosing type
99 return true;
100 }
101 }
102 } else {
103 // a resource name, e.g. java/lang/Object.class
104
105 if (name.equals(pkg)) {
106 // exact match of resource name
107 return true;
108 }
109
110 pkg = pkg.replace('.', '/');
111
112 if (name.startsWith(pkg) && name.length() > pkg.length()) {
113 if (name.charAt(pkg.length()) == '/') {
114 // prefix match of package directory
115 return true;
116 } else if (name.charAt(pkg.length()) == '$') {
117 // prefix match of nested class file
118 return true;
119 } else //noinspection RedundantIfStatement
120 if (name.length() == pkg.length() + 6 && name.endsWith(".class")) {
121 // exact match of class file
122 return true;
123 }
124 }
125 }
126
127 return false;
128 } else {
129 return true;
130 }
131 }
132
133 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134 // java.lang.Comparable
135 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
136
137 /**
138 * Compare this entry to another for relative ordering.
139 * <p/>
140 * <p/>
141 * The natural ordering of Entry objects is reverse-alphabetical
142 * based upon package name.
143 * </p>
144 *
145 * @param that The object to compare.
146 * @return -1 if this object sorts before that object, 0
147 * if they are equal, or 1 if this object sorts
148 * after that object.
149 */
150 public int compareTo(Entry that) {
151 // We are reverse sorting this list, so that
152 // we get longer matches first:
153 //
154 // com.werken.foo.bar
155 // com.werken.foo
156 // com.werken
157
158 return -(getPackageName().compareTo(that.getPackageName()));
159 }
160
161 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
162 // java.lang.Object
163 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
164
165 /**
166 * Test this entry for equality to another.
167 * <p/>
168 * <p/>
169 * Consistent with {@link #compareTo}, this method tests
170 * for equality purely on the package name.
171 * </p>
172 *
173 * @param thatObj The object to compare
174 * @return <code>true</code> if the two objects are
175 * semantically equivalent, otherwise <code>false</code>.
176 */
177 public boolean equals(Object thatObj) {
178 Entry that = (Entry) thatObj;
179
180 return getPackageName().equals(that.getPackageName());
181 }
182
183 /**
184 * <p/>
185 * Consistent with {@link #equals}, this method creates a hashCode
186 * based on the packagename.
187 * </p>
188 */
189 public int hashCode() {
190 return getPackageName().hashCode();
191 }
192
193 public String toString() {
194 return "Entry[import " + getPackageName() + " from realm " + getClassLoader() + "]";
195 }
196 }