1 17 18 package org.sape.carbon.core.component.factory; 19 20 import java.lang.reflect.Method ; 21 import java.lang.reflect.Proxy ; 22 import java.util.Arrays ; 23 import java.util.HashSet ; 24 import java.util.Iterator ; 25 import java.util.Set ; 26 27 import org.sape.carbon.core.component.Component; 28 import org.sape.carbon.core.component.ComponentConfiguration; 29 import org.sape.carbon.core.component.ComponentNotFoundException; 30 import org.sape.carbon.core.component.FunctionalInterface; 31 import org.sape.carbon.core.component.lifecycle.LifecycleInterceptor; 32 import org.sape.carbon.core.component.proxy.ComponentProxyInvocationHandler; 33 import org.sape.carbon.core.component.proxy.Decorator; 34 import org.sape.carbon.core.component.proxy.DecoratorFactory; 35 import org.sape.carbon.core.config.Config; 36 import org.sape.carbon.core.config.Configuration; 37 import org.sape.carbon.core.config.ConfigurationNotFoundException; 38 import org.sape.carbon.core.config.ConfigurationRuntimeException; 39 import org.sape.carbon.core.config.InvalidConfigurationException; 40 import org.sape.carbon.core.util.reflection.ClassUtil; 41 42 import org.apache.commons.logging.Log; 43 import org.apache.commons.logging.LogFactory; 44 45 46 58 public class DefaultComponentFactory implements ComponentFactory { 59 60 61 62 63 64 65 66 69 private Log log = LogFactory.getLog(this.getClass()); 70 71 72 78 public Component getInstance(String logicalComponentName) { 79 80 if (log.isTraceEnabled()) { 81 log.trace("Building new component: [" + logicalComponentName + "]"); 82 } 83 84 ComponentConfiguration componentConfiguration = 86 getComponentConfig(logicalComponentName); 87 88 Component requestedComponent = 90 assembleComponent(componentConfiguration); 91 92 initializeComponent(requestedComponent); 94 95 return requestedComponent; 96 } 97 98 104 private ComponentConfiguration getComponentConfig( 105 String logicalComponentName) { 106 Configuration config = null; 107 try { 108 config = 109 Config.getInstance().fetchWritableConfiguration(logicalComponentName); 110 111 return (ComponentConfiguration) config; 112 113 } catch (ConfigurationNotFoundException cre) { 114 throw new ComponentNotFoundException( 115 this.getClass(), 116 logicalComponentName, 117 cre); 118 } catch (ClassCastException cce) { 119 throw new InvalidConfigurationException( 120 this.getClass(), 121 logicalComponentName, 122 "ConfigurationInterface", 123 "Unable to create component configuration as the " 124 + "implementing class is not assignable from " 125 + "ComponentConfiguration", 126 cce); 127 } 128 } 129 130 147 private Component assembleComponent( 148 ComponentConfiguration componentConfiguration) { 149 150 151 FunctionalInterface functionalImplementation = 153 buildFunctionalImplementation(componentConfiguration); 154 155 ComponentTemplateConfiguration componentTemplateConfiguration = 160 getComponentTemplateConfiguration(componentConfiguration); 161 162 ComponentProxyInvocationHandler proxy = 164 buildProxyInvocationHandler(componentTemplateConfiguration); 165 166 proxy.setComponentName(componentConfiguration.getConfigurationName()); 169 170 Class [] functionalInterface = 173 new Class [] {componentConfiguration.getFunctionalInterface()}; 174 175 proxy.setFunctionalImplementation( 176 ClassUtil.getSuperInterfaces(functionalInterface), 177 functionalImplementation); 178 179 185 Set componentInterfaces = new HashSet (); 187 188 componentInterfaces.add( 191 componentConfiguration.getFunctionalInterface()); 192 componentInterfaces.add(Component.class); 193 194 197 Set decoratorSet = new HashSet (); 199 200 DecoratorConfiguration[] decoratorConfigurations = 201 componentTemplateConfiguration.getDecoratorConfiguration(); 202 203 for (int i = 0; i < decoratorConfigurations.length; i++) { 204 Decorator decorator = 206 buildDecorator( 207 decoratorConfigurations[i], 208 functionalImplementation, 209 componentConfiguration, 210 proxy); 211 212 Class [] decoratorInterfaces = decorator.getExposedInterfaces(); 214 for (int j = 0; j < decoratorInterfaces.length; j++) { 215 componentInterfaces.add(decoratorInterfaces[j]); 216 } 217 218 proxy.addDecorator(decorator); 220 221 decoratorSet.add(decorator); 224 } 225 226 227 229 checkAllMethodNames(componentInterfaces, proxy.getComponentName()); 231 232 Class [] componentInterfacesArray = 233 (Class []) componentInterfaces.toArray( 234 new Class [componentInterfaces.size()]); 235 236 Component requestedComponent = 237 (Component) 238 Proxy.newProxyInstance( 239 this.getClass().getClassLoader(), 240 componentInterfacesArray, 241 proxy); 242 243 Iterator decoratorIterator = decoratorSet.iterator(); 245 while (decoratorIterator.hasNext()) { 246 Decorator decorator = (Decorator) decoratorIterator.next(); 247 decorator.setComponentReference(requestedComponent); 248 } 249 250 return requestedComponent; 251 } 252 253 259 private void initializeComponent(Component component) { 260 ((LifecycleInterceptor) component).initializeComponent(component); 261 } 262 263 269 private FunctionalInterface buildFunctionalImplementation( 270 ComponentConfiguration componentConfiguration) { 271 272 273 try { 274 Class functionInterface = 275 componentConfiguration.getFunctionalInterface(); 276 277 if (functionInterface == null) { 278 throw new InvalidConfigurationException( 279 this.getClass(), 280 componentConfiguration.getConfigurationName(), 281 "FunctionalInterface", 282 "Component configurations must provide a Functional " + 283 "Interface class."); 284 } 285 286 Class functionalImplementation = 287 componentConfiguration.getFunctionalImplementationClass(); 288 289 if (functionalImplementation == null) { 290 throw new InvalidConfigurationException( 291 this.getClass(), 292 componentConfiguration.getConfigurationName(), 293 "FunctionalImplementationClass", 294 "Component configurations must provide a Functional " + 295 "Implementation class."); 296 } 297 298 if (!functionInterface 300 .isAssignableFrom(functionalImplementation)) { 301 throw new InvalidConfigurationException( 302 this.getClass(), 303 componentConfiguration.getConfigurationName(), 304 "FunctionalImplementationClass", 305 "The configured functional implementation class [" 306 + functionalImplementation.getName() 307 + "] does not implement configured " 308 + "FunctionalInterface [" 309 + functionInterface.getName() 310 + "]"); 311 } 312 313 return (FunctionalInterface) functionalImplementation.newInstance(); 315 316 } catch (ClassCastException cce) { 317 throw new InvalidConfigurationException( 318 this.getClass(), 319 componentConfiguration.getConfigurationName(), 320 "FunctionalInterface", 321 "The configured functional interface [" 322 + componentConfiguration.getFunctionalInterface().getName() 323 + "] does not extend " 324 + FunctionalInterface.class.getName(), 325 cce); 326 327 } catch (InstantiationException ie) { 328 throw new InvalidConfigurationException( 329 this.getClass(), 330 componentConfiguration.getConfigurationName(), 331 "FunctionalImplementationClass", 332 "Could not instantiate functional implementation class [" 333 + componentConfiguration 334 .getFunctionalImplementationClass() 335 .getName() 336 + "]", 337 ie); 338 339 } catch (IllegalAccessException iae) { 340 throw new InvalidConfigurationException( 341 this.getClass(), 342 componentConfiguration.getConfigurationName(), 343 "FunctionalImplementationClass", 344 "Could not instantiate functional implementation class [" 345 + componentConfiguration 346 .getFunctionalImplementationClass() 347 .getName() 348 + "]", 349 iae); 350 } 351 } 352 353 361 private ComponentProxyInvocationHandler buildProxyInvocationHandler( 362 ComponentTemplateConfiguration componentTemplateConfiguration) { 363 364 Class componentProxyInvocationHandlerClass = 365 componentTemplateConfiguration 366 .getComponentProxyInvocationHandlerClass(); 367 368 if (log.isTraceEnabled()) { 369 log.trace("Building component proxy: [" 370 + componentProxyInvocationHandlerClass.getName() 371 + "]"); 372 } 373 374 try { 375 return 376 (ComponentProxyInvocationHandler) 377 componentProxyInvocationHandlerClass.newInstance(); 378 379 } catch (ClassCastException cce) { 380 throw new InvalidConfigurationException( 381 this.getClass(), 382 componentTemplateConfiguration.getConfigurationName(), 383 "ComponentProxyInvocationHandlerClass", 384 "ComponentProxyInvocationHandler not an instance of [" 385 + ComponentProxyInvocationHandler.class.getName() 386 + "]", 387 cce); 388 389 } catch (InstantiationException ie) { 390 throw new InvalidConfigurationException( 391 this.getClass(), 392 componentTemplateConfiguration.getConfigurationName(), 393 "ComponentProxyInvocationHandlerClass", 394 "Could not instantiate [" 395 + componentProxyInvocationHandlerClass.getName() 396 + "]", 397 ie); 398 399 } catch (IllegalAccessException iae) { 400 throw new InvalidConfigurationException( 401 this.getClass(), 402 componentTemplateConfiguration.getConfigurationName(), 403 "ComponentProxyInvocationHandlerClass", 404 "Could not instantiate [" 405 + componentProxyInvocationHandlerClass.getName() 406 + "]", 407 iae); 408 } 409 } 410 411 423 private Decorator buildDecorator( 424 DecoratorConfiguration decoratorConfiguration, 425 FunctionalInterface functionalImplementation, 426 ComponentConfiguration componentConfiguration, 427 ComponentProxyInvocationHandler proxyInvocationHandler) { 428 429 430 Class factoryClass = decoratorConfiguration.getFactory(); 431 DecoratorFactory factory; 432 433 try { 434 factory = (DecoratorFactory) factoryClass.newInstance(); 435 436 } catch (ClassCastException cce) { 437 throw new InvalidConfigurationException( 438 this.getClass(), 439 decoratorConfiguration.getConfigurationName(), 440 "DecoratorFactory", 441 "value was not an instance of: [" 442 + DecoratorFactory.class.getName() 443 + "]", 444 cce); 445 446 } catch (InstantiationException ie) { 447 throw new InvalidConfigurationException( 448 this.getClass(), 449 decoratorConfiguration.getConfigurationName(), 450 "DecoratorFactory", 451 "could not instantiate AssistantFactory: [" 452 + factoryClass.getName() 453 + "]", 454 ie); 455 456 } catch (IllegalAccessException iae) { 457 throw new InvalidConfigurationException( 458 this.getClass(), 459 decoratorConfiguration.getConfigurationName(), 460 "DecoratorFactory", 461 "could not instantiate AssistantFactory: [" 462 + factoryClass.getName() 463 + "]", 464 iae); 465 } 466 467 if (log.isTraceEnabled()) { 468 log.trace("Building decorator: [" + 469 factoryClass.getName() + "]"); 470 } 471 472 Configuration configuration = 474 decoratorConfiguration.getCustomConfiguration(); 475 476 return factory.getInstance( 478 functionalImplementation, 479 componentConfiguration, 480 proxyInvocationHandler, 481 configuration); 482 } 483 484 496 private ComponentTemplateConfiguration getComponentTemplateConfiguration( 497 ComponentConfiguration componentConfiguration) { 498 499 try { 500 return (ComponentTemplateConfiguration) Config 501 .getInstance() 502 .fetchConfiguration( 503 componentConfiguration.getComponentTemplateName()); 504 505 } catch (ClassCastException cce) { 506 throw new InvalidConfigurationException( 507 this.getClass(), 508 componentConfiguration.getConfigurationName(), 509 "ComponentTemplateName", 510 "ComponentTemplateName does not refer to a configuration " 511 + "that implements " 512 + ComponentTemplateConfiguration.class.getName(), 513 cce); 514 515 } catch (ConfigurationNotFoundException cnfe) { 516 throw new InvalidConfigurationException( 517 this.getClass(), 518 componentConfiguration.getConfigurationName(), 519 "ComponentTemplateName", 520 "Configurattion [" 521 + componentConfiguration.getComponentTemplateName() 522 + "] was not found", 523 cnfe); 524 } 525 } 526 527 528 536 private void checkAllMethodNames(Set interfaces, String componentName) { 537 538 Set methodSet = new HashSet (); 539 Iterator interfaceIterator = interfaces.iterator(); 540 541 while (interfaceIterator.hasNext()) { 543 Class thisInterface = (Class ) interfaceIterator.next(); 544 Method [] methods = thisInterface.getMethods(); 545 546 for (int i = 0; i < methods.length; i++) { 548 MethodWrapper nextMethod = new MethodWrapper(methods[i]); 549 boolean methodConflict = !methodSet.add(nextMethod); 550 551 if (methodConflict) { 552 if (log.isWarnEnabled()) { 554 log.warn("Component has conflicting methods, method [" 555 + nextMethod.toString() 556 + "] in component [" 557 + componentName 558 + "]"); 559 } 560 } 561 } 562 } 563 } 564 565 575 protected static class MethodWrapper { 576 577 private Method method; 578 579 584 public MethodWrapper(Method method) { 585 this.method = method; 586 } 587 588 593 public Method getMethod() { 594 return this.method; 595 } 596 597 604 public boolean equals(Object obj) { 605 boolean isEquals = false; 606 try { 607 Method otherMethod = ((MethodWrapper) obj).getMethod(); 608 609 if (otherMethod.getName().equals(this.method.getName())) { 610 Class [] thisMethodParams = this.method.getParameterTypes(); 612 Class [] otherMethodParams = otherMethod.getParameterTypes(); 613 614 if (Arrays.equals(thisMethodParams, otherMethodParams)) { 615 isEquals = true; 617 } 618 } 619 } catch (ClassCastException cce) { 620 isEquals = false; 621 } 622 return isEquals; 623 624 } 625 626 629 public int hashCode() { 630 return this.method.getName().hashCode() 631 + this.method.getParameterTypes().length; 632 } 633 634 637 public String toString() { 638 StringBuffer buffer = new StringBuffer (this.method.getName()); 639 buffer.append("("); 640 641 Class [] parameterTypes = this.method.getParameterTypes(); 642 if (parameterTypes.length > 0) { 643 buffer.append(getTypeString(parameterTypes[0])); 644 for (int i = 1; i < parameterTypes.length; i++) { 645 buffer.append(", "); 646 buffer.append(getTypeString(parameterTypes[i])); 647 } 648 } 649 buffer.append(")"); 650 651 return buffer.toString(); 652 } 653 654 662 private String getTypeString(Class type) { 663 if (type.isArray()) { 664 return type.getComponentType().getName() + "[]"; 665 } else { 666 return type.getName(); 667 } 668 } 669 670 } 671 672 673 } 674 | Popular Tags |