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.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 }