content: 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();
          }
      }
  }