View Javadoc
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 }