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 }