/** * Copyright 2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 the "License"; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ package io.neba.core.resourcemodels.registration; import io.neba.api.annotations.ResourceModel; import io.neba.core.resourcemodels.adaptation.ResourceToModelAdapterUpdater; import io.neba.core.resourcemodels.metadata.ResourceModelMetaDataRegistrar; import io.neba.core.util.OsgiBeanSource; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.stereotype.Service; import static io.neba.core.util.BundleUtil.displayNameOf; import static org.apache.commons.lang.StringUtils.join; import static org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors; /** * Whenever a {@link org.springframework.beans.factory.BeanFactory} is initialized, this registrar * {@link #registerModels(BundleContext, ConfigurableListableBeanFactory) * searches} the factory's bean definitions for beans annotated with * {@link ResourceModel}. The corresponding mappings {type -> model} are then * added to the {@link ModelRegistry}, providing models for resources. This * registrar also signals changes of the {@link ModelRegistry} to the * {@link io.neba.core.resourcemodels.adaptation.ResourceToModelAdapter}. * * @author Olaf Otto * @see io.neba.core.resourcemodels.adaptation.ResourceToModelAdapterUpdater * @see io.neba.core.blueprint.SlingBeanFactoryPostProcessor */ @Service public class ModelRegistrar { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private ModelRegistry registry; @Autowired private ResourceToModelAdapterUpdater resourceToModelAdapterUpdater; @Autowired private ResourceModelMetaDataRegistrar resourceModelMetaDataRegistrar; private void discoverResourceModels(ConfigurableListableBeanFactory factory, Bundle bundle) { logger.info("Discovering resource models in bundle: " + displayNameOf(bundle) + " ..."); String[] beanNames = beanNamesForTypeIncludingAncestors(factory, Object.class); int numberOfDiscoveredModels = 0; for (String beanName : beanNames) { ResourceModel resourceModel = factory.findAnnotationOnBean(beanName, ResourceModel.class); if (resourceModel != null) { ++numberOfDiscoveredModels; OsgiBeanSource<Object> source = new OsgiBeanSource<>(beanName, factory, bundle); this.resourceModelMetaDataRegistrar.register(source); this.registry.add(resourceModel.types(), source); logger.debug("Registered bean " + beanName + " as a model for the resource types " + join(resourceModel.types(), ", ") + "."); } } logger.info("Discovered " + numberOfDiscoveredModels + " resource model(s) in bundle: " + displayNameOf(bundle) + "."); } public void registerModels(BundleContext bundleContext, ConfigurableListableBeanFactory beanFactory) { discoverResourceModels(beanFactory, bundleContext.getBundle()); this.resourceToModelAdapterUpdater.refresh(); } public void unregister(Bundle bundle) { this.registry.removeResourceModels(bundle); this.resourceModelMetaDataRegistrar.remove(bundle); this.resourceToModelAdapterUpdater.refresh(); } }