1 8 package org.codehaus.loom.components.util.verifier; 9 10 import java.util.ArrayList ; 11 import java.util.Stack ; 12 13 import org.codehaus.loom.components.util.info.ComponentInfo; 14 import org.codehaus.loom.components.util.info.DependencyDescriptor; 15 import org.codehaus.loom.components.util.info.ServiceDescriptor; 16 import org.codehaus.loom.components.util.metadata.DependencyDirective; 17 import org.codehaus.loom.components.util.profile.ComponentProfile; 18 import org.codehaus.spice.salt.i18n.ResourceManager; 19 import org.codehaus.spice.salt.i18n.Resources; 20 import org.codehaus.dna.AbstractLogEnabled; 21 22 40 public class AssemblyVerifier 41 extends AbstractLogEnabled 42 { 43 private static final Resources REZ = 44 ResourceManager.getPackageResources( AssemblyVerifier.class ); 45 46 54 public void verifyAssembly( final ComponentProfile[] components ) 55 throws Exception 56 { 57 String message; 58 59 message = REZ.getString( "assembly.valid-names.notice" ); 60 getLogger().info( message ); 61 verifyValidNames( components ); 62 63 message = REZ.getString( "assembly.unique-names.notice" ); 64 getLogger().info( message ); 65 checkNamesUnique( components ); 66 67 message = REZ.getString( "assembly.dependencies-mapping.notice" ); 68 getLogger().info( message ); 69 verifyValidDependencies( components ); 70 71 message = REZ.getString( "assembly.dependency-references.notice" ); 72 getLogger().info( message ); 73 verifyDependencyReferences( components ); 74 75 message = REZ.getString( "assembly.nocircular-dependencies.notice" ); 76 getLogger().info( message ); 77 verifyNoCircularDependencies( components ); 78 } 79 80 87 public void verifyValidDependencies( final ComponentProfile[] components ) 88 throws Exception 89 { 90 for( int i = 0; i < components.length; i++ ) 91 { 92 verifyDependenciesMap( components[ i ] ); 93 } 94 } 95 96 102 protected void verifyNoCircularDependencies( 103 final ComponentProfile[] components ) 104 throws Exception 105 { 106 for( int i = 0; i < components.length; i++ ) 107 { 108 final ComponentProfile component = components[ i ]; 109 110 final Stack stack = new Stack (); 111 stack.push( component ); 112 verifyNoCircularDependencies( component, components, stack ); 113 stack.pop(); 114 } 115 } 116 117 125 protected void verifyNoCircularDependencies( 126 final ComponentProfile component, 127 final ComponentProfile[] components, 128 final Stack stack ) 129 throws Exception 130 { 131 final ComponentProfile[] dependencies = getDependencies( component, 132 components ); 133 for( int i = 0; i < dependencies.length; i++ ) 134 { 135 final ComponentProfile dependency = dependencies[ i ]; 136 if( stack.contains( dependency ) ) 137 { 138 final String trace = getDependencyTrace( dependency, stack ); 139 final String message = 140 REZ.format( "assembly.circular-dependency.error", 141 component.getTemplate().getName(), 142 trace ); 143 throw new Exception ( message ); 144 } 145 146 stack.push( dependency ); 147 verifyNoCircularDependencies( dependency, components, stack ); 148 stack.pop(); 149 } 150 } 151 152 160 protected String getDependencyTrace( final ComponentProfile component, 161 final Stack stack ) 162 { 163 final StringBuffer sb = new StringBuffer (); 164 sb.append( "[ " ); 165 166 final String name = component.getTemplate().getName(); 167 final int size = stack.size(); 168 final int top = size - 1; 169 for( int i = top; i >= 0; i-- ) 170 { 171 final ComponentProfile other = (ComponentProfile)stack.get( i ); 172 if( top != i ) 173 { 174 sb.append( ", " ); 175 } 176 sb.append( other.getTemplate().getName() ); 177 178 if( other.getTemplate().getName().equals( name ) ) 179 { 180 break; 181 } 182 } 183 184 sb.append( ", " ); 185 sb.append( name ); 186 187 sb.append( " ]" ); 188 return sb.toString(); 189 } 190 191 199 protected ComponentProfile[] getDependencies( 200 final ComponentProfile component, 201 final ComponentProfile[] components ) 202 { 203 final ArrayList dependencies = new ArrayList (); 204 final DependencyDirective[] deps = 205 component.getTemplate().getDependencies(); 206 207 for( int i = 0; i < deps.length; i++ ) 208 { 209 final String name = deps[ i ].getProviderName(); 210 final ComponentProfile other = getComponentProfile( name, 211 components ); 212 dependencies.add( other ); 213 } 214 215 return (ComponentProfile[])dependencies.toArray( 216 new ComponentProfile[ 0 ] ); 217 } 218 219 225 protected void verifyDependencyReferences( 226 final ComponentProfile[] components ) 227 throws Exception 228 { 229 for( int i = 0; i < components.length; i++ ) 230 { 231 verifyDependencyReferences( components[ i ], components ); 232 } 233 } 234 235 243 protected void verifyDependencyReferences( 244 final ComponentProfile component, 245 final ComponentProfile[] others ) 246 throws Exception 247 { 248 final ComponentInfo info = component.getInfo(); 249 final DependencyDirective[] dependencies = component.getTemplate() 250 .getDependencies(); 251 252 for( int i = 0; i < dependencies.length; i++ ) 253 { 254 final DependencyDirective dependency = dependencies[ i ]; 255 final String providerName = dependency.getProviderName(); 256 final String key = dependency.getKey(); 257 final String type = info.getDependency( key ).getComponentType(); 258 259 final ComponentProfile provider = getComponentProfile( 261 providerName, others ); 262 if( null == provider ) 263 { 264 final String message = 265 REZ.format( "assembly.missing-dependency.error", 266 key, 267 providerName, 268 component.getTemplate().getName() ); 269 throw new Exception ( message ); 270 } 271 272 final ComponentInfo providerInfo = provider.getInfo(); 275 final ServiceDescriptor[] services = providerInfo.getServices(); 276 if( !hasMatchingService( type, services ) ) 277 { 278 final String message = 279 REZ.format( "assembly.dependency-missing-service.error", 280 providerName, 281 type, 282 component.getTemplate().getName() ); 283 throw new Exception ( message ); 284 } 285 } 286 } 287 288 295 protected ComponentProfile getComponentProfile( final String name, 296 final ComponentProfile[] components ) 297 { 298 for( int i = 0; i < components.length; i++ ) 299 { 300 ComponentProfile ComponentProfile = components[ i ]; 301 if( ComponentProfile.getTemplate().getName().equals( name ) ) 302 { 303 return components[ i ]; 304 } 305 } 306 307 return null; 308 } 309 310 316 protected void verifyValidNames( final ComponentProfile[] components ) 317 throws Exception 318 { 319 for( int i = 0; i < components.length; i++ ) 320 { 321 ComponentProfile ComponentProfile = components[ i ]; 322 final String name = ComponentProfile.getTemplate().getName(); 323 if( !isValidName( name ) ) 324 { 325 final String message = 326 REZ.format( "assembly.bad-name.error", name ); 327 throw new Exception ( message ); 328 } 329 } 330 } 331 332 339 protected boolean isValidName( final String name ) 340 { 341 final int size = name.length(); 342 for( int i = 0; i < size; i++ ) 343 { 344 final char ch = name.charAt( i ); 345 346 if( !Character.isLetterOrDigit( ch ) && '-' != ch ) 347 { 348 return false; 349 } 350 } 351 352 return true; 353 } 354 355 363 protected void checkNamesUnique( final ComponentProfile[] components ) 364 throws Exception 365 { 366 for( int i = 0; i < components.length; i++ ) 367 { 368 ComponentProfile ComponentProfile = components[ i ]; 369 final String name = ComponentProfile.getTemplate().getName(); 370 verifyUniqueName( components, name, i ); 371 } 372 } 373 374 382 private void verifyUniqueName( final ComponentProfile[] components, 383 final String name, 384 final int index ) 385 throws Exception 386 { 387 for( int i = 0; i < components.length; i++ ) 388 { 389 ComponentProfile ComponentProfile = components[ i ]; 390 final String other = 391 ComponentProfile.getTemplate().getName(); 392 if( index != i && other.equals( name ) ) 393 { 394 final String message = 395 REZ.format( "assembly.duplicate-name.error", name ); 396 throw new Exception ( message ); 397 } 398 } 399 } 400 401 409 protected void verifyDependenciesMap( final ComponentProfile component ) 410 throws Exception 411 { 412 final DependencyDirective[] dependencySet = 414 component.getTemplate().getDependencies(); 415 416 for( int i = 0; i < dependencySet.length; i++ ) 417 { 418 final String key = dependencySet[ i ].getKey(); 419 final ComponentInfo info = component.getInfo(); 420 final DependencyDescriptor descriptor = info.getDependency( key ); 421 422 if( null == descriptor ) 425 { 426 final String name = dependencySet[ i ].getProviderName(); 427 final String message = 428 REZ.format( "assembly.unknown-dependency.error", 429 name, 430 key, 431 component.getTemplate().getName() ); 432 throw new Exception ( message ); 433 } 434 } 435 436 final ComponentInfo info = component.getInfo(); 438 final DependencyDescriptor[] dependencies = info.getDependencies(); 439 for( int i = 0; i < dependencies.length; i++ ) 440 { 441 final DependencyDescriptor dependency = dependencies[ i ]; 442 final DependencyDirective dependencyMetaData = 443 component.getTemplate().getDependency( dependency.getKey() ); 444 445 if( null == dependencyMetaData && !dependency.isOptional() ) 448 { 449 final String message = 450 REZ.format( "assembly.unspecified-dependency.error", 451 dependency.getKey(), 452 component.getTemplate().getName() ); 453 throw new Exception ( message ); 454 } 455 } 456 } 457 458 467 protected boolean hasMatchingService( final String type, 468 final ServiceDescriptor[] candidates ) 469 { 470 for( int i = 0; i < candidates.length; i++ ) 471 { 472 final String otherClassname = candidates[ i ].getType(); 473 if( otherClassname.equals( type ) ) 474 { 475 return true; 476 } 477 } 478 479 return false; 480 } 481 } 482 | Popular Tags |