package org.alien4cloud.bootstrap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.PriorityOrdered; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import alien4cloud.audit.rest.AuditController; import alien4cloud.plugin.IPluginLoadingCallback; import alien4cloud.plugin.model.ManagedPlugin; import alien4cloud.webconfiguration.RestDocumentationHandlerProvider; import alien4cloud.webconfiguration.RestDocumentationPluginsBootstrapper; import lombok.extern.slf4j.Slf4j; /** * Map rest services to the rest dispatcher. */ @Slf4j @Component public class PluginRestMapper implements IPluginLoadingCallback, HandlerMapping, PriorityOrdered { private List<HandlerMapping> handlerMappings = Lists.newArrayList(); private Map<String, RequestMappingHandlerMapping> pluginMappings = Maps.newHashMap(); @Inject private AuditController auditController; @Autowired(required = false) private RestDocumentationHandlerProvider restDocumentationHandlerProvider; @Autowired(required = false) private RestDocumentationPluginsBootstrapper documentationPluginsBootstrapper; @Override public synchronized void onPluginLoaded(ManagedPlugin managedPlugin) { mapContext(managedPlugin); } @Override public synchronized void onPluginClosed(ManagedPlugin managedPlugin) { RequestMappingHandlerMapping mapping = this.pluginMappings.remove(managedPlugin.getPlugin().getDescriptor().getId()); auditController.unRegister(mapping); for (int i = 0; i < this.handlerMappings.size(); i++) { // identity check and remove if this is the mapping associated with the plugin to close. if (this.handlerMappings.get(i) == mapping) { this.handlerMappings.remove(i); break; } } unregisterDocumentation(mapping); } private void mapContext(ManagedPlugin managedPlugin) { // dispatcher context is ready after the plugin mapper actually. RequestMappingHandlerMapping mapper = new RequestMappingHandlerMapping(); mapper.setApplicationContext(managedPlugin.getPluginContext()); mapper.afterPropertiesSet(); auditController.register(mapper); this.handlerMappings.add(mapper); this.pluginMappings.put(managedPlugin.getPlugin().getDescriptor().getId(), mapper); registerDocumentation(mapper); } @Override public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { if (log.isTraceEnabled()) { log.trace("Testing handler map [" + hm + "]"); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; } @Override public int getOrder() { return PriorityOrdered.HIGHEST_PRECEDENCE + 1; } private void registerDocumentation(RequestMappingHandlerMapping mapper) { if (restDocumentationHandlerProvider != null && documentationPluginsBootstrapper != null) { restDocumentationHandlerProvider.register(mapper); documentationPluginsBootstrapper.refresh(); } } private void unregisterDocumentation(RequestMappingHandlerMapping mapping) { if (restDocumentationHandlerProvider != null && documentationPluginsBootstrapper != null) { restDocumentationHandlerProvider.unregister(mapping); documentationPluginsBootstrapper.refresh(); } } }