KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > loom > classman > verifier > ClassLoaderVerifier


1 /*
2  * Copyright (C) The Spice Group. All rights reserved.
3  *
4  * This software is published under the terms of the Spice
5  * Software License version 1.1, a copy of which has been included
6  * with this distribution in the LICENSE.txt file.
7  */

8 package org.codehaus.loom.classman.verifier;
9
10 import org.codehaus.loom.classman.metadata.ClassLoaderMetaData;
11 import org.codehaus.loom.classman.metadata.ClassLoaderSetMetaData;
12 import org.codehaus.loom.classman.metadata.JoinMetaData;
13 import org.codehaus.spice.salt.i18n.ResourceManager;
14 import org.codehaus.spice.salt.i18n.Resources;
15
16 /**
17  * Verify ClassLoader set is valid. Validity is defined as <ul> <li>With
18  * exception of predefined names, all ClassLoader names should be defined
19  * starting with letters or '_' and then continuing with Alpha-Numeric
20  * characters, '-', '.' or '_'.</li> <li>No ClassLoader can have a parent
21  * ClassLoader that is not predefined or not defined in ClassLoaderSet.</li>
22  * <li>No "join" ClassLoader can link against a non-existent ClassLoader.</li>
23  * <li>No "join" ClassLoader can join multiple instances of same
24  * ClassLoader.</li> <li>No ClassLoader can have multiple entrys that point to
25  * the same location.</li> <li>No ClassLoader (either predefined, join or
26  * regular) can have the same name.</li> <li>The default ClassLoader must
27  * exist.</li> <li>There must be no circular dependencies between join
28  * classloaders.</li> </ul>
29  *
30  * @author Peter Donald
31  * @version $Revision: 1.1 $ $Date: 2004/04/19 22:19:26 $
32  */

33 public class ClassLoaderVerifier
34 {
35     /** i18n resources for used to present messages. */
36     private static final Resources REZ =
37         ResourceManager.getPackageResources( ClassLoaderVerifier.class );
38
39     public void verifyClassLoaderSet( final ClassLoaderSetMetaData set )
40         throws Exception JavaDoc
41     {
42         String JavaDoc message = null;
43
44         message = REZ.getString( "valid-names.notice" );
45         info( message );
46         verifyNames( set );
47
48         message = REZ.getString( "valid-parents.notice" );
49         info( message );
50         verifyParents( set );
51
52         message = REZ.getString( "valid-links.notice" );
53         info( message );
54         verifyLinks( set );
55
56         message = REZ.getString( "default-loader.notice" );
57         info( message );
58         verifyDefaultLoaderExists( set );
59
60         message = REZ.getString( "unique-classloader.notice" );
61         info( message );
62         verifyUniqueClassLoaderNames( set );
63
64         message = REZ.getString( "unique-joins.notice" );
65         info( message );
66         verifyUniqueJoinNames( set );
67
68         message = REZ.getString( "unique-predefined.notice" );
69         info( message );
70         verifyUniquePredefinedNames( set );
71
72         message = REZ.getString( "unique-joins-entrys.notice" );
73         info( message );
74         verifyUniqueJoinEntrys( set );
75
76         message = REZ.getString( "unique-classpath-entrys.notice" );
77         info( message );
78         verifyUniqueClassLoaderEntrys( set );
79
80         //TODO: Verify that the joins form a directed graph with no loops
81
}
82
83     /**
84      * Log an informational message. Sub-classes should overide this.
85      *
86      * @param message the message
87      */

88     protected void info( final String JavaDoc message )
89     {
90         //noop
91
}
92
93     /**
94      * Verify that all the classloaders have valid names.
95      *
96      * @throws Exception if validity check fails
97      */

98     private void verifyNames( ClassLoaderSetMetaData set )
99         throws Exception JavaDoc
100     {
101         final ClassLoaderMetaData[] classLoaders = set.getClassLoaders();
102         for( int i = 0; i < classLoaders.length; i++ )
103         {
104             final String JavaDoc name = classLoaders[ i ].getName();
105             verifyName( name );
106         }
107
108         final JoinMetaData[] joins = set.getJoins();
109         for( int i = 0; i < joins.length; i++ )
110         {
111             final String JavaDoc name = joins[ i ].getName();
112             verifyName( name );
113         }
114     }
115
116     /**
117      * Verify that all the classloaders have valid parents.
118      *
119      * @throws Exception if validity check fails
120      */

121     private void verifyParents( ClassLoaderSetMetaData set )
122         throws Exception JavaDoc
123     {
124         final ClassLoaderMetaData[] classLoaders = set.getClassLoaders();
125         for( int i = 0; i < classLoaders.length; i++ )
126         {
127             final ClassLoaderMetaData classLoader = classLoaders[ i ];
128             final String JavaDoc parent = classLoader.getParent();
129             if( !isLoaderDefined( parent, set ) )
130             {
131                 final String JavaDoc message =
132                     REZ.format( "invalid-parent.error",
133                                 classLoader.getName(),
134                                 parent );
135                 throw new Exception JavaDoc( message );
136             }
137         }
138     }
139
140     /**
141      * Verify that each join ClassLoader only links to ClassLoaders that exist.
142      *
143      * @throws Exception if validity check fails
144      */

145     private void verifyLinks( final ClassLoaderSetMetaData set )
146         throws Exception JavaDoc
147     {
148         final JoinMetaData[] joins = set.getJoins();
149         for( int i = 0; i < joins.length; i++ )
150         {
151             verifyLinks( joins[ i ], set );
152         }
153     }
154
155     /**
156      * Verify that each join ClassLoader only links to ClassLoaders that exist.
157      *
158      * @throws Exception if validity check fails
159      */

160     private void verifyLinks( final JoinMetaData join,
161                               final ClassLoaderSetMetaData set )
162         throws Exception JavaDoc
163     {
164         final String JavaDoc[] classloaders = join.getClassloaders();
165         for( int i = 0; i < classloaders.length; i++ )
166         {
167             final String JavaDoc classloader = classloaders[ i ];
168             if( !isLoaderDefined( classloader, set ) )
169             {
170                 final String JavaDoc message =
171                     REZ.format( "bad-join-link.error",
172                                 join.getName(),
173                                 classloader );
174                 throw new Exception JavaDoc( message );
175             }
176         }
177     }
178
179     /**
180      * Verify that all the classloaders have valid names.
181      *
182      * @throws Exception if validity check fails
183      */

184     private void verifyName( final String JavaDoc name )
185         throws Exception JavaDoc
186     {
187         final int size = name.length();
188         if( 0 == size )
189         {
190             final String JavaDoc message =
191                 REZ.format( "empty-name.error",
192                             name );
193             throw new Exception JavaDoc( message );
194         }
195         final char ch = name.charAt( 0 );
196         if( !Character.isLetter( ch ) &&
197             '_' != ch )
198         {
199             final String JavaDoc message =
200                 REZ.format( "name-invalid-start.error",
201                             name );
202             throw new Exception JavaDoc( message );
203         }
204
205         for( int i = 1; i < size; i++ )
206         {
207             final char c = name.charAt( i );
208             if( !Character.isLetterOrDigit( c ) &&
209                 '_' != c &&
210                 '-' != c &&
211                 '.' != c )
212             {
213                 final String JavaDoc message =
214                     REZ.format( "name-invalid-char.error",
215                                 name,
216                                 String.valueOf( c ) );
217                 throw new Exception JavaDoc( message );
218             }
219         }
220     }
221
222     /**
223      * Verify that each regular ClassLoader only contains unique entrys.
224      *
225      * @throws Exception if validity check fails
226      */

227     private void verifyUniqueClassLoaderEntrys(
228         final ClassLoaderSetMetaData set )
229         throws Exception JavaDoc
230     {
231         final ClassLoaderMetaData[] classLoaders = set.getClassLoaders();
232         for( int i = 0; i < classLoaders.length; i++ )
233         {
234             verifyUniqueClassLoaderEntrys( classLoaders[ i ] );
235         }
236     }
237
238     /**
239      * Verify that each regular ClassLoader only contains unique entrys.
240      *
241      * @throws Exception if validity check fails
242      */

243     private void verifyUniqueClassLoaderEntrys(
244         final ClassLoaderMetaData classLoader )
245         throws Exception JavaDoc
246     {
247         final String JavaDoc[] entrys = classLoader.getEntrys();
248         for( int i = 0; i < entrys.length; i++ )
249         {
250             final String JavaDoc location = entrys[ i ];
251             for( int j = i + 1; j < entrys.length; j++ )
252             {
253                 if( location.equals( entrys[ j ] ) )
254                 {
255                     final String JavaDoc message =
256                         REZ.format( "classloader-dup-entrys.error",
257                                     classLoader.getName(),
258                                     location );
259                     throw new Exception JavaDoc( message );
260                 }
261             }
262         }
263     }
264
265     /**
266      * Verify that each join only contains unique classloaders.
267      *
268      * @throws Exception if validity check fails
269      */

270     private void verifyUniqueJoinEntrys( final ClassLoaderSetMetaData set )
271         throws Exception JavaDoc
272     {
273         final JoinMetaData[] joins = set.getJoins();
274         for( int i = 0; i < joins.length; i++ )
275         {
276             verifyUniqueJoinEntrys( joins[ i ] );
277         }
278     }
279
280     /**
281      * Verify that specified join only contains unique classloaders.
282      *
283      * @throws Exception if validity check fails
284      */

285     private void verifyUniqueJoinEntrys( final JoinMetaData join )
286         throws Exception JavaDoc
287     {
288         final String JavaDoc[] classloaders = join.getClassloaders();
289         for( int j = 0; j < classloaders.length; j++ )
290         {
291             final String JavaDoc name = classloaders[ j ];
292             for( int k = j + 1; k < classloaders.length; k++ )
293             {
294                 final String JavaDoc other = classloaders[ k ];
295                 if( other.equals( name ) )
296                 {
297                     final String JavaDoc message =
298                         REZ.format( "join-dup-entrys.error",
299                                     join.getName(),
300                                     name );
301                     throw new Exception JavaDoc( message );
302                 }
303             }
304         }
305     }
306
307     /**
308      * Verify that the Predefined names are unique set.
309      *
310      * @throws Exception if validity check fails
311      */

312     private void verifyUniquePredefinedNames( final ClassLoaderSetMetaData set )
313         throws Exception JavaDoc
314     {
315         final String JavaDoc[] predefined = set.getPredefined();
316         for( int i = 0; i < predefined.length; i++ )
317         {
318             final String JavaDoc name = predefined[ i ];
319             for( int j = i + 1; j < predefined.length; j++ )
320             {
321                 final String JavaDoc other = predefined[ j ];
322                 if( other.equals( name ) )
323                 {
324                     final String JavaDoc message =
325                         REZ.format( "duplicate-name.error",
326                                     "predefined",
327                                     "predefined",
328                                     name );
329                     throw new Exception JavaDoc( message );
330                 }
331             }
332         }
333     }
334
335     /**
336      * Verify that the ClassLoader names are unique throughout the set.
337      *
338      * @param set the set of ClassLoader defs to search in
339      * @throws Exception if validity check fails
340      */

341     private void verifyUniqueClassLoaderNames(
342         final ClassLoaderSetMetaData set )
343         throws Exception JavaDoc
344     {
345         final ClassLoaderMetaData[] classLoaders = set.getClassLoaders();
346         for( int i = 0; i < classLoaders.length; i++ )
347         {
348             final ClassLoaderMetaData classLoader = classLoaders[ i ];
349             verifyUniqueName( set,
350                               classLoader.getName(),
351                               "classloader",
352                               classLoader );
353         }
354     }
355
356     /**
357      * Verify that the specified name is unique in set except for specified
358      * entity.
359      *
360      * @param set the set of classloaders
361      * @param name the name
362      * @param type the type of classloder (used for exception messages)
363      * @param entity the entity to skip (ie the one the name refers to)
364      * @throws Exception if validity check fails
365      */

366     private void verifyUniqueName( final ClassLoaderSetMetaData set,
367                                    final String JavaDoc name,
368                                    final String JavaDoc type,
369                                    final Object JavaDoc entity )
370         throws Exception JavaDoc
371     {
372         //Make sure our join does not have same name as a
373
//predefined ClassLoader
374
if( set.isPredefined( name ) )
375         {
376             final String JavaDoc message =
377                 REZ.format( "duplicate-name.error",
378                             type,
379                             "predefined",
380                             name );
381             throw new Exception JavaDoc( message );
382         }
383
384         //Make sure no joins have same name as our join
385
final JoinMetaData[] joins = set.getJoins();
386         for( int j = 0; j < joins.length; j++ )
387         {
388             final JoinMetaData other = joins[ j ];
389             if( other == entity )
390             {
391                 continue;
392             }
393             if( other.getName().equals( name ) )
394             {
395                 final String JavaDoc message =
396                     REZ.format( "duplicate-name.error",
397                                 type,
398                                 "join",
399                                 name );
400                 throw new Exception JavaDoc( message );
401             }
402         }
403
404         final ClassLoaderMetaData[] classLoaders = set.getClassLoaders();
405         for( int j = 0; j < classLoaders.length; j++ )
406         {
407             final ClassLoaderMetaData other = classLoaders[ j ];
408             if( other == entity )
409             {
410                 continue;
411             }
412             if( other.getName().equals( name ) )
413             {
414                 final String JavaDoc message =
415                     REZ.format( "duplicate-name.error",
416                                 type,
417                                 "classloader",
418                                 name );
419                 throw new Exception JavaDoc( message );
420             }
421         }
422     }
423
424     /**
425      * Verify that the join names are unique throughout the set.
426      *
427      * @param set the set of ClassLoader defs to search in
428      * @throws Exception if validity check fails
429      */

430     private void verifyUniqueJoinNames( final ClassLoaderSetMetaData set )
431         throws Exception JavaDoc
432     {
433         final JoinMetaData[] joins = set.getJoins();
434         for( int i = 0; i < joins.length; i++ )
435         {
436             final JoinMetaData join = joins[ i ];
437             verifyUniqueName( set,
438                               join.getName(),
439                               "join",
440                               join );
441         }
442     }
443
444     /**
445      * Verify that the default loader is defined.
446      *
447      * @param set the set of ClassLoader defs to search in
448      * @throws Exception if validity check fails
449      */

450     private void verifyDefaultLoaderExists( final ClassLoaderSetMetaData set )
451         throws Exception JavaDoc
452     {
453         final String JavaDoc name = set.getDefault();
454         if( !isLoaderDefined( name, set ) )
455         {
456             final String JavaDoc message =
457                 REZ.format( "missing-default-loader.error",
458                             name );
459             throw new Exception JavaDoc( message );
460         }
461     }
462
463     /**
464      * Return true if specified loader is defined in set.
465      *
466      * @param name the name of loader
467      * @param set the set to search
468      * @return true if specified loader is defined in set.
469      */

470     private boolean isLoaderDefined( final String JavaDoc name,
471                                      final ClassLoaderSetMetaData set )
472     {
473         if( set.isPredefined( name ) )
474         {
475             return true;
476         }
477         else if( null != set.getClassLoader( name ) )
478         {
479             return true;
480         }
481         else if( null != set.getJoin( name ) )
482         {
483             return true;
484         }
485         else
486         {
487             return false;
488         }
489     }
490 }
491
Popular Tags