/refapp-core/src/main/java/com/atlassian/plugin/refimpl/plugins/RefappHostComponentProvider.java
Java | 148 lines | 116 code | 14 blank | 18 comment | 2 complexity | 4b332d4eb0e1037cb44c95525786838c MD5 | raw file
- package com.atlassian.plugin.refimpl.plugins;
- import com.atlassian.annotations.VisibleForTesting;
- import com.atlassian.beehive.ClusterLockService;
- import com.atlassian.event.api.EventPublisher;
- import com.atlassian.healthcheck.spi.HealthCheckWhitelist;
- import com.atlassian.plugin.ModuleDescriptorFactory;
- import com.atlassian.plugin.PluginController;
- import com.atlassian.plugin.SplitStartupPluginSystemLifecycle;
- import com.atlassian.plugin.metadata.PluginMetadataManager;
- import com.atlassian.plugin.module.ModuleFactory;
- import com.atlassian.plugin.osgi.external.ListableModuleDescriptorFactory;
- import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
- import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
- import com.atlassian.plugin.schema.descriptor.DescribedModuleDescriptorFactory;
- import com.atlassian.plugin.servlet.ServletContextFactory;
- import com.atlassian.plugin.servlet.ServletModuleManager;
- import com.atlassian.plugin.webresource.PluginResourceLocator;
- import com.atlassian.plugin.webresource.ResourceBatchingConfiguration;
- import com.atlassian.plugin.webresource.WebResourceIntegration;
- import com.atlassian.plugin.webresource.WebResourceManager;
- import com.atlassian.plugin.webresource.WebResourceUrlProvider;
- import com.atlassian.plugin.webresource.prebake.PrebakeWebResourceAssemblerFactory;
- import com.atlassian.plugins.landlord.spi.LandlordRequests;
- import com.atlassian.refapp.api.ConnectionProvider;
- import com.atlassian.scheduler.SchedulerHistoryService;
- import com.atlassian.scheduler.SchedulerService;
- import com.atlassian.tenancy.api.TenantAccessor;
- import com.atlassian.tenancy.api.TenantContext;
- import com.atlassian.vcache.VCacheFactory;
- import com.atlassian.webresource.api.assembler.PageBuilderService;
- import com.atlassian.webresource.api.assembler.WebResourceAssemblerFactory;
- import org.springframework.beans.BeansException;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationContextAware;
- import javax.annotation.Nonnull;
- import javax.annotation.ParametersAreNonnullByDefault;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Map;
- import static java.util.Arrays.asList;
- import static java.util.Collections.unmodifiableList;
- import static java.util.Objects.requireNonNull;
- import static org.apache.commons.lang3.StringUtils.uncapitalize;
- /**
- * The set of services that Refapp exports to OSGi, for use by plugins.
- *
- * @since 5.4 was a map in ContainerManager; this is more type-safe and removes a lot of boilerplate
- */
- @ParametersAreNonnullByDefault
- public class RefappHostComponentProvider implements ApplicationContextAware, HostComponentProvider {
- /*
- These components will be made available to plugins via OSGi. To export a new type:
- (1) add its interface (not class) below
- (2) make sure the injected Spring ApplicationContext contains a (single?) bean of that type
- */
- @SuppressWarnings("deprecation") // not this class' fault if Refapp uses deprecated types
- private static final Class<?>[] SERVICE_TYPES_TO_EXPORT = {
- ClusterLockService.class,
- ConnectionProvider.class,
- DescribedModuleDescriptorFactory.class,
- EventPublisher.class,
- HealthCheckWhitelist.class,
- LandlordRequests.class,
- ListableModuleDescriptorFactory.class,
- ModuleDescriptorFactory.class,
- ModuleFactory.class,
- PageBuilderService.class,
- PluginController.class,
- PluginMetadataManager.class,
- PluginResourceLocator.class,
- PrebakeWebResourceAssemblerFactory.class,
- ResourceBatchingConfiguration.class,
- SchedulerHistoryService.class,
- SchedulerService.class,
- ServletContextFactory.class,
- ServletModuleManager.class,
- SplitStartupPluginSystemLifecycle.class,
- TenantAccessor.class,
- TenantContext.class,
- VCacheFactory.class,
- WebResourceAssemblerFactory.class,
- WebResourceIntegration.class,
- WebResourceManager.class,
- WebResourceUrlProvider.class
- };
- /**
- * Factory method for this class.
- *
- * @return a new instance
- */
- @Nonnull
- public static RefappHostComponentProvider getInstance() {
- return new RefappHostComponentProvider(asList(SERVICE_TYPES_TO_EXPORT));
- }
- private final List<Class<?>> serviceTypes;
- private ApplicationContext applicationContext;
- @VisibleForTesting
- RefappHostComponentProvider(final List<Class<?>> serviceTypes) {
- this.serviceTypes = unmodifiableList(serviceTypes);
- }
- @Override
- public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = requireNonNull(applicationContext);
- }
- @Override
- public void provide(final ComponentRegistrar registrar) {
- final Map<Class<?>, Object> instancesByType = new LinkedHashMap<>();
- //noinspection CollectionAddedToSelf yes, this is weird, but that's what ContainerManager did
- instancesByType.put(Map.class, instancesByType);
- serviceTypes.forEach(serviceType -> {
- final Object instance = registerService(registrar, serviceType);
- instancesByType.put(serviceType, instance);
- });
- // Presumably some plugin needs to iterate over a map of all the exported services, including the Map itself...
- registrar.register(Map.class).forInstance(instancesByType).withName(getBeanName(Map.class));
- }
- private Object registerService(final ComponentRegistrar registrar, final Class<?> serviceType) {
- checkIsInterface(serviceType);
- final Object instance = applicationContext.getBean(serviceType);
- final String name = getBeanName(serviceType);
- registrar.register(serviceType).forInstance(instance).withName(name);
- return instance;
- }
- private void checkIsInterface(final Class<?> serviceType) {
- // Remember that annotations are also interfaces
- if (serviceType.isAnnotation() || !serviceType.isInterface()) {
- throw new IllegalArgumentException(
- "Only interfaces can be exported to OSGi, not " + serviceType.getName());
- }
- }
- private static String getBeanName(final Class<?> serviceType) {
- return uncapitalize(serviceType.getSimpleName());
- }
- }