/**
 * Copyright 2016 Red Hat, Inc.
 * <p/>
 * Red Hat licenses this file to you 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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.fabric8.karaf;

import org.apache.aries.blueprint.ext.evaluator.PropertyEvaluator;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;

import java.util.Dictionary;
import java.util.LinkedHashMap;

/**
 * Ports Camel's env: sys: service: service.host: service.port: property
 * placeholder prefix resolution strategies so that they are supported in Blueprint via an
 * evaluator.
 *
 * see: http://camel.apache.org/using-propertyplaceholder.html
 */
@Component(
    name = "io.fabric8.karaf.env",
    immediate = true,
    enabled = true,
    policy = ConfigurationPolicy.IGNORE,
    createPid = false
)
@org.apache.felix.scr.annotations.Properties({@Property(
    name = "org.apache.aries.blueprint.ext.evaluator.name", value = "camel")
})
@Service(PropertyEvaluator.class)
public class CamelPropertyEvaluator implements PropertyEvaluator {

    LinkedHashMap<String, PropertiesFunction> functions = new LinkedHashMap<>();

    public CamelPropertyEvaluator() {
        addFunction(new EnvPropertiesFunction());
        addFunction(new SysPropertiesFunction());
        addFunction(new ServicePropertiesFunction());
        addFunction(new ServiceHostPropertiesFunction());
        addFunction(new ServicePortPropertiesFunction());
    }

    private void addFunction(PropertiesFunction function) {
        functions.put(function.getName(), function);
    }

    @Override
    public String evaluate(String key, Dictionary<String, String> dictionary) {
        for (PropertiesFunction function : functions.values()) {
            String token = function.getName() + ":";
            if (key.startsWith(token)) {
                String remainder = key.substring(token.length());
                String value = function.apply(remainder);
                if (value != null) {
                    return value;
                }
            }
        }
        return dictionary.get(key);
    }

}

@@ -657,16 +657,78 @@
 karaf;%0A%0A
+import java.util.Dictionary;%0Aimport java.util.LinkedHashMap;%0A%0A
 import o
@@ -1002,70 +1002,8 @@
 e;%0A%0A
-import java.util.Dictionary;%0Aimport java.util.LinkedHashMap;%0A%0A
 /**%0A
@@ -1162,18 +1162,18 @@
 rint
+%0A *
  via an
-%0A *
  eva
@@ -1246,16 +1246,217 @@
 er.html%0A
+ *%0A * It supports chained evaluators i.e $%7Benv+service:MY_ENV_VAR%7D where the first%0A * step is to resolve MY_ENV_VAR against environment variables then the result is%0A * resolved using service function.%0A
  */%0A@Com
@@ -1492,19 +1492,21 @@
 8.karaf.
-env
+camel
 %22,%0A    i
@@ -1845,21 +1845,34 @@
 uator %7B%0A
-%0A
     
+private final 
 LinkedHa
@@ -2482,88 +2482,232 @@
     
-for (PropertiesFunction function : functions.values()) %7B%0A            String toke
+String%5B%5D resolvers = Support.before(key, %22:%22).split(%22%5C%5C+%22);%0A        String remainder = Support.after(key, %22:%22);%0A        String value = null;%0A%0A        for (String resolver : resolvers) %7B%0A            PropertiesFunction functio
 n = 
@@ -2718,24 +2718,23 @@
 tion
+s
 .get
-Name() + %22:%22
+(resolver)
 ;%0A  
@@ -2751,121 +2751,107 @@
 if (
-key.startsWith(token)) %7B%0A                String remainder = key.substring(token.length());%0A                String
+function == null) %7B%0A                value = null;%0A                break;%0A            %7D%0A%0A           
  val
@@ -2878,28 +2878,24 @@
 remainder);%0A
-    
             
@@ -2931,26 +2931,27 @@
         
-    return
+remainder =
  value;%0A
@@ -2954,37 +2954,63 @@
 ue;%0A            
-    %7D
+%7D else %7B%0A                break;
 %0A            %7D%0A 
@@ -3010,32 +3010,33 @@
     %7D%0A        %7D%0A
+%0A
         return d
@@ -3033,16 +3033,40 @@
   return
+ value != null ? value :
  diction
@@ -3086,10 +3086,12 @@
 %0A    %7D%0A%0A
+%0A%0A
 %7D%0A

Add support for chained resolution to make k8s services discovery easy to use in karaf