/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * 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.gravitee.gateway.http.core.endpoint.impl;

import io.gravitee.common.component.AbstractLifecycleComponent;
import io.gravitee.definition.model.Api;
import io.gravitee.gateway.api.endpoint.Endpoint;
import io.gravitee.gateway.api.http.client.HttpClient;
import io.gravitee.gateway.http.core.endpoint.HttpEndpoint;
import io.gravitee.gateway.http.core.endpoint.EndpointLifecycleManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author David BRASSELY (david.brassely at graviteesource.com)
 * @author GraviteeSource Team
 */
public class EndpointLifecycleManagerImpl extends AbstractLifecycleComponent<EndpointLifecycleManager> implements EndpointLifecycleManager<HttpClient>, ApplicationContextAware {

    private final Logger LOGGER = LoggerFactory.getLogger(EndpointLifecycleManagerImpl.class);

    @Autowired
    private Api api;

    private ApplicationContext applicationContext;

    private final Map<String, HttpEndpoint> endpoints = new LinkedHashMap<>();
    private final Map<String, String> endpointsTarget = new LinkedHashMap<>();

    @Override
    protected void doStart() throws Exception {
        api.getProxy().getEndpoints()
                .stream()
                .filter(endpoint -> ! endpoint.isBackup())
                .forEach(endpoint -> {
                    try {
                        LOGGER.debug("Preparing a new target endpoint: {} [{}]", endpoint.getName(), endpoint.getTarget());
                        HttpClient httpClient = applicationContext.getBean(HttpClient.class, endpoint);
                        httpClient.start();
                        endpoints.put(endpoint.getName(), new HttpEndpoint(endpoint, httpClient));
                        endpointsTarget.put(endpoint.getName(), endpoint.getTarget());
                    } catch (Exception ex) {
                        LOGGER.error("Unexpected error while creating endpoint connector", ex);
                    }
                });
    }

    @Override
    protected void doStop() throws Exception {
        for(Map.Entry<String, HttpEndpoint> connectors : endpoints.entrySet()) {
            try {
                LOGGER.debug("Closing target endpoint: {}", connectors.getKey());
                connectors.getValue().getHttpClient().stop();
                endpoints.remove(connectors.getKey());
                endpointsTarget.remove(connectors.getKey());
            } catch (Exception ex) {
                LOGGER.error("Unexpected error while closing endpoint connector", ex);
            }
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public Endpoint<HttpClient> get(String endpointName) {
        return endpoints.get(endpointName);
    }

    @Override
    public Endpoint<HttpClient> getOrDefault(String endpointName) {
        Endpoint<HttpClient> endpoint = get(endpointName);
        return (endpoint != null) ? endpoint : endpoints.values().iterator().next();
    }

    @Override
    public Set<String> endpoints() {
        return Collections.unmodifiableSet(endpoints.keySet());
    }

    @Override
    public Map<String, String> targetByEndpoint() {
        return Collections.unmodifiableMap(endpointsTarget);
    }
}

@@ -934,28 +934,24 @@
 ndpoint.
-Http
 Endpoint
 ;%0Aimport
@@ -934,32 +934,48 @@
 ndpoint.Endpoint
+LifecycleManager
 ;%0Aimport io.grav
@@ -1002,32 +1002,36 @@
 re.endpoint.
+Http
 Endpoint
 LifecycleMan
@@ -1018,32 +1018,16 @@
 Endpoint
-LifecycleManager
 ;%0Aimport
@@ -1326,95 +1326,9 @@
 til.
-Collections;%0Aimport java.util.LinkedHashMap;%0Aimport java.util.Map;%0Aimport java.util.Set
+*
 ;%0A%0A/
@@ -2924,16 +2924,25 @@
     for(
+Iterator%3C
 Map.Entr
@@ -2968,21 +2968,14 @@
 int%3E
- connectors :
+%3E it =
  end
@@ -2991,19 +2991,112 @@
 trySet()
-) %7B
+.iterator(); it.hasNext(); ) %7B%0A            Map.Entry%3CString, HttpEndpoint%3E endpoint = it.next();
 %0A       
@@ -3166,26 +3166,24 @@
 t: %7B%7D%22, 
-connectors
+endpoint
 .getKey(
@@ -3202,26 +3202,24 @@
         
-connectors
+endpoint
 .getValu
@@ -3266,44 +3266,18 @@
     
-endpoints.remove(connectors.getKey()
+it.remove(
 );%0A 
@@ -3318,18 +3318,16 @@
 ove(
-connectors
+endpoint
 .get

Use an iterator when removing item from the data structure