001 /* 002 * Copyright 2002-2006 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016 package org.springframework.richclient.application.support; 017 018 import java.io.IOException; 019 import java.util.Collections; 020 import java.util.HashMap; 021 import java.util.Iterator; 022 import java.util.Map; 023 024 import org.apache.commons.logging.Log; 025 import org.apache.commons.logging.LogFactory; 026 import org.springframework.beans.factory.NoSuchBeanDefinitionException; 027 import org.springframework.binding.convert.ConversionService; 028 import org.springframework.binding.form.FieldFaceSource; 029 import org.springframework.binding.form.FormModel; 030 import org.springframework.binding.form.support.MessageSourceFieldFaceSource; 031 import org.springframework.binding.value.ValueChangeDetector; 032 import org.springframework.binding.value.support.DefaultValueChangeDetector; 033 import org.springframework.context.ApplicationContext; 034 import org.springframework.context.ApplicationContextAware; 035 import org.springframework.context.MessageSource; 036 import org.springframework.context.support.GenericApplicationContext; 037 import org.springframework.context.support.MessageSourceAccessor; 038 import org.springframework.context.support.ResourceBundleMessageSource; 039 import org.springframework.context.support.ResourceMapFactoryBean; 040 import org.springframework.core.enums.LabeledEnumResolver; 041 import org.springframework.core.enums.StaticLabeledEnumResolver; 042 import org.springframework.core.io.ClassPathResource; 043 import org.springframework.richclient.application.ApplicationPageFactory; 044 import org.springframework.richclient.application.ApplicationServices; 045 import org.springframework.richclient.application.ApplicationWindowFactory; 046 import org.springframework.richclient.application.DefaultConversionServiceFactoryBean; 047 import org.springframework.richclient.application.PageComponentPaneFactory; 048 import org.springframework.richclient.application.PageDescriptorRegistry; 049 import org.springframework.richclient.application.ServiceNotFoundException; 050 import org.springframework.richclient.application.ViewDescriptorRegistry; 051 import org.springframework.richclient.application.config.ApplicationObjectConfigurer; 052 import org.springframework.richclient.application.config.DefaultApplicationObjectConfigurer; 053 import org.springframework.richclient.command.CommandServices; 054 import org.springframework.richclient.command.config.CommandConfigurer; 055 import org.springframework.richclient.command.config.DefaultCommandConfigurer; 056 import org.springframework.richclient.command.support.DefaultCommandServices; 057 import org.springframework.richclient.factory.ButtonFactory; 058 import org.springframework.richclient.factory.ComponentFactory; 059 import org.springframework.richclient.factory.DefaultButtonFactory; 060 import org.springframework.richclient.factory.DefaultComponentFactory; 061 import org.springframework.richclient.factory.DefaultMenuFactory; 062 import org.springframework.richclient.factory.MenuFactory; 063 import org.springframework.richclient.form.binding.BinderSelectionStrategy; 064 import org.springframework.richclient.form.binding.BindingFactoryProvider; 065 import org.springframework.richclient.form.binding.swing.SwingBinderSelectionStrategy; 066 import org.springframework.richclient.form.binding.swing.SwingBindingFactoryProvider; 067 import org.springframework.richclient.form.builder.FormComponentInterceptor; 068 import org.springframework.richclient.form.builder.FormComponentInterceptorFactory; 069 import org.springframework.richclient.image.DefaultIconSource; 070 import org.springframework.richclient.image.DefaultImageSource; 071 import org.springframework.richclient.image.IconSource; 072 import org.springframework.richclient.image.ImageSource; 073 import org.springframework.richclient.security.ApplicationSecurityManager; 074 import org.springframework.richclient.security.SecurityControllerManager; 075 import org.springframework.richclient.security.support.DefaultApplicationSecurityManager; 076 import org.springframework.richclient.security.support.DefaultSecurityControllerManager; 077 import org.springframework.richclient.util.Assert; 078 import org.springframework.rules.RulesSource; 079 import org.springframework.rules.reporting.DefaultMessageTranslatorFactory; 080 import org.springframework.rules.reporting.MessageTranslatorFactory; 081 import org.springframework.rules.support.DefaultRulesSource; 082 import org.springframework.util.ClassUtils; 083 084 /** 085 * A default implementation of the ApplicationServices (service locator) interface. This implementation allows for the 086 * direct registration of service implementations by using various setter methods (like 087 * {@link #setImageSource(ImageSource)}). Service registry entries can also be added in bulk using the 088 * {@link #setRegistryEntries(Map)} method. 089 * <p> 090 * Except in testing environments, this class will typically be instantiated in the application context and the various 091 * service implementations will be set <b>BY ID</b>. The use of service bean ids instead of direct bean references is 092 * to avoid numerous problems with cyclic dependencies and other order dependent operations. So, a typical incarnation 093 * might look like this: 094 * 095 * <pre> 096 * <bean id="applicationServices" 097 * class="org.springframework.richclient.application.support.DefaultApplicationServices"> 098 * <property name="applicationObjectConfigurerId"><idref bean="applicationObjectConfigurer" /></property> 099 * <property name="imageSourceId"><idref bean="imageSource"/></property> 100 * <property name="rulesSourceId"><idref bean="rulesSource"/></property> 101 * <property name="conversionServiceId"><idref bean="conversionService"/></property> 102 * <property name="formComponentInterceptorFactoryId"><idref bean="formComponentInterceptorFactory"/></property> 103 * </bean> 104 * </pre> 105 * 106 * Note the use of the <code>idref</code> form instead of just using a string value. This is the preferred syntax in 107 * order to avoid having misspelled bean names go unreported. 108 * <p> 109 * Which service implementation is returned by {@link #getService(Class)} will be determined through the following 110 * steps: 111 * <ol> 112 * <li>Consult the current registry of service implementations which have been explicitly defined through bean 113 * definition. If a registry entry was made using a bean id, this is the point at which it will be dereferenced into the 114 * actual bean implementation. So, the bean impementation will not be referenced until it is requested.</li> 115 * <li>If the service impl. is not found yet the short string name of the service' Java class in decapitalized 116 * JavaBeans property format will be used to lookup the service implementation in the current application context.<br/> 117 * If the service class is <code>org.springframework.richclient.factory.MenuFactory</code> the bean name 118 * <code>menuFactory</code> will be used to find the bean</li> 119 * <li>If the service impl. is not found yet and a default implementation can be provided, it will be constructed at 120 * that time. Default implementations are provided for essentially all services referenced by the platform.</li> 121 * </ol> 122 * 123 * @author Larry Streepy 124 */ 125 public class DefaultApplicationServices implements ApplicationServices, ApplicationContextAware { 126 127 private static final Log logger = LogFactory.getLog( DefaultApplicationServices.class ); 128 129 /** Map of services, keyed by service type (class). */ 130 private final Map services = Collections.synchronizedMap( new HashMap() ); 131 132 /** Map of service types to default implementation builders. */ 133 private static final Map serviceImplBuilders = new HashMap(); 134 135 /** Application context with needed bean definitions. */ 136 private ApplicationContext applicationContext; 137 138 /** ID of the ApplicationObjectConfigurer bean. */ 139 private String applicationObjectConfigurerBeanId; 140 141 /** 142 * Default Constructor. 143 */ 144 public DefaultApplicationServices() { 145 } 146 147 /** 148 * Constuct using the given application context. 149 * 150 * @param applicationContext to use for locating named services (beans) 151 */ 152 public DefaultApplicationServices( ApplicationContext applicationContext ) { 153 setApplicationContext( applicationContext ); 154 } 155 156 /** 157 * Set the application context. We are ApplicationContextAware so this will happen 158 * automatically if we are defined in the context. If not, then this method should be 159 * called directly. 160 */ 161 public void setApplicationContext( ApplicationContext applicationContext ) { 162 this.applicationContext = applicationContext; 163 } 164 165 /** 166 * @return application context 167 */ 168 public ApplicationContext getApplicationContext() { 169 if (applicationContext == null) { 170 applicationContext = new GenericApplicationContext(); 171 } 172 return applicationContext; 173 } 174 175 /** 176 * Get a service of the indicated type. If no service definition for the requested 177 * type is found in the application context, then a reasonable default implementation 178 * will be created. 179 * 180 * @param serviceType Type of service being requested 181 * @return Service instance 182 * @throws ServiceNotFoundException if the service is not found and no suitable 183 * default implementation is available. 184 */ 185 public synchronized Object getService( Class serviceType ) { 186 Assert.required( serviceType, "serviceType" ); 187 Object service = services.get( serviceType ); 188 if( service == null ) { 189 service = getServiceForClassType(serviceType); 190 if (service == null) { 191 service = getDefaultImplementation(serviceType); 192 } 193 if (service != null) { 194 services.put(serviceType, service); 195 } 196 } else { 197 // Runtime derefence of refid's 198 if( service instanceof String ) { 199 service = getApplicationContext().getBean( (String) service, serviceType ); 200 services.put( serviceType, service ); 201 } 202 } 203 204 // If we still don't have an implementation, then it's a bust 205 if( service == null ) { 206 throw new ServiceNotFoundException(serviceType); 207 } 208 return service; 209 } 210 211 public boolean containsService( Class serviceType ) { 212 Assert.required( serviceType, "serviceType" ); 213 return services.containsKey( serviceType ) || containsServiceForClassType(serviceType) || containsDefaultImplementation( serviceType ); 214 } 215 216 /** 217 * Add entries to the service registry. This is typically called from a bean 218 * definition in the application context. The entryMap parameter must be a map with 219 * keys that are either class instances (the serviceType) or the String name of the 220 * class and values that are the implementation to use for that service or an idref to 221 * a bean that is the implementation (passed as a String). 222 * 223 * @param entryMap Map of entries 224 */ 225 public void setRegistryEntries( Map entryMap ) { 226 Iterator iter = entryMap.entrySet().iterator(); 227 228 while( iter.hasNext() ) { 229 Map.Entry entry = (Map.Entry) iter.next(); 230 Class serviceType = null; 231 Object key = entry.getKey(); 232 233 // If the key is a String, convert it to a class 234 if( key instanceof String ) { 235 try { 236 serviceType = Class.forName( (String) key ); 237 } catch( ClassNotFoundException e ) { 238 logger.error( "Unable to convert key to Class", e ); 239 } 240 } else if( key instanceof Class ) { 241 serviceType = (Class) key; 242 } else { 243 logger.error( "Invalid service entry key; must be String or Class, got: " + key.getClass() ); 244 } 245 246 // If we got something usable, then add the map entry 247 if( serviceType != null ) { 248 services.put( serviceType, entry.getValue() ); 249 } 250 } 251 } 252 253 /** 254 * Set the application object configurer service implementation. 255 * 256 * @param applicationObjectConfigurer 257 */ 258 public void setApplicationObjectConfigurer( ApplicationObjectConfigurer applicationObjectConfigurer ) { 259 services.put( ApplicationObjectConfigurer.class, applicationObjectConfigurer ); 260 } 261 262 /** 263 * Set the application object configurer service implementation bean id 264 * 265 * @param applicationObjectConfigurerId bean id 266 */ 267 public void setApplicationObjectConfigurerId( String applicationObjectConfigurerId ) { 268 services.put( ApplicationObjectConfigurer.class, applicationObjectConfigurerId ); 269 } 270 271 /** 272 * Set the application security manager service implementation. 273 * 274 * @param applicationSecurityManager instance to use 275 */ 276 public void setApplicationSecurityManager( ApplicationSecurityManager applicationSecurityManager ) { 277 services.put( ApplicationSecurityManager.class, applicationSecurityManager ); 278 } 279 280 /** 281 * Set the application security manager service implementation bean id 282 * 283 * @param applicationSecurityManagerId bean id 284 */ 285 public void setApplicationSecurityManagerId( String applicationSecurityManagerId ) { 286 services.put( ApplicationSecurityManager.class, applicationSecurityManagerId ); 287 } 288 289 /** 290 * Set the <code>ApplicationWindow</code> factory service implementation 291 * 292 * @param factory 293 */ 294 public void setApplicationWindowFactory( ApplicationWindowFactory factory ) { 295 services.put( ApplicationWindowFactory.class, factory ); 296 } 297 298 /** 299 * Set the <code>ApplicationWindow</code> factory service implementation bean id 300 * 301 * @param factoryId bean id 302 */ 303 public void setApplicationWindowFactoryId( String factoryId ) { 304 services.put( ApplicationWindowFactory.class, factoryId ); 305 } 306 307 /** 308 * Set the <code>ApplicationPage</code> factory service implementation 309 * 310 * @param factory 311 */ 312 public void setApplicationPageFactory( ApplicationPageFactory factory ) { 313 services.put( ApplicationPageFactory.class, factory ); 314 } 315 316 /** 317 * Set the <code>ApplicationPage</code> factory service implementation bean id 318 * 319 * @param factoryId bean id 320 */ 321 public void setApplicationPageFactoryId( String factoryId ) { 322 services.put( ApplicationPageFactory.class, factoryId ); 323 } 324 325 /** 326 * Set the <code>PageComponentPane</code> factory service implementation bean 327 * 328 * @param factory bean id 329 */ 330 public void setPageComponentPaneFactory( PageComponentPaneFactory factory ) { 331 services.put( PageComponentPaneFactory.class, factory ); 332 } 333 334 /** 335 * Set the <code>PageComponentPane</code> factory service implementation bean id 336 * 337 * @param factoryId bean id 338 */ 339 public void setPageComponentPaneFactoryId( String factoryId ) { 340 services.put( PageComponentPaneFactory.class, factoryId ); 341 } 342 343 /** 344 * Set the binder selection strategy service implementation 345 * 346 * @param binderSelectionStrategy 347 */ 348 public void setBinderSelectionStrategy( BinderSelectionStrategy binderSelectionStrategy ) { 349 services.put( BinderSelectionStrategy.class, binderSelectionStrategy ); 350 } 351 352 /** 353 * Set the binder selection strategy service implementation bean id 354 * 355 * @param binderSelectionStrategyId bean id 356 */ 357 public void setBinderSelectionStrategyId( String binderSelectionStrategyId ) { 358 services.put( BinderSelectionStrategy.class, binderSelectionStrategyId ); 359 } 360 361 /** 362 * Set the binding factory provider service implementation 363 * 364 * @param bindingFactoryProvider 365 */ 366 public void setBindingFactoryProvider( BindingFactoryProvider bindingFactoryProvider ) { 367 services.put( BindingFactoryProvider.class, bindingFactoryProvider ); 368 } 369 370 /** 371 * Set the binding factory provider service implementation bean id 372 * 373 * @param bindingFactoryProviderId bean id 374 */ 375 public void setBindingFactoryProviderId( String bindingFactoryProviderId ) { 376 services.put( BindingFactoryProvider.class, bindingFactoryProviderId ); 377 } 378 379 /** 380 * Set the command services service implementation 381 * 382 * @param commandServices 383 */ 384 public void setCommandServices( CommandServices commandServices ) { 385 services.put( CommandServices.class, commandServices ); 386 } 387 388 /** 389 * Set the command services service implementation bean id 390 * 391 * @param commandServicesId bean id 392 */ 393 public void setCommandServicesId( String commandServicesId ) { 394 services.put( CommandServices.class, commandServicesId ); 395 } 396 397 /** 398 * Set the command configurer service implementation 399 * 400 * @param commandConfigurer 401 */ 402 public void setCommandConfigurer( CommandConfigurer commandConfigurer ) { 403 services.put( CommandConfigurer.class, commandConfigurer ); 404 } 405 406 /** 407 * Set the command configurer service implementation bean id 408 * 409 * @param commandConfigurerId bean id 410 */ 411 public void setCommandConfigurerId( String commandConfigurerId ) { 412 services.put( CommandConfigurer.class, commandConfigurerId ); 413 } 414 415 /** 416 * Set the button factory service implementation 417 * 418 * @param buttonFactory 419 */ 420 public void setButtonFactory( ButtonFactory buttonFactory ) { 421 services.put( ButtonFactory.class, buttonFactory ); 422 } 423 424 /** 425 * Set the button factory service implementation bean id 426 * 427 * @param buttonFactoryId bean id 428 */ 429 public void setButtonFactoryId( String buttonFactoryId ) { 430 services.put( ButtonFactory.class, buttonFactoryId ); 431 } 432 433 /** 434 * Set the menu factory service implementation 435 * 436 * @param menuFactory 437 */ 438 public void setMenuFactory( MenuFactory menuFactory ) { 439 services.put( MenuFactory.class, menuFactory ); 440 } 441 442 /** 443 * Set the menu factory service implementation bean id 444 * 445 * @param menuFactoryId bean id 446 */ 447 public void setMenuFactoryId( String menuFactoryId ) { 448 services.put( MenuFactory.class, menuFactoryId ); 449 } 450 451 /** 452 * Set the component factory service implementation 453 * 454 * @param componentFactory 455 */ 456 public void setComponentFactory( ComponentFactory componentFactory ) { 457 services.put( ComponentFactory.class, componentFactory ); 458 } 459 460 /** 461 * Set the component factory service implementation bean id 462 * 463 * @param componentFactoryId bean id 464 */ 465 public void setComponentFactoryId( String componentFactoryId ) { 466 services.put( ComponentFactory.class, componentFactoryId ); 467 } 468 469 /** 470 * Set the conversion service service implementation 471 * 472 * @param conversionService 473 */ 474 public void setConversionService( ConversionService conversionService ) { 475 services.put( ConversionService.class, conversionService ); 476 } 477 478 /** 479 * Set the conversion service service implementation bean id 480 * 481 * @param conversionServiceId bean id 482 */ 483 public void setConversionServiceId( String conversionServiceId ) { 484 services.put( ConversionService.class, conversionServiceId ); 485 } 486 487 /** 488 * Set the form component interceptor factory service implementation 489 * 490 * @param formComponentInterceptorFactory 491 */ 492 public void setFormComponentInterceptorFactory( FormComponentInterceptorFactory formComponentInterceptorFactory ) { 493 services.put( FormComponentInterceptorFactory.class, formComponentInterceptorFactory ); 494 } 495 496 /** 497 * Set the form component interceptor factory service implementation bean id 498 * 499 * @param formComponentInterceptorFactoryId bean id 500 */ 501 public void setFormComponentInterceptorFactoryId( String formComponentInterceptorFactoryId ) { 502 services.put( FormComponentInterceptorFactory.class, formComponentInterceptorFactoryId ); 503 } 504 505 /** 506 * Set the field face descriptor source service implementation 507 * 508 * @param fieldFaceSource 509 */ 510 public void setFieldFaceSource( FieldFaceSource fieldFaceSource ) { 511 services.put( FieldFaceSource.class, fieldFaceSource ); 512 } 513 514 /** 515 * Set the field face descriptor source service implementation bean id 516 * 517 * @param fieldFaceSourceId bean id 518 */ 519 public void setFieldFaceSourceId( String fieldFaceSourceId ) { 520 services.put( FieldFaceSource.class, fieldFaceSourceId ); 521 } 522 523 /** 524 * Set the icon source service implementation 525 * 526 * @param iconSource 527 */ 528 public void setIconSource( IconSource iconSource ) { 529 services.put( IconSource.class, iconSource ); 530 } 531 532 /** 533 * Set the icon source service implementation bean id 534 * 535 * @param iconSourceId bean id 536 */ 537 public void setIconSourceId( String iconSourceId ) { 538 services.put( IconSource.class, iconSourceId ); 539 } 540 541 /** 542 * Set the image source service implementation 543 * 544 * @param imageSource 545 */ 546 public void setImageSource( ImageSource imageSource ) { 547 services.put( ImageSource.class, imageSource ); 548 } 549 550 /** 551 * Set the image source service implementation bean id 552 * 553 * @param imageSourceId bean id 554 */ 555 public void setImageSourceId( String imageSourceId ) { 556 services.put( ImageSource.class, imageSourceId ); 557 } 558 559 /** 560 * Set the labeled enum resolver service implementation 561 * 562 * @param labeledEnumResolver 563 */ 564 public void setLabeledEnumResolver( LabeledEnumResolver labeledEnumResolver ) { 565 services.put( LabeledEnumResolver.class, labeledEnumResolver ); 566 } 567 568 /** 569 * Set the labeled enum resolver service implementation bean id 570 * 571 * @param labeledEnumResolverId bean id 572 */ 573 public void setLabeledEnumResolverId( String labeledEnumResolverId ) { 574 services.put( LabeledEnumResolver.class, labeledEnumResolverId ); 575 } 576 577 /** 578 * Set the message source service implementation 579 * 580 * @param messageSource 581 */ 582 public void setMessageSource( MessageSource messageSource ) { 583 services.put( MessageSource.class, messageSource ); 584 } 585 586 /** 587 * Set the message source service implementation bean id 588 * 589 * @param messageSourceId bean id 590 */ 591 public void setMessageSourceId( String messageSourceId ) { 592 services.put( MessageSource.class, messageSourceId ); 593 } 594 595 /** 596 * Set the message source accessor service implementation 597 * 598 * @param messageSourceAccessor 599 */ 600 public void setMessageSourceAccesor( MessageSourceAccessor messageSourceAccessor ) { 601 services.put( MessageSourceAccessor.class, messageSourceAccessor ); 602 } 603 604 /** 605 * Set the message source accessor service implementation bean id 606 * 607 * @param messageSourceAccessorId bean id 608 */ 609 public void setMessageSourceAccesorId( String messageSourceAccessorId ) { 610 services.put( MessageSourceAccessor.class, messageSourceAccessorId ); 611 } 612 613 /** 614 * Set the rules source service implementation 615 * 616 * @param rulesSource 617 */ 618 public void setRulesSource( RulesSource rulesSource ) { 619 services.put( RulesSource.class, rulesSource ); 620 } 621 622 /** 623 * Set the rules source service implementation bean id 624 * 625 * @param rulesSourceId bean id 626 */ 627 public void setRulesSourceId( String rulesSourceId ) { 628 services.put( RulesSource.class, rulesSourceId ); 629 } 630 631 /** 632 * Set the security controller manager service implementation 633 * 634 * @param securityControllerManager instance to use 635 */ 636 public void setSecurityControllerManager( SecurityControllerManager securityControllerManager ) { 637 services.put( SecurityControllerManager.class, securityControllerManager ); 638 } 639 640 /** 641 * Set the security controller manager service implementation bean id 642 * 643 * @param securityControllerManagerId bean id 644 */ 645 public void setSecurityControllerManagerId( String securityControllerManagerId ) { 646 services.put( SecurityControllerManager.class, securityControllerManagerId ); 647 } 648 649 /** 650 * Set the value change detector service imlpementation. 651 * 652 * @param valueChangeDetector instance to use 653 */ 654 public void setValueChangeDetector( ValueChangeDetector valueChangeDetector ) { 655 services.put( ValueChangeDetector.class, valueChangeDetector ); 656 } 657 658 /** 659 * Set the value change detector service imlpementation bean id 660 * 661 * @param valueChangeDetectorId bean id 662 */ 663 public void setValueChangeDetectorId( String valueChangeDetectorId ) { 664 services.put( ValueChangeDetector.class, valueChangeDetectorId ); 665 } 666 667 /** 668 * Set the view descriptor registry service implementation 669 * 670 * @param viewDescriptorRegistry 671 */ 672 public void setViewDescriptorRegistry( ViewDescriptorRegistry viewDescriptorRegistry ) { 673 services.put( ViewDescriptorRegistry.class, viewDescriptorRegistry ); 674 } 675 676 /** 677 * Set the page descriptor registry service implementation 678 * 679 * @param pageDescriptorRegistry 680 */ 681 public void setPageDescriptorRegistry( PageDescriptorRegistry pageDescriptorRegistry ) { 682 services.put( PageDescriptorRegistry.class, pageDescriptorRegistry ); 683 } 684 685 /** 686 * Set the message translator registry service implementation 687 * 688 * @param messageTranslatorFactory 689 */ 690 public void setMessageTranslatorFactory( MessageTranslatorFactory messageTranslatorFactory ) { 691 services.put( MessageTranslatorFactory.class, messageTranslatorFactory ); 692 } 693 694 /** 695 * Set the message translator registry service implementation bean id 696 * 697 * @param messageTranslatorFactory 698 */ 699 public void setMessageTranslatorFactoryId( String messageTranslatorFactoryId ) { 700 services.put( MessageTranslatorFactory.class, messageTranslatorFactoryId ); 701 } 702 703 /** 704 * Set the view descriptor registry service implementation bean id 705 * 706 * @param viewDescriptorRegistryId bean id 707 */ 708 public void setViewDescriptorRegistryId( String viewDescriptorRegistryId ) { 709 services.put( ViewDescriptorRegistry.class, viewDescriptorRegistryId ); 710 } 711 712 /** 713 * Set the page descriptor registry service implementation bean id 714 * 715 * @param pageDescriptorRegistryId bean id 716 */ 717 public void setPageDescriptorRegistryId( String pageDescriptorRegistryId ) { 718 services.put( PageDescriptorRegistry.class, pageDescriptorRegistryId ); 719 } 720 721 /** 722 * Get the implementation of a service by using the decapitalized shortname of the serviceType class name. 723 * 724 * @param serviceType 725 * the service class to lookup the bean definition 726 * @return the found service implementation if a bean definition can be found and it implements the required service 727 * type, otherwise null 728 * @see ClassUtils#getShortNameAsProperty(Class) 729 */ 730 protected Object getServiceForClassType(Class serviceType) { 731 String lookupName = ClassUtils.getShortNameAsProperty(serviceType); 732 ApplicationContext ctx = getApplicationContext(); 733 if (ctx.containsBean(lookupName)) { 734 Object bean = ctx.getBean(lookupName); 735 if (serviceType.isAssignableFrom(bean.getClass())) { 736 if(logger.isDebugEnabled()) { 737 logger.debug("Using bean '" + lookupName + "' (" + bean.getClass().getName() + ") for service " + serviceType.getName()); 738 } 739 return bean; 740 } 741 else if(logger.isDebugEnabled()){ 742 logger.debug("Bean with id '" + lookupName + "' (" + bean.getClass().getName() + ") does not implement " + serviceType.getName()); 743 } 744 } else if(logger.isDebugEnabled()){ 745 logger.debug("No Bean with id '" + lookupName + "' found for service " + serviceType.getName()); 746 } 747 return null; 748 } 749 750 751 /** 752 * Get the default implementation of a service according to the service type. If no 753 * default implementation is available, then a null is returned. 754 * 755 * @param serviceType Type of service requested 756 * @return Default service implementation, or null if none defined 757 */ 758 protected Object getDefaultImplementation( Class serviceType ) { 759 Object impl = null; 760 ImplBuilder builder = (ImplBuilder) serviceImplBuilders.get( serviceType ); 761 if( builder != null ) { 762 impl = builder.build( this ); 763 } 764 return impl; 765 } 766 767 /** 768 * Tests if the application context contains a bean definition by using the decapitalized shortname of the serviceType class name 769 * @param serviceType the service class to lookup the bean definition 770 * @return true if a bean definition is found in the current application context, otherwise false 771 * 772 * @see ClassUtils#getShortNameAsProperty(Class) 773 */ 774 protected boolean containsServiceForClassType(Class serviceType) { 775 return getApplicationContext().containsBean(ClassUtils.getShortNameAsProperty(serviceType)); 776 } 777 778 /** 779 * Tests if a default implementation for the requested service type is available 780 * 781 * @param serviceType the requested service type 782 * @return true if a default implementation is available otherwise false. 783 */ 784 protected boolean containsDefaultImplementation( Class serviceType ) { 785 return serviceImplBuilders.containsKey( serviceType ); 786 } 787 788 /** 789 * Internal interface used to provide default implementation builders. 790 */ 791 protected interface ImplBuilder { 792 /** 793 * Build the service implementation. 794 * 795 * @param applicationServices reference to service locator 796 * @return service implementation 797 */ 798 Object build( DefaultApplicationServices applicationServices ); 799 } 800 801 protected static final ImplBuilder applicationContextImplBuilder = new ImplBuilder() { 802 public Object build( DefaultApplicationServices applicationServices ) { 803 return applicationServices.getApplicationContext(); 804 } 805 }; 806 807 protected static final ImplBuilder menuFactoryImplBuilder = new ImplBuilder() { 808 public Object build( DefaultApplicationServices applicationServices ) { 809 logger.info( "Creating default service impl: MenuFactory" ); 810 return new DefaultMenuFactory(); 811 } 812 }; 813 814 protected static final ImplBuilder buttonFactoryImplBuilder = new ImplBuilder() { 815 public Object build( DefaultApplicationServices applicationServices ) { 816 logger.info( "Creating default service impl: ButtonFactory" ); 817 return new DefaultButtonFactory(); 818 } 819 }; 820 821 protected static final ImplBuilder commandServicesImplBuilder = new ImplBuilder() { 822 public Object build( DefaultApplicationServices applicationServices ) { 823 logger.info( "Creating default service impl: CommandServices" ); 824 return new DefaultCommandServices(); 825 } 826 }; 827 828 protected static final ImplBuilder componentFactoryImplBuilder = new ImplBuilder() { 829 public Object build( DefaultApplicationServices applicationServices ) { 830 logger.info( "Creating default service impl: ComponentFactory" ); 831 return new DefaultComponentFactory(); 832 } 833 }; 834 835 protected static final ImplBuilder formComponentInterceptorFactoryImplBuilder = new ImplBuilder() { 836 public Object build( DefaultApplicationServices applicationServices ) { 837 logger.info( "Creating default service impl: FormComponentInterceptorFactory" ); 838 return new FormComponentInterceptorFactory() { 839 public FormComponentInterceptor getInterceptor( FormModel formModel ) { 840 return null; 841 } 842 }; 843 } 844 }; 845 846 protected static final ImplBuilder applicationObjectConfigurerImplBuilder = new ImplBuilder() { 847 public Object build( DefaultApplicationServices applicationServices ) { 848 // First see if there is an AOC in the context, if not construct a default 849 Object impl = null; 850 String aocBeanId = applicationServices.applicationObjectConfigurerBeanId; 851 if( aocBeanId != null ) { 852 try { 853 impl = applicationServices.getApplicationContext().getBean( aocBeanId, 854 ApplicationObjectConfigurer.class ); 855 } catch( NoSuchBeanDefinitionException e ) { 856 logger.info( "No object configurer found in context under name '" + aocBeanId 857 + "'; configuring defaults." ); 858 impl = new DefaultApplicationObjectConfigurer((MessageSource)applicationServices.getService(MessageSource.class)); 859 } 860 } else { 861 logger.info( "No object configurer bean Id has been set; configuring defaults." ); 862 impl = new DefaultApplicationObjectConfigurer((MessageSource)applicationServices.getService(MessageSource.class)); 863 } 864 return impl; 865 } 866 }; 867 868 protected static final ImplBuilder commandConfigurerImplBuilder = new ImplBuilder() { 869 public Object build( DefaultApplicationServices applicationServices ) { 870 logger.info( "Creating default service impl: CommandConfigurer" ); 871 return new DefaultCommandConfigurer(); 872 } 873 }; 874 875 protected static final ImplBuilder imageSourceImplBuilder = new ImplBuilder() { 876 public Object build( DefaultApplicationServices applicationServices ) { 877 logger.info( "Creating default service impl: ImageSource" ); 878 try { 879 ResourceMapFactoryBean imageResourcesFactory = new ResourceMapFactoryBean(); 880 imageResourcesFactory.setLocation(new ClassPathResource("org/springframework/richclient/image/images.properties")); 881 imageResourcesFactory.afterPropertiesSet(); 882 return new DefaultImageSource((Map)imageResourcesFactory.getObject()); 883 } 884 catch (IOException e) { 885 return new DefaultImageSource(new HashMap()); 886 } 887 } 888 }; 889 890 protected static final ImplBuilder iconSourceImplBuilder = new ImplBuilder() { 891 public Object build( DefaultApplicationServices applicationServices ) { 892 logger.info( "Creating default service impl: IconSource" ); 893 return new DefaultIconSource(); 894 } 895 }; 896 897 protected static final ImplBuilder rulesSourceImplBuilder = new ImplBuilder() { 898 public Object build( DefaultApplicationServices applicationServices ) { 899 logger.info( "Creating default service impl: RulesSource" ); 900 return new DefaultRulesSource(); 901 } 902 }; 903 904 protected static final ImplBuilder conversionServiceImplBuilder = new ImplBuilder() { 905 public Object build( DefaultApplicationServices applicationServices ) { 906 logger.info( "Creating default service impl: ConversionService" ); 907 return new DefaultConversionServiceFactoryBean().getConversionService(); 908 } 909 }; 910 911 protected static final ImplBuilder binderSelectionStrategyImplBuilder = new ImplBuilder() { 912 public Object build( DefaultApplicationServices applicationServices ) { 913 logger.info( "Creating default service impl: BinderSelectionStrategy" ); 914 return new SwingBinderSelectionStrategy(); 915 } 916 }; 917 918 protected static final ImplBuilder FieldFaceSourceImplBuilder = new ImplBuilder() { 919 public Object build( DefaultApplicationServices applicationServices ) { 920 logger.info( "Creating default service impl: FieldFaceSource" ); 921 return new MessageSourceFieldFaceSource(); 922 } 923 }; 924 925 protected static final ImplBuilder bindingFactoryProviderImplBuilder = new ImplBuilder() { 926 public Object build( DefaultApplicationServices applicationServices ) { 927 logger.info( "Creating default service impl: BindingFactoryProvider" ); 928 return new SwingBindingFactoryProvider(); 929 } 930 }; 931 932 protected static final ImplBuilder valueChangeDetectorImplBuilder = new ImplBuilder() { 933 public Object build( DefaultApplicationServices applicationServices ) { 934 logger.info( "Creating default service impl: ValueChangeDetector" ); 935 return new DefaultValueChangeDetector(); 936 } 937 }; 938 939 protected static final ImplBuilder applicationSecurityManagerImplBuilder = new ImplBuilder() { 940 public Object build( DefaultApplicationServices applicationServices ) { 941 logger.info( "Creating default service impl: ApplicationSecurityManager" ); 942 return new DefaultApplicationSecurityManager( true ); 943 } 944 }; 945 946 protected static final ImplBuilder SecurityControllerManagerImplBuilder = new ImplBuilder() { 947 public Object build( DefaultApplicationServices applicationServices ) { 948 logger.info( "Creating default service impl: SecurityControllerManager" ); 949 return new DefaultSecurityControllerManager(); 950 } 951 }; 952 953 protected static final ImplBuilder viewDescriptorRegistryImplBuilder = new ImplBuilder() { 954 public Object build( DefaultApplicationServices applicationServices ) { 955 logger.info( "Creating default service impl: ViewDescriptorRegistry" ); 956 BeanFactoryViewDescriptorRegistry impl = new BeanFactoryViewDescriptorRegistry(); 957 impl.setApplicationContext( applicationServices.getApplicationContext() ); 958 return impl; 959 } 960 }; 961 962 protected static final ImplBuilder pageDescriptorRegistryImplBuilder = new ImplBuilder() { 963 public Object build( DefaultApplicationServices applicationServices ) { 964 logger.info( "Creating default service impl: PageDescriptorRegistry" ); 965 BeanFactoryPageDescriptorRegistry impl = new BeanFactoryPageDescriptorRegistry(); 966 impl.setApplicationContext( applicationServices.getApplicationContext() ); 967 return impl; 968 } 969 }; 970 971 protected static final ImplBuilder messageTranslatorFactoryImplBuilder = new ImplBuilder() { 972 public Object build( DefaultApplicationServices applicationServices ) { 973 logger.info( "Creating default service impl: MessageTranslatorFactory" ); 974 DefaultMessageTranslatorFactory impl = new DefaultMessageTranslatorFactory(); 975 impl.setMessageSource( applicationServices.getApplicationContext() ); 976 return impl; 977 } 978 }; 979 980 protected static final ImplBuilder labeledEnumResolverImplBuilder = new ImplBuilder() { 981 public Object build( DefaultApplicationServices applicationServices ) { 982 logger.info( "Creating default service impl: LabeledEnumResolver" ); 983 return new StaticLabeledEnumResolver(); 984 } 985 }; 986 987 protected static final ImplBuilder messageSourceImplBuilder = new ImplBuilder() { 988 public Object build( DefaultApplicationServices applicationServices ) { 989 // The application context is our properly configured message source 990 logger.info( "Using MessageSource from application context" ); 991 ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); 992 messageSource.setBasename("org.springframework.richclient.application.messages"); 993 return messageSource; 994 } 995 }; 996 997 protected static final ImplBuilder messageSourceAccessorImplBuilder = new ImplBuilder() { 998 public Object build( DefaultApplicationServices applicationServices ) { 999 // Just construct one on top of the current message source 1000 return new MessageSourceAccessor( (MessageSource) applicationServices.getService( MessageSource.class ) ); 1001 } 1002 }; 1003 1004 protected static final ImplBuilder applicationWindowFactoryImplBuilder = new ImplBuilder() { 1005 public Object build( DefaultApplicationServices applicationServices ) { 1006 logger.info( "Creating default service impl: ApplicationWindowFactory" ); 1007 return new DefaultApplicationWindowFactory(); 1008 } 1009 }; 1010 1011 protected static final ImplBuilder applicationPageFactoryImplBuilder = new ImplBuilder() { 1012 public Object build( DefaultApplicationServices applicationServices ) { 1013 logger.info( "Creating default service impl: ApplicationPageFactory" ); 1014 return new DefaultApplicationPageFactory(); 1015 } 1016 }; 1017 1018 protected static final ImplBuilder pageComponentPaneFactoryImplBuilder = new ImplBuilder() { 1019 public Object build( DefaultApplicationServices applicationServices ) { 1020 logger.info( "Creating default service impl: PageComponentPaneFactory" ); 1021 return new DefaultPageComponentPaneFactory(); 1022 } 1023 }; 1024 1025 /** 1026 * Static initializer to construct the implementation builder map. 1027 */ 1028 static { 1029 // Default service implementation builders 1030 serviceImplBuilders.put( ApplicationContext.class, applicationContextImplBuilder ); 1031 serviceImplBuilders.put( ApplicationObjectConfigurer.class, applicationObjectConfigurerImplBuilder ); 1032 serviceImplBuilders.put( ApplicationSecurityManager.class, applicationSecurityManagerImplBuilder ); 1033 serviceImplBuilders.put( ApplicationPageFactory.class, applicationPageFactoryImplBuilder ); 1034 serviceImplBuilders.put( ApplicationWindowFactory.class, applicationWindowFactoryImplBuilder ); 1035 serviceImplBuilders.put( PageComponentPaneFactory.class, pageComponentPaneFactoryImplBuilder ); 1036 serviceImplBuilders.put( BinderSelectionStrategy.class, binderSelectionStrategyImplBuilder ); 1037 serviceImplBuilders.put( BindingFactoryProvider.class, bindingFactoryProviderImplBuilder ); 1038 serviceImplBuilders.put( ButtonFactory.class, buttonFactoryImplBuilder ); 1039 serviceImplBuilders.put( MenuFactory.class, menuFactoryImplBuilder ); 1040 serviceImplBuilders.put( CommandServices.class, commandServicesImplBuilder ); 1041 serviceImplBuilders.put( CommandConfigurer.class, commandConfigurerImplBuilder ); 1042 serviceImplBuilders.put( ComponentFactory.class, componentFactoryImplBuilder ); 1043 serviceImplBuilders.put( ConversionService.class, conversionServiceImplBuilder ); 1044 serviceImplBuilders.put( FormComponentInterceptorFactory.class, formComponentInterceptorFactoryImplBuilder ); 1045 serviceImplBuilders.put( FieldFaceSource.class, FieldFaceSourceImplBuilder ); 1046 serviceImplBuilders.put( IconSource.class, iconSourceImplBuilder ); 1047 serviceImplBuilders.put( ImageSource.class, imageSourceImplBuilder ); 1048 serviceImplBuilders.put( LabeledEnumResolver.class, labeledEnumResolverImplBuilder ); 1049 serviceImplBuilders.put( MessageSource.class, messageSourceImplBuilder ); 1050 serviceImplBuilders.put( MessageSourceAccessor.class, messageSourceAccessorImplBuilder ); 1051 serviceImplBuilders.put( RulesSource.class, rulesSourceImplBuilder ); 1052 serviceImplBuilders.put( SecurityControllerManager.class, SecurityControllerManagerImplBuilder ); 1053 serviceImplBuilders.put( ValueChangeDetector.class, valueChangeDetectorImplBuilder ); 1054 serviceImplBuilders.put( ViewDescriptorRegistry.class, viewDescriptorRegistryImplBuilder ); 1055 serviceImplBuilders.put( PageDescriptorRegistry.class, pageDescriptorRegistryImplBuilder ); 1056 serviceImplBuilders.put( MessageTranslatorFactory.class, messageTranslatorFactoryImplBuilder ); 1057 } 1058 }