001    // Copyright 2007 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.hivemind.annotations.internal;
016    
017    import org.apache.hivemind.ApplicationRuntimeException;
018    import org.apache.hivemind.annotations.TypedRegistry;
019    import org.apache.hivemind.internal.Module;
020    import org.apache.hivemind.internal.RegistryInfrastructure;
021    import org.apache.hivemind.util.Defense;
022    import org.apache.hivemind.util.PropertyUtils;
023    
024    /**
025     * Implementation of {@link ModuleInstanceProvider}.
026     * 
027     * @author Achim Huegen
028     */
029    public class ModuleInstanceProviderImpl implements ModuleInstanceProvider
030    {
031        private static final String REGISTRY_PROPERTY_NAME = "registry";
032    
033        private Class _moduleClass;
034    
035        private Object _instance;
036    
037        private String _moduleId;
038        
039        public ModuleInstanceProviderImpl(Class moduleClass, String moduleId)
040        {
041            _moduleClass = moduleClass;
042            _moduleId = moduleId;
043        }
044    
045        public Object getModuleInstance()
046        {
047            Defense.fieldNotNull(_instance, "instance");
048            return _instance;
049        }
050        
051        private void createModuleInstance(RegistryInfrastructure _registry)
052        {
053            try
054            {
055                _instance = _moduleClass.newInstance();
056                injectRegistry(_instance, _registry);
057            }
058            catch (Exception ex)
059            {
060                // TODO: more expressive error message
061                throw new ApplicationRuntimeException(ex.getMessage(), ex);
062            }
063        }
064    
065        /**
066         * Checks if the module contains a property REGISTRY_PROPERTY_NAME and injects
067         * the registry interface provided to this class during construction.
068         * 
069         * @param moduleInstance
070         */
071        private void injectRegistry(Object moduleInstance, RegistryInfrastructure _registry)
072        {
073            if (PropertyUtils.isWritable(moduleInstance, REGISTRY_PROPERTY_NAME) 
074                    && PropertyUtils.getPropertyType(moduleInstance, REGISTRY_PROPERTY_NAME).equals(TypedRegistry.class)) {
075                
076                Module callingModule = _registry.getModule(_moduleId);
077                TypedRegistry annotatedRegistry = new TypedRegistryImpl(callingModule, _registry);
078                PropertyUtils.write(moduleInstance, REGISTRY_PROPERTY_NAME, annotatedRegistry);
079            }
080        }
081    
082        /**
083         * Called after initialization of the registry infrastructure. 
084         * This is a good moment to create the module instance. If any service defined in the module
085         * is initialized during startup (by the EagerLoad service) it will find the registry
086         * reference in place.
087         * 
088         * @see org.apache.hivemind.events.RegistryInitializationListener#registryInitialized(org.apache.hivemind.internal.RegistryInfrastructure)
089         */
090        public void registryInitialized(RegistryInfrastructure registry)
091        {
092            createModuleInstance(registry);
093        }
094    
095    }