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