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
25 implements Comparable<Entry>
26 {
27
28 final ClassLoader classLoader;
29
30 final String pkgName;
31
32 Entry( ClassLoader realm, String pkgName )
33 {
34 this.classLoader = realm;
35
36 this.pkgName = pkgName;
37 }
38
39 // ------------------------------------------------------------
40 // Instance methods
41 // ------------------------------------------------------------
42
43 /**
44 * Retrieve the class loader.
45 *
46 * @return The class loader.
47 */
48 ClassLoader getClassLoader()
49 {
50 return this.classLoader;
51 }
52
53 /**
54 * Retrieve the package name.
55 *
56 * @return The package name.
57 */
58 String getPackageName()
59 {
60 return this.pkgName;
61 }
62
63 /**
64 * Determine if the class/resource name matches the package
65 * described by this entry.
66 *
67 * @param name The class or resource name to test, must not be <code>null</code>.
68 * @return <code>true</code> if this entry matches the
69 * classname, otherwise <code>false</code>.
70 */
71 boolean matches( String name )
72 {
73 String pkg = getPackageName();
74
75 if ( pkg.endsWith( ".*" ) )
76 {
77 String pkgName;
78
79 if ( name.indexOf( '/' ) < 0 )
80 {
81 // a binary class name, e.g. java.lang.Object
82
83 int index = name.lastIndexOf( '.' );
84 pkgName = ( index < 0 ) ? "" : name.substring( 0, index );
85 }
86 else
87 {
88 // a resource name, e.g. java/lang/Object.class
89
90 int index = name.lastIndexOf( '/' );
91 pkgName = ( index < 0 ) ? "" : name.substring( 0, index ).replace( '/', '.' );
92 }
93
94 return pkgName.length() == pkg.length() - 2 && pkg.regionMatches( 0, pkgName, 0, pkgName.length() );
95 }
96 else if ( pkg.length() > 0 )
97 {
98 if ( name.indexOf( '/' ) < 0 )
99 {
100 // a binary class name, e.g. java.lang.Object
101
102 if ( name.startsWith( pkg ) )
103 {
104 if ( name.length() == pkg.length() )
105 {
106 // exact match of class name
107 return true;
108 }
109 else if ( name.charAt( pkg.length() ) == '.' )
110 {
111 // prefix match of package name
112 return true;
113 }
114 else if ( name.charAt( pkg.length() ) == '$' )
115 {
116 // prefix match of enclosing type
117 return true;
118 }
119 }
120 }
121 else
122 {
123 // a resource name, e.g. java/lang/Object.class
124
125 if ( name.equals( pkg ) )
126 {
127 // exact match of resource name
128 return true;
129 }
130
131 pkg = pkg.replace( '.', '/' );
132
133 if ( name.startsWith( pkg ) && name.length() > pkg.length() )
134 {
135 if ( name.charAt( pkg.length() ) == '/' )
136 {
137 // prefix match of package directory
138 return true;
139 }
140 else if ( name.charAt( pkg.length() ) == '$' )
141 {
142 // prefix match of nested class file
143 return true;
144 }
145 else if ( name.length() == pkg.length() + 6 && name.endsWith( ".class" ) )
146 {
147 // exact match of class file
148 return true;
149 }
150 }
151 }
152
153 return false;
154 }
155 else
156 {
157 return true;
158 }
159 }
160
161 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
162 // java.lang.Comparable
163 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
164
165 /**
166 * Compare this entry to another for relative ordering.
167 * <p/>
168 * <p/>
169 * The natural ordering of Entry objects is reverse-alphabetical
170 * based upon package name.
171 * </p>
172 *
173 * @param thatObj The object to compare.
174 * @return -1 if this object sorts before that object, 0
175 * if they are equal, or 1 if this object sorts
176 * after that object.
177 */
178 public int compareTo( Entry that )
179 {
180 // We are reverse sorting this list, so that
181 // we get longer matches first:
182 //
183 // com.werken.foo.bar
184 // com.werken.foo
185 // com.werken
186
187 return - ( getPackageName().compareTo( that.getPackageName() ) );
188 }
189
190 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
191 // java.lang.Object
192 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
193
194 /**
195 * Test this entry for equality to another.
196 * <p/>
197 * <p/>
198 * Consistent with {@link #compareTo}, this method tests
199 * for equality purely on the package name.
200 * </p>
201 *
202 * @param thatObj The object to compare
203 * @return <code>true</code> if the two objects are
204 * semantically equivalent, otherwise <code>false</code>.
205 */
206 public boolean equals( Object thatObj )
207 {
208 Entry that = (Entry) thatObj;
209
210 return getPackageName().equals( that.getPackageName() );
211 }
212
213 /**
214 * <p/>
215 * Consistent with {@link #equals}, this method creates a hashCode
216 * based on the packagename.
217 * </p>
218 */
219 public int hashCode()
220 {
221 return getPackageName().hashCode();
222 }
223
224 public String toString()
225 {
226 return "Entry[import " + getPackageName() + " from realm " + getClassLoader() + "]";
227 }
228 }