KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > loom > components > util > verifier > SarVerifier


1 /* ====================================================================
2  * Loom Software License, version 1.1
3  *
4  * Copyright (c) 2003, Loom Group. All rights reserved.
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. Neither the name of the Loom Group nor the name "Loom" nor
18  * the names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior
20  * written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * ====================================================================
36  *
37  * Loom includes code from the Apache Software Foundation
38  *
39  * ====================================================================
40  * The Apache Software License, Version 1.1
41  *
42  * Copyright (c) 1997-2003 The Apache Software Foundation. All rights
43  * reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions
47  * are met:
48  *
49  * 1. Redistributions of source code must retain the above copyright
50  * notice, this list of conditions and the following disclaimer.
51  *
52  * 2. Redistributions in binary form must reproduce the above copyright
53  * notice, this list of conditions and the following disclaimer in
54  * the documentation and/or other materials provided with the
55  * distribution.
56  *
57  * 3. The end-user documentation included with the redistribution,
58  * if any, must include the following acknowledgment:
59  * "This product includes software developed by the
60  * Apache Software Foundation (http://www.apache.org/)."
61  * Alternately, this acknowledgment may appear in the software
62  * itself, if and wherever such third-party acknowledgments
63  * normally appear.
64  *
65  * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
66  * must not be used to endorse or promote products derived from this
67  * software without prior written permission. For written
68  * permission, please contact apache@apache.org.
69  *
70  * 5. Products derived from this software may not be called "Apache",
71  * nor may "Apache" appear in their name, without prior written
72  * permission of the Apache Software Foundation.
73  *
74  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
75  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
76  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
77  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
78  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
79  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
80  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
81  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
82  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
83  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
84  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
85  * SUCH DAMAGE.
86  */

87 package org.codehaus.loom.components.util.verifier;
88
89 import org.codehaus.loom.components.util.metadata.ComponentTemplate;
90 import org.codehaus.loom.components.util.profile.ComponentProfile;
91 import org.codehaus.loom.components.util.profile.PartitionProfile;
92 import org.codehaus.loom.interfaces.ContainerConstants;
93 import org.codehaus.spice.salt.i18n.ResourceManager;
94 import org.codehaus.spice.salt.i18n.Resources;
95 import org.codehaus.dna.Logger;
96
97 /**
98  * This Class verifies that Sars are valid. It performs a number of checks to make sure that the Sar represents a valid
99  * application and excluding runtime errors will start up validly. Some of the checks it performs include;
100  *
101  * <ul> <li>Verify names of Sar, Blocks and BlockListeners contain only letters, digits or the '_' character.</li>
102  * <li>Verify that the names of the Blocks and BlockListeners are unique to Sar.</li> <li>Verify that the
103  * dependendencies specified in assembly.xml correspond to dependencies specified in BlockInfo files.</li> <li>Verify
104  * that the inter-block dependendencies specified in assembly.xml are valid. This essentially means that if Block A
105  * requires Service S from Block B then Block B must provide Service S.</li> <li>Verify that there are no circular
106  * dependendencies between blocks.</li> <li>Verify that the Class objects for Blocks support the Block interface and any
107  * specified Services.</li> <li>Verify that the Class objects for BlockListeners support the BlockListener
108  * interface.</li> </ul>
109  *
110  * @author Peter Donald
111  * @version $Revision: 1.3 $ $Date: 2004/08/17 23:14:32 $
112  */

113 public class SarVerifier
114     extends AssemblyVerifier
115 {
116     /**
117      * I18n utils.
118      */

119     private static final Resources REZ =
120         ResourceManager.getPackageResources( SarVerifier.class );
121
122     /**
123      * The Block class used to warn about deprecation.
124      */

125     private static final Class JavaDoc BLOCK_CLASS =
126         getClass( "org.apache.avalon.phoenix.Block" );
127
128     /**
129      * The BlockListener class used to warn about deprecation.
130      */

131     private static final Class JavaDoc BLOCKLISTENER_CLASS =
132         getClass( "org.apache.avalon.phoenix.BlockListener" );
133
134     /**
135      * The Verifier for Info instances.
136      */

137     private final ComponentVerifier m_infoVerifier = new ComponentVerifier();
138
139     public void enableLogging( final Logger logger )
140     {
141         super.enableLogging( logger );
142
143         setupLogger( m_infoVerifier );
144     }
145
146     /**
147      * Verify the specified {@link org.codehaus.loom.components.util.profile.PartitionProfile} object. The rules used
148      * to verify {@link org.codehaus.loom.components.util.profile.PartitionProfile} are specified in the Class
149      * javadocs.
150      *
151      * @param profile the Sar profile
152      * @param classLoader the classloader to load types from
153      *
154      * @throws Exception if an error occurs
155      */

156     public void verifySar( final PartitionProfile profile,
157                            final ClassLoader JavaDoc classLoader )
158         throws Exception JavaDoc
159     {
160         final ComponentProfile[] blocks =
161             profile.getPartition( ContainerConstants.BLOCK_PARTITION )
162             .getComponents();
163         final ComponentProfile[] listeners =
164             profile.getPartition( ContainerConstants.LISTENER_PARTITION )
165             .getComponents();
166
167         String JavaDoc message;
168
169         message = REZ.getString( "verify-valid-names" );
170         getLogger().info( message );
171         verifySarName( profile.getMetaData().getName() );
172         verifyValidNames( listeners );
173
174         super.verifyAssembly( blocks );
175
176         message = REZ.getString( "verify-unique-names" );
177         getLogger().info( message );
178         checkNamesUnique( blocks, listeners );
179
180         message = REZ.getString( "verify-block-type" );
181         getLogger().info( message );
182         verifyBlocksType( blocks, classLoader );
183
184         message = REZ.getString( "verify-listener-type" );
185         getLogger().info( message );
186         verifyListenersType( listeners, classLoader );
187     }
188
189     /**
190      * Verfiy that all Blocks specify classes that implement the advertised interfaces.
191      *
192      * @param blocks the ComponentProfile objects for the blocks
193      * @param classLoader the Classloader to load type from
194      *
195      * @throws Exception if an error occurs
196      */

197     private void verifyBlocksType( final ComponentProfile[] blocks,
198                                    final ClassLoader JavaDoc classLoader )
199         throws Exception JavaDoc
200     {
201         for( int i = 0; i < blocks.length; i++ )
202         {
203             verifyBlockType( blocks[i], classLoader );
204         }
205     }
206
207     /**
208      * Verfiy that specified Block designate classes that implement the advertised interfaces.
209      *
210      * @param block the BlockMetaData object for the blocks
211      * @param classLoader the classloader to load type from
212      *
213      * @throws Exception if an error occurs
214      */

215     private void verifyBlockType( final ComponentProfile block,
216                                   final ClassLoader JavaDoc classLoader )
217         throws Exception JavaDoc
218     {
219         final ComponentTemplate metaData = block.getTemplate();
220         final Class JavaDoc clazz = loadClass( "block", metaData, classLoader );
221
222         m_infoVerifier.verifyType( metaData.getName(),
223                                    block.getInfo().getType() );
224
225         if( BLOCK_CLASS.isAssignableFrom( clazz ) )
226         {
227             final String JavaDoc message =
228                 REZ.format( "verifier.implements-block.error",
229                             metaData.getName(),
230                             metaData.getImplementationKey() );
231             getLogger().error( message );
232             System.err.println( message );
233         }
234     }
235
236     private Class JavaDoc loadClass( final String JavaDoc type,
237                              final ComponentTemplate metaData,
238                              final ClassLoader JavaDoc classLoader )
239         throws Exception JavaDoc
240     {
241         try
242         {
243             return classLoader.loadClass( metaData.getImplementationKey() );
244         }
245         catch( final Exception JavaDoc e )
246         {
247             final String JavaDoc message =
248                 REZ.format( "bad-" + type + "-class",
249                             metaData.getName(),
250                             metaData.getImplementationKey(),
251                             e.getMessage() );
252             throw new Exception JavaDoc( message );
253         }
254     }
255
256     /**
257      * Verfiy that all listeners implement BlockListener.
258      *
259      * @param listeners the BlockListenerMetaData objects for the listeners
260      * @param classLoader the classloader to load type from
261      *
262      * @throws Exception if an error occurs
263      */

264     private void verifyListenersType( final ComponentProfile[] listeners,
265                                       final ClassLoader JavaDoc classLoader )
266         throws Exception JavaDoc
267     {
268         for( int i = 0; i < listeners.length; i++ )
269         {
270             verifyListenerType( listeners[i], classLoader );
271         }
272     }
273
274     /**
275      * Verfiy that specified Listener class implements the BlockListener interface.
276      *
277      * @param listener the BlockListenerMetaData object for the listener
278      * @param classLoader the classloader to laod type from
279      *
280      * @throws Exception if an error occurs
281      */

282     private void verifyListenerType( final ComponentProfile listener,
283                                      final ClassLoader JavaDoc classLoader )
284         throws Exception JavaDoc
285     {
286         final ComponentTemplate metaData = listener.getTemplate();
287         final Class JavaDoc clazz = loadClass( "listener", metaData, classLoader );
288         if( !BLOCKLISTENER_CLASS.isAssignableFrom( clazz ) )
289         {
290             final String JavaDoc message =
291                 REZ.format( "listener-noimpl-listener",
292                             metaData,
293                             metaData );
294             throw new Exception JavaDoc( message );
295         }
296     }
297
298     /**
299      * Verify that the Sat name specified is valid.
300      *
301      * @param name the sar name
302      *
303      * @throws Exception if an error occurs
304      */

305     private void verifySarName( final String JavaDoc name )
306         throws Exception JavaDoc
307     {
308         if( !isValidName( name ) )
309         {
310             final String JavaDoc message = REZ.format( "invalid-sar-name", name );
311             throw new Exception JavaDoc( message );
312         }
313     }
314
315     /**
316      * Return true if specified name is valid. Valid names consist of letters, digits or the '-' & '.' characters.
317      *
318      * @param name the name to check
319      *
320      * @return true if valid, false otherwise
321      */

322     public boolean isValidName( final String JavaDoc name )
323     {
324         final int size = name.length();
325         for( int i = 0; i < size; i++ )
326         {
327             final char ch = name.charAt( i );
328
329             if( !Character.isLetterOrDigit( ch ) && '-' != ch && '.' != ch )
330             {
331                 return false;
332             }
333         }
334
335         return true;
336     }
337
338     /**
339      * Verify that the names of the specified blocks and listeners are unique. It is not valid for the same name to be
340      * used in multiple Blocks and or BlockListeners.
341      *
342      * @param blocks the Blocks
343      * @param listeners the listeners
344      *
345      * @throws Exception if an error occurs
346      */

347     private void checkNamesUnique( final ComponentProfile[] blocks,
348                                    final ComponentProfile[] listeners )
349         throws Exception JavaDoc
350     {
351         for( int i = 0; i < blocks.length; i++ )
352         {
353             final String JavaDoc name = blocks[i].getTemplate().getName();
354             checkNameUnique( name, blocks, listeners, i, -1 );
355         }
356
357         for( int i = 0; i < listeners.length; i++ )
358         {
359             final String JavaDoc name = listeners[i].getTemplate().getName();
360             checkNameUnique( name, blocks, listeners, -1, i );
361         }
362     }
363
364     /**
365      * Verify that the specified name is unique among specified blocks and listeners except for those indexes
366      * specified.
367      *
368      * @param name the name to check for
369      * @param blocks the Blocks
370      * @param listeners the listeners
371      * @param blockIndex the index of block that is allowed to match in name (or -1 if name designates a listener)
372      * @param listenerIndex the index of listener that is allowed to match in name (or -1 if name designates a block)
373      *
374      * @throws Exception if an error occurs
375      */

376     private void checkNameUnique( final String JavaDoc name,
377                                   final ComponentProfile[] blocks,
378                                   final ComponentProfile[] listeners,
379                                   final int blockIndex,
380                                   final int listenerIndex )
381         throws Exception JavaDoc
382     {
383         //Verify no blocks have the same name
384
for( int i = 0; i < blocks.length; i++ )
385         {
386             final String JavaDoc other = blocks[i].getTemplate().getName();
387             if( blockIndex != i && name.equals( other ) )
388             {
389                 final String JavaDoc message = REZ.format( "duplicate-name", name );
390                 throw new Exception JavaDoc( message );
391             }
392         }
393
394         //Verify no listeners have the same name
395
for( int i = 0; i < listeners.length; i++ )
396         {
397             final String JavaDoc other = listeners[i].getTemplate().getName();
398             if( listenerIndex != i && name.equals( other ) )
399             {
400                 final String JavaDoc message = REZ.format( "duplicate-name", name );
401                 throw new Exception JavaDoc( message );
402             }
403         }
404     }
405
406     /**
407      * Load class with specified name and throw a IllegalStateException if unable to load class.
408      *
409      * @param classname the name of class to load
410      *
411      * @return the Class object
412      */

413     private static Class JavaDoc getClass( final String JavaDoc classname )
414     {
415         try
416         {
417             return Class.forName( classname );
418         }
419         catch( final ClassNotFoundException JavaDoc cnfe )
420         {
421             final String JavaDoc message = "Unable to locate class " +
422                 classname + " due to " + cnfe;
423             throw new IllegalStateException JavaDoc( message );
424         }
425     }
426 }
427
Popular Tags