/*
 * Copyright 2013 Netflix, Inc.
 *
 *      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 com.netflix.zuul.dependency.ribbon;

import com.netflix.client.ClientException;
import com.netflix.client.ClientFactory;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.config.*;
import com.netflix.zuul.ZuulApplicationInfo;
import com.netflix.zuul.constants.ZuulConstants;
import org.apache.commons.configuration.AbstractConfiguration;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Handles Eureka VIP names and addresses.
 *
 * @author mhawthorne
 */
public class RibbonConfig {


    static String APPLICATION_NAME = null;

    static String APPLICATION_STACK = null;

    private static Logger LOG = LoggerFactory.getLogger(RibbonConfig.class);


    private static final DynamicBooleanProperty AUTODETECT_BACKEND_VIPS =
            DynamicPropertyFactory.getInstance().getBooleanProperty(ZuulConstants.ZUUL_AUTODETECT_BACKEND_VIPS, true);
    private static final DynamicStringProperty DEFAULT_CLIENT =
            DynamicPropertyFactory.getInstance().getStringProperty(ZuulConstants.ZUUL_NIWS_DEFAULTCLIENT, null);

    /**
     * This method attempts to set up the default Ribbon origin VIP from properties and environment.
     * One method is through autoscale name convention. The Autoscaling group name can be set up as follow : zuul-origin_stack.
     * Zuul will derive the origin VIP  as origin-stack.{zuul.ribbon.vipAddress.template}
     * <p/>
     * the client may also be specified by the property ZuulConstants.ZUUL_NIWS_DEFAULTCLIENT
     *
     * @throws ClientException
     */
    public static void setupDefaultRibbonConfig() throws ClientException {
        final DeploymentContext config = ConfigurationManager.getDeploymentContext();

        String stack = config.getDeploymentStack();

        if (stack != null && stack.contains("_")) { //use stack for client and stack  client_stack
            setAppInfoFromZuulStack(stack);
        } else {
            String env = config.getDeploymentEnvironment();
            if (stack != null) {
                setApplicationName(stack);
            } else {
                if (DEFAULT_CLIENT.get() == null)
                    throw new RuntimeException("Can't figure out default origin vips. Set stack as appName_stack of set zuul.niws.defaultClient param");
                setApplicationName(DEFAULT_CLIENT.get());
            }

            setApplicationStack(env);
        }
        String vip = RibbonConfig.getDefaultVipName();
        String vipAddr = RibbonConfig.getDefaultVipAddress(getApplicationStack());
        String namespace = DynamicPropertyFactory.getInstance().getStringProperty(ZuulConstants.ZUUL_RIBBON_NAMESPACE, "ribbon").get();

        setIfNotDefined(vip, vipAddr);
        setIfNotDefined(getApplicationName() + "." + namespace + ".Port", "7001");
        setIfNotDefined(getApplicationName() + "." + namespace + ".AppName", getApplicationName());
        setIfNotDefined(getApplicationName() + "." + namespace + ".ReadTimeout", "2000");
        setIfNotDefined(getApplicationName() + "." + namespace + ".ConnectTimeout", "2000");
        setIfNotDefined(getApplicationName() + "." + namespace + ".MaxAutoRetriesNextServer", "1");
        setIfNotDefined(getApplicationName() + "." + namespace + ".FollowRedirects", "false");
        setIfNotDefined(getApplicationName() + "." + namespace + ".ConnIdleEvictTimeMilliSeconds", "3600000");
        setIfNotDefined(getApplicationName() + "." + namespace + ".EnableZoneAffinity", "true");
        DefaultClientConfigImpl clientConfig = DefaultClientConfigImpl.getClientConfigWithDefaultValues(getApplicationName(),
                namespace);
        ClientFactory.registerClientFromProperties(getApplicationName(), clientConfig);
    }

    private static void setIfNotDefined(String key, String value) {
        final AbstractConfiguration config = ConfigurationManager.getConfigInstance();
        if (config.getString(key) == null) {
            LOG.info("Setting default NIWS Property " + key + "=" + value);
            config.setProperty(key, value);
        }
    }


    /**
     * Parses out the the applicationName and application stack from the zuul "stack" element.
     * when deployed, the applicaiton
     *
     * @param stack
     * @return
     */
    public static boolean setAppInfoFromZuulStack(String stack) {
        String[] stackSplit = stack.split("_");
        if (stackSplit == null || stackSplit.length != 2) return false;

        setApplicationName(stackSplit[0]);
        setApplicationStack(stackSplit[1]);
        return true;
    }

    /**
     * @return the APPLICATION_NAME
     */
    public static String getApplicationName() {
        return APPLICATION_NAME;
    }

    /**
     * sets the application name of the origin
     *
     * @param applicationName
     */
    public static void setApplicationName(String applicationName) {
        RibbonConfig.APPLICATION_NAME = applicationName;
        if (ZuulApplicationInfo.getApplicationName() == null) ZuulApplicationInfo.setApplicationName(applicationName);
        LOG.info("Setting back end VIP application = " + applicationName);
    }

    /**
     * returns the application_stack
     *
     * @return
     */
    public static String getApplicationStack() {
        return APPLICATION_STACK;
    }

    /**
     * sets the default origin applcation stack
     *
     * @param stack
     */
    public static void setApplicationStack(String stack) {
        RibbonConfig.APPLICATION_STACK = stack;
        if (ZuulApplicationInfo.getStack() == null) ZuulApplicationInfo.setStack(stack);
        LOG.info("Setting back end VIP stack = " + stack);
    }

    /**
     * true if the app shoudl autodetect the origin vip
     *
     * @return true if the app shoudl autodetect the origin vip
     */
    public static final boolean isAutodetectingBackendVips() {
        return AUTODETECT_BACKEND_VIPS.get();
    }

    /**
     * returns the Ribbon property name for the default origin vip
     *
     * @return
     */
    public static final String getDefaultVipName() {
        String client = getApplicationName();
        if (client == null) client = DEFAULT_CLIENT.get();

        String namespace = DynamicPropertyFactory.getInstance().getStringProperty(ZuulConstants.ZUUL_RIBBON_NAMESPACE, "ribbon").get();

        String vipTemplate = "%s." + namespace + ".DeploymentContextBasedVipAddresses";
        return String.format(vipTemplate, client);
    }


    /**
     * builds the default vip address of the origin based on the stack.
     * You need to configure zuul.ribbon.vipAddress.template . eg zuul.ribbon.vipAddress.template=%s-%s.netflix.net:8888 where %s(1) is client and %s(2) is stack
     *
     * @param stack
     * @return
     */
    public static final String getDefaultVipAddress(String stack) {
        String client = getApplicationName();
        if (client == null) client = DEFAULT_CLIENT.get();

        String vipAddressTemplate = DynamicPropertyFactory.getInstance().getStringProperty(ZuulConstants.ZUUL_RIBBON_VIPADDRESS_TEMPLATE, null).get();
        if (vipAddressTemplate == null)
            throw new RuntimeException("need to configure zuul.ribbon.vipAddress.template . eg zuul.ribbon.vipAddress.template=%s-%s.netflix.net:8888 where %s(1) is client and %s(2) is stack");

        return String.format(vipAddressTemplate, client, stack);
    }


    public static final class UnitTest {

        @Test
        public void defaultVipAddressForStandardStack() {
            //todo fix
//            assertEquals("null-prod.netflix.net:7001", RibbonConfig.getDefaultVipAddress("prod"));
        }


        @Test
        public void defaultVipAddressForLatAmStack() {
            //todo fix
//            assertEquals("null-prod.latam.netflix.net:7001", RibbonConfig.getDefaultVipAddress("prod.latam"));
        }


    }

}

@@ -6006,16 +6006,17 @@
 gin appl
+i
 cation s

Fix typo in Javadoc