You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by im...@apache.org on 2013/11/10 18:09:45 UTC

[1/3] Added load balancer configuration parser and its test cases from lb.common component

Updated Branches:
  refs/heads/master 14d59ad37 -> 1041b1bae


http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java
new file mode 100755
index 0000000..5da1264
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java
@@ -0,0 +1,169 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.test;
+
+import java.io.File;
+
+import org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration;
+import org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration.ServiceConfiguration;
+import org.apache.stratos.load.balancer.conf.util.HostContext;
+
+import junit.framework.TestCase;
+
+public class LoadBalancerConfigurationTest extends TestCase {
+    
+    private LoadBalancerConfiguration lbConfig ;
+    private LoadBalancerConfiguration lbConfig1;
+    
+    
+    @Override
+    protected void setUp() throws Exception {
+
+        LoadBalancerConfiguration.setInstance(null);
+        File f = new File("src/test/resources/loadbalancer.conf");
+        System.setProperty("loadbalancer.conf", f.getAbsolutePath());
+        lbConfig = LoadBalancerConfiguration.getInstance();
+    }
+    
+    public final void testCreateLoadBalancerConfig() {
+
+        LoadBalancerConfiguration.LBConfiguration loadBalancerConfig =
+            lbConfig.getLoadBalancerConfig();
+        
+        assertEquals(1, loadBalancerConfig.getInstances());
+        assertEquals(5000, loadBalancerConfig.getAutoscalerTaskInterval());
+        assertEquals(15000, loadBalancerConfig.getServerStartupDelay());
+    }
+
+    public final void testCreateServicesConfig() {
+
+        /* Tests relavant to loadbalancer.conf file */
+        
+        ServiceConfiguration asServiceConfig =
+                                               lbConfig.getServiceConfig("wso2.as1.domain",
+                                                                         "worker");
+
+        assertEquals(1, asServiceConfig.getInstancesPerScaleUp());
+        assertEquals(5, asServiceConfig.getMaxAppInstances());
+        assertEquals(0, asServiceConfig.getMinAppInstances());
+        assertEquals(60000, asServiceConfig.getMessageExpiryTime());
+        assertEquals(400, asServiceConfig.getMaxRequestsPerSecond());
+        assertEquals(0.65, asServiceConfig.getAlarmingUpperRate());
+        assertEquals(10, asServiceConfig.getRoundsToAverage());
+        assertEquals("worker", asServiceConfig.getSubDomain());
+
+        asServiceConfig = lbConfig.getServiceConfig("wso2.as2.domain", "worker1");
+        assertEquals("worker1", asServiceConfig.getSubDomain());
+
+        asServiceConfig = lbConfig.getServiceConfig("wso2.esb.domain", "mgt");
+        assertEquals("mgt", asServiceConfig.getSubDomain());
+
+        assertEquals(2, lbConfig.getHostNamesTracker().keySet().size());
+        assertEquals(3, lbConfig.getHostNamesTracker().get("appserver").size());
+        assertEquals(2, lbConfig.getHostNamesTracker().get("esb").size());
+
+        for (HostContext ctx : lbConfig.getHostContextMap().values()) {
+
+            if (ctx.getHostName().equals("appserver.cloud-test.wso2.com")) {
+
+                assertEquals("nirmal", ctx.getSubDomainFromTenantId(30));
+                assertEquals(18, ctx.getTenantDomainContexts().size());
+            } else if (ctx.getHostName().equals("as2.cloud-test.wso2.com")) {
+                assertEquals("worker", ctx.getSubDomainFromTenantId(2));
+            } else if (ctx.getHostName().equals("esb.cloud-test.wso2.com")) {
+                assertEquals("mgt", ctx.getSubDomainFromTenantId(5));
+            }
+        }
+        
+        /* tests relevant to loadbalancer1.conf file */
+        
+        File f = new File("src/test/resources/loadbalancer2.conf");
+        System.setProperty("loadbalancer.conf", f.getAbsolutePath());
+        
+        LoadBalancerConfiguration.setInstance(null);
+        lbConfig1 = LoadBalancerConfiguration.getInstance();
+        
+        for (HostContext ctx : lbConfig1.getHostContextMap().values()) {
+
+            if (ctx.getHostName().equals("appserver.cloud-test.wso2.com")) {
+
+                assertEquals("nirmal", ctx.getSubDomainFromTenantId(30));
+                assertEquals("wso2.as1.domain", ctx.getDomainFromTenantId(5));
+                assertEquals("wso2.as.domain", ctx.getDomainFromTenantId(8));
+                assertEquals("wso2.as.domain", ctx.getDomainFromTenantId(2));
+                assertEquals(4, ctx.getTenantDomainContexts().size());
+                
+            } else if (ctx.getHostName().equals("esb.cloud-test.wso2.com")) {
+                
+                assertEquals("mgt", ctx.getSubDomainFromTenantId(5));
+            }
+        }
+
+    }
+
+    public final void testGetServiceDomains() throws Exception {
+
+        setUp();
+        String[] serviceDomains = lbConfig.getServiceDomains();
+        assertEquals(4, serviceDomains.length);
+        
+        assertTrue("wso2.as1.domain".equals(serviceDomains[0]) ||
+            "wso2.as1.domain".equals(serviceDomains[1]) ||
+            "wso2.as1.domain".equals(serviceDomains[2]) ||
+            "wso2.as1.domain".equals(serviceDomains[3]));
+        
+        assertTrue("wso2.as2.domain".equals(serviceDomains[0]) ||
+            "wso2.as2.domain".equals(serviceDomains[1]) ||
+            "wso2.as2.domain".equals(serviceDomains[2]) ||
+            "wso2.as2.domain".equals(serviceDomains[3]));
+        
+        assertTrue("wso2.as3.domain".equals(serviceDomains[0]) ||
+            "wso2.as3.domain".equals(serviceDomains[1]) ||
+            "wso2.as3.domain".equals(serviceDomains[2]) ||
+            "wso2.as3.domain".equals(serviceDomains[3]));
+        
+        assertTrue("wso2.esb.domain".equals(serviceDomains[0]) ||
+                   "wso2.esb.domain".equals(serviceDomains[1]) ||
+                   "wso2.esb.domain".equals(serviceDomains[2]) ||
+                   "wso2.esb.domain".equals(serviceDomains[3]));
+        
+    }
+    
+    public final void testGetServiceSubDomains() throws Exception {
+
+        setUp();
+        String[] serviceSubDomains = lbConfig.getServiceSubDomains("wso2.as3.domain");
+        assertEquals(2, serviceSubDomains.length);
+        
+        assertTrue("nirmal".equals(serviceSubDomains[0]) ||
+            "nirmal".equals(serviceSubDomains[1]));
+        
+        assertTrue("nirmal2".equals(serviceSubDomains[0]) ||
+            "nirmal2".equals(serviceSubDomains[1]));
+        
+        serviceSubDomains = lbConfig.getServiceSubDomains("wso2.esb.domain");
+        assertEquals(2, serviceSubDomains.length);
+        
+        serviceSubDomains = lbConfig.getServiceSubDomains("wso2.as1.domain");
+        assertEquals(1, serviceSubDomains.length);
+        
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/NodeBuilderTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/NodeBuilderTest.java b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/NodeBuilderTest.java
new file mode 100755
index 0000000..9b4e001
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/NodeBuilderTest.java
@@ -0,0 +1,123 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.test;
+
+import junit.framework.TestCase;
+
+import org.apache.stratos.load.balancer.conf.structure.Node;
+import org.apache.stratos.load.balancer.conf.structure.NodeBuilder;
+
+public class NodeBuilderTest extends TestCase {
+
+    String content;
+
+    public void setUp() throws Exception {
+    }
+
+    public final void testBuildNode() {
+
+        // Testing a node only has properties
+        Node a = new Node();
+        a.setName("loadbalancer");
+
+        content =
+            "securityGroups      stratos-appserver-lb;\ninstanceType        m1.large;\n"
+                + "instances           1;\nelasticIP           ${ELASTIC_IP};\n"
+                + "availabilityZone    us-east-1c;\npayload             /mnt/payload.zip;";
+
+        a = NodeBuilder.buildNode(a, content);
+
+        assertEquals("loadbalancer", a.getName());
+        assertEquals("stratos-appserver-lb", a.getProperty("securityGroups"));
+        assertEquals("${ELASTIC_IP}", a.getProperty("elasticIP"));
+        assertEquals("/mnt/payload.zip", a.getProperty("payload"));
+        assertNull(a.getProperty("payloader"));
+
+        // Testing a node has sub nodes and properties
+        a = new Node();
+        a.setName("appserver");
+
+        content =
+            "hosts                   appserver.cloud-test.wso2.com,as.cloud-test.wso2.com;\n"
+                + "domains   {\n" + "wso2.as1.domain {\n" + "tenant_range    1-100;\n" + "}\n"
+                + "wso2.as2.domain {\n" + "tenant_range    101-200;\n" + "}\n"
+                + "wso2.as3.domain { # domain\n" + "tenant_range    *;\n" + "}\n" + "}\n"
+                + "# line comment \n"
+                + "payload                 resources/cluster_node.zip;# payload\n"
+                + "availability_zone       us-east-1c;\n";
+
+        a = NodeBuilder.buildNode(a, content);
+
+        assertEquals("appserver", a.getName());
+        assertEquals(1, a.getChildNodes().size());
+        assertEquals("domains", a.getChildNodes().get(0).getName());
+        assertEquals("appserver.cloud-test.wso2.com,as.cloud-test.wso2.com",
+                            a.getProperty("hosts"));
+        assertEquals("resources/cluster_node.zip", a.getProperty("payload"));
+        assertEquals(null, a.getProperty("payloader"));
+
+        Node b = a.getChildNodes().get(0);
+
+        assertEquals(3, b.getChildNodes().size());
+        assertEquals(null, b.getProperty("payload"));
+
+        Node c = b.getChildNodes().get(0);
+
+        assertEquals(0, c.getChildNodes().size());
+        assertEquals("1-100", c.getProperty("tenant_range"));
+
+        c = b.getChildNodes().get(2);
+
+        assertEquals(0, c.getChildNodes().size());
+        assertEquals("*", c.getProperty("tenant_range"));
+        
+        String nodeStr = "appserver {\n" +
+                "\thosts\tappserver.cloud-test.wso2.com,as.cloud-test.wso2.com;\n" +
+                "\tpayload\tresources/cluster_node.zip;\n" +
+        		"\tavailability_zone\tus-east-1c;\n" +
+        		"\tdomains {\n" +
+        		"\t\twso2.as1.domain {\n" +
+        		"\t\t\ttenant_range\t1-100;\n" +
+        		"\t\t}\n" +
+        		"\t\twso2.as2.domain {\n" +
+        		"\t\t\ttenant_range\t101-200;\n" +
+        		"\t\t}\n" +
+        		"\t\twso2.as3.domain {\n" +
+        		"\t\t\ttenant_range\t*;\n" +
+        		"\t\t}\n" +
+        		"\t}\n" +
+        		"}";
+        
+        assertEquals(nodeStr, a.toString());
+        
+        // test equals method
+        assertEquals(true, a.equals(a));
+        assertEquals(false, a.equals(b));
+        assertEquals(false, c.equals(b));
+        
+        // test buildNode(String)
+        c = NodeBuilder.buildNode(nodeStr);
+        
+        assertEquals(c.getName(), "appserver");
+        assertEquals(c.getChildNodes().size(), 1);
+        assertEquals(c.getProperty("availability_zone"), "us-east-1c");
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer.conf
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer.conf b/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer.conf
new file mode 100755
index 0000000..7622e31
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer.conf
@@ -0,0 +1,84 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF 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
+#
+#   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.
+#
+
+loadbalancer {
+    instances	1;
+    enable_autoscaler	true;
+    # interval between two task executions in milliseconds
+    autoscaler_task_interval	5000;
+    # after an instance booted up, task will wait till this much of time and let the server started up
+    server_startup_delay		15000; #default will be 60000ms
+}
+
+services {
+    defaults {
+        min_app_instances 1;
+        max_app_instances       5;
+        max_requests_per_second   400;
+        alarming_upper_rate 0.65;
+        alarming_lower_rate 0.2;
+        scale_down_factor 0.25;
+        rounds_to_average       10;
+        instances_per_scale_up  1;
+        message_expiry_time     60000;
+    }
+
+    appserver {
+        hosts                   appserver.cloud-test.wso2.com, as.cloud-test.wso2.com;
+        sub_domain      worker1;
+        domains   {
+            wso2.as1.domain {
+            	hosts as2.cloud-test.wso2.com;
+            	  min_app_instances   0;
+            	  sub_domain      worker;
+                tenant_range    1-5;
+            }
+            wso2.as2.domain {
+                tenant_range    7;
+            }
+            wso2.as3.domain {
+                sub_domain nirmal;
+                tenant_range    10-20;
+            }
+            
+            wso2.as3.domain {
+                sub_domain nirmal2;
+                tenant_range    21-25;
+            }
+            
+            wso2.esb.domain {
+            	sub_domain nirmal;
+                tenant_range    *;
+            }
+        }
+    }
+    
+    esb {
+        hosts                   esb.cloud-test.wso2.com,mgt.as.cloud-test.wso2.com;
+        domains   {
+            wso2.esb.domain {
+                sub_domain      mgt;
+                tenant_range    *;
+            }
+        }
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer1.conf
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer1.conf b/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer1.conf
new file mode 100755
index 0000000..9535f06
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer1.conf
@@ -0,0 +1,60 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF 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
+#
+#   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.
+#
+#
+
+loadbalancer {
+    instances	1;
+    enable_autoscaler	true;
+    # interval between two task executions in milliseconds
+    autoscaler_task_interval	5000;
+    # after an instance booted up, task will wait till this much of time and let the server started up
+    server_startup_delay		15000; #default will be 60000ms
+}
+
+services {
+
+    appserver {
+        hosts                   appserver.cloud-test.wso2.com, as.cloud-test.wso2.com;
+        sub_domain      worker1;
+        domains   {
+            
+            wso2.as.domain {
+            	sub_domain nirmal;
+                tenant_range    *;
+            }
+            wso2.as1.domain {
+            	sub_domain nirmal;
+                tenant_range    5-7;
+            }
+        }
+    }
+    
+    esb {
+        hosts                   esb.cloud-test.wso2.com, mgt.as.cloud-test.wso2.com;
+        domains   {
+            wso2.esb.domain {
+                sub_domain      mgt;
+                tenant_range    *;
+            }
+        }
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer2.conf
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer2.conf b/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer2.conf
new file mode 100755
index 0000000..6fd85f2
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/test/resources/loadbalancer2.conf
@@ -0,0 +1,50 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF 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
+#
+#   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.
+#
+
+services {
+
+    appserver {
+        hosts                   appserver.cloud-test.wso2.com, as.cloud-test.wso2.com;
+        sub_domain      worker1;
+        domains   {
+            
+            wso2.as.domain {
+            	sub_domain nirmal;
+                tenant_range    *;
+            }
+            wso2.as1.domain {
+            	sub_domain nirmal;
+                tenant_range    5-7;
+            }
+        }
+    }
+    
+    esb {
+        hosts                   esb.cloud-test.wso2.com, mgt.as.cloud-test.wso2.com;
+        domains   {
+            wso2.esb.domain {
+                sub_domain      mgt;
+                tenant_range    *;
+            }
+        }
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/resources/testng.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/test/resources/testng.xml b/components/org.apache.stratos.load.balancer/src/test/resources/testng.xml
new file mode 100755
index 0000000..bc1cf56
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/test/resources/testng.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF 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
+
+   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.
+
+-->
+
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+<suite name="Default suite">
+  <test verbose="2" name="Default test">
+    <classes>
+    </classes>
+  </test>
+</suite>


Re: [2/3] git commit: Added load balancer configuration parser and its test cases from lb.common component

Posted by Nirmal Fernando <ni...@gmail.com>.
On Mon, Nov 11, 2013 at 10:30 AM, Imesh Gunaratne <im...@apache.org> wrote:

> Hi Nirmal,
>
> Yes I agree, that would be the ideal situation.
>
> We cleaned up previous load balancer components and created new ones.
> That's the reason for checking these files as new.  If you look at the
> commit message, it says these files were moved from lb.common.
>

Ok, thanks for the clarification. We should have not removed them in the
first place.

>
> Thanks
> Imesh
>
>
> On Mon, Nov 11, 2013 at 7:26 AM, Nirmal Fernando <ni...@gmail.com>wrote:
>
>> Imesh,
>>
>> These should have been git copied/moved.
>>  On Nov 10, 2013 10:40 PM, <im...@apache.org> wrote:
>>
>>> Added load balancer configuration parser and its test cases from
>>> lb.common component
>>>
>>>
>>> Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo
>>> Commit:
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/32565547
>>> Tree:
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/32565547
>>> Diff:
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/32565547
>>>
>>> Branch: refs/heads/master
>>> Commit: 32565547050e49e89dd8b76e1fcace9504e89c69
>>> Parents: 59811f9
>>> Author: Imesh Gunaratne <im...@apache.org>
>>> Authored: Sun Nov 10 22:37:36 2013 +0530
>>> Committer: Imesh Gunaratne <im...@apache.org>
>>> Committed: Sun Nov 10 22:37:36 2013 +0530
>>>
>>> ----------------------------------------------------------------------
>>>  .../conf/LoadBalancerConfiguration.java         | 1202
>>> ++++++++++++++++++
>>>  .../load/balancer/conf/structure/Node.java      |  356 ++++++
>>>  .../balancer/conf/structure/NodeBuilder.java    |  140 ++
>>>  .../load/balancer/conf/util/Constants.java      |   50 +
>>>  .../load/balancer/conf/util/HostContext.java    |  161 +++
>>>  .../conf/util/LoadBalancerConfigUtil.java       |  305 +++++
>>>  .../balancer/conf/util/TenantDomainContext.java |   80 ++
>>>  .../test/LoadBalancerConfigUtilTest.java        |   48 +
>>>  .../test/LoadBalancerConfigurationTest.java     |  169 +++
>>>  .../load/balancer/test/NodeBuilderTest.java     |  123 ++
>>>  .../src/test/resources/loadbalancer.conf        |   84 ++
>>>  .../src/test/resources/loadbalancer1.conf       |   60 +
>>>  .../src/test/resources/loadbalancer2.conf       |   50 +
>>>  .../src/test/resources/testng.xml               |   29 +
>>>  14 files changed, 2857 insertions(+)
>>> ----------------------------------------------------------------------
>>>
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
>>> new file mode 100755
>>> index 0000000..747ba5b
>>> --- /dev/null
>>> +++
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
>>> @@ -0,0 +1,1202 @@
>>> +/**
>>> + *  Licensed to the Apache Software Foundation (ASF) under one
>>> + *  or more contributor license agreements.  See the NOTICE file
>>> + *  distributed with this work for additional information
>>> + *  regarding copyright ownership.  The ASF 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
>>> +
>>> + *  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 org.apache.stratos.load.balancer.conf;
>>> +
>>> +import org.apache.commons.lang.builder.HashCodeBuilder;
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.synapse.commons.util.PropertyHelper;
>>> +import org.apache.stratos.load.balancer.conf.structure.Node;
>>> +import org.apache.stratos.load.balancer.conf.structure.NodeBuilder;
>>> +import org.apache.stratos.load.balancer.conf.util.Constants;
>>> +import org.apache.stratos.load.balancer.conf.util.HostContext;
>>> +import
>>> org.apache.stratos.load.balancer.conf.util.LoadBalancerConfigUtil;
>>> +import org.apache.stratos.load.balancer.conf.util.TenantDomainContext;
>>> +import java.io.*;
>>> +import java.net.URL;
>>> +import java.util.*;
>>> +
>>> +/**
>>> + * Data object which hold configuration data of the load analyzer task
>>> + */
>>> +@SuppressWarnings("unused")
>>> +public class LoadBalancerConfiguration implements Serializable {
>>> +
>>> +    protected static final long serialVersionUID =
>>> -5553545217542808233L;
>>> +
>>> +    private static final Log log =
>>> LogFactory.getLog(LoadBalancerConfiguration.class);
>>> +
>>> +    /**
>>> +     * This map is there to speed up the lookup time.
>>> +     * Key: domain
>>> +     * <p/>
>>> +     * Value: A map whose key is sub domain and value is
>>> ServiceConfiguration
>>> +     */
>>> +    private Map<String, Map<String, ServiceConfiguration>>
>>> serviceConfigurations =
>>> +            new HashMap<String, Map<String, ServiceConfiguration>>();
>>> +
>>> +    /**
>>> +     * Key - host name
>>> +     * Value - {@link
>>> org.apache.stratos.load.balancer.conf.util.HostContext}
>>> +     */
>>> +    private transient Map<String, HostContext> hostCtxt = new
>>> HashMap<String, HostContext>();
>>> +
>>> +    /**
>>> +     * This map is there to speed up the lookup time.
>>> +     * Key: service name/cartridge type (Stratos2). NOTE: that this is
>>> not the service cluster domain.
>>> +     * Value: list of {@link
>>> org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration.ServiceConfiguration}
>>> - corresponding objects under a service name.
>>> +     */
>>> +       private Map<String, List<ServiceConfiguration>>
>>> serviceNameToServiceConfigurations =
>>> +                       new HashMap<String,
>>> List<ServiceConfiguration>>();
>>> +
>>> +    /**
>>> +     * This list will be used to identify host name duplications among
>>> different services.
>>> +     * Within a service there can be duplications, but among different
>>> services you can't have duplications.
>>> +     * Key - service name
>>> +     * Value - hosts under the respective service.
>>> +     */
>>> +    private Map<String, Set<String>> hostNamesTracker = new
>>> HashMap<String, Set<String>>();
>>> +
>>> +    protected ServiceConfiguration defaultServiceConfig;
>>> +    protected LBConfiguration lbConfig;
>>> +
>>> +    /**
>>> +     * LBConfig file as a String
>>> +     */
>>> +    protected String lbConfigString;
>>> +
>>> +    /**
>>> +     * Root node object for loadbalancer.conf
>>> +     */
>>> +    protected Node rootNode;
>>> +
>>> +    private LoadBalancerConfiguration(){
>>> +        init(System.getProperty("loadbalancer.conf"));
>>> +    }
>>> +
>>> +    private static LoadBalancerConfiguration instance ;
>>> +
>>> +    public static LoadBalancerConfiguration getInstance(){
>>> +        if(instance == null){
>>> +            instance = new LoadBalancerConfiguration();
>>> +        }
>>> +        return instance;
>>> +    }
>>> +
>>> +    /**
>>> +     * Sample loadbalancer.conf:
>>> +     * <p/>
>>> +     * loadbalancer {
>>> +     * # minimum number of load balancer instances
>>> +     * instances           1;
>>> +     * # whether autoscaling enable or not
>>> +     * enable_autoscaler   true;
>>> +     * # End point reference of the Autoscaler Service
>>> +     * autoscaler_service_epr
>>> https://10.100.3.81:9443/services/AutoscalerService/;
>>> +     * # interval between two task executions in milliseconds
>>> +     * autoscaler_task_interval 1000;
>>> +     * # after an instance booted up, task will wait till this much of
>>> time and let the server started up
>>> +     * server_startup_delay 15000;
>>> +     * }
>>> +     * <p/>
>>> +     * services {
>>> +     * defaults {
>>> +     * min_app_instances       1;
>>> +     * max_app_instances       5;
>>> +     * queue_length_per_node   400;
>>> +     * rounds_to_average       10;
>>> +     * instances_per_scale_up  1;
>>> +     * message_expiry_time     60000;
>>> +     * }
>>> +     * <p/>
>>> +     * appserver {
>>> +     * hosts                   appserver.cloud-test.wso2.com,
>>> as.cloud-test.wso2.com;
>>> +     * domains   {
>>> +     * wso2.as1.domain {
>>> +     * tenant_range    1-100;
>>> +     * }
>>> +     * wso2.as2.domain {
>>> +     * tenant_range    101-200;
>>> +     * }
>>> +     * wso2.as3.domain {
>>> +     * tenant_range    *;
>>> +     * }
>>> +     * }
>>> +     * }
>>> +     * }
>>> +     *
>>> +     * @param configURL URL of the load balancer config
>>> +     */
>>> +    public void init(String configURL) {
>>> +
>>> +        if(configURL == null){
>>> +            String msg = "Cannot locate the location of the
>>> loadbalancer.conf file." +
>>> +                   " You need to set the 'loadbalancer.conf' system
>>> property.";
>>> +            log.error(msg);
>>> +            throw new RuntimeException(msg);
>>> +        }
>>> +
>>> +        if (configURL.startsWith("$system:")) {
>>> +            configURL =
>>> System.getProperty(configURL.substring("$system:".length()));
>>> +        }
>>> +
>>> +        try {
>>> +
>>> +            // get loadbalancer.conf file as a String
>>> +            if (configURL.startsWith(File.separator)) {
>>> +                lbConfigString = createLBConfigString(configURL);
>>> +            } else {
>>> +                lbConfigString = createLBConfigString(new
>>> URL(configURL).openStream());
>>> +            }
>>> +
>>> +        } catch (Exception e) {
>>> +            String msg = "Cannot read configuration file from " +
>>> configURL;
>>> +            log.error(msg, e);
>>> +            throw new RuntimeException(msg, e);
>>> +        }
>>> +
>>> +        // build a Node object for whole loadbalancer.conf
>>> +        rootNode = new Node();
>>> +        rootNode.setName("root");
>>> +        rootNode = NodeBuilder.buildNode(rootNode, lbConfigString);
>>> +
>>> +        // load 'loadbalancer' node
>>> +        Node lbConfigNode =
>>> rootNode.findChildNodeByName(Constants.LOAD_BALANCER_ELEMENT);
>>> +
>>> +        if(lbConfigNode != null){
>>> +               createConfiguration(lbConfig = new LBConfiguration(),
>>> lbConfigNode);
>>> +        }
>>> +
>>> +        // load services node
>>> +        Node servicesConfigNode =
>>> rootNode.findChildNodeByName(Constants.SERVICES_ELEMENT);
>>> +
>>> +        if (servicesConfigNode == null) {
>>> +            String msg = "Mandatory " + Constants.SERVICES_ELEMENT +
>>> +                    " element can not be found in the configuration
>>> file.";
>>> +            log.error(msg);
>>> +            throw new RuntimeException(msg);
>>> +        }
>>> +
>>> +        // Set services configuration
>>> +        createServicesConfig(servicesConfigNode);
>>> +
>>> +    }
>>> +
>>> +
>>> +    /**
>>> +     * Process the content of the following 'services' element
>>> +     * <p/>
>>> +     * services {
>>> +     * defaults {
>>> +     * min_app_instances       1;
>>> +     * max_app_instances       5;
>>> +     * queue_length_per_node   400;
>>> +     * rounds_to_average       10;
>>> +     * instances_per_scale_up  1;
>>> +     * message_expiry_time     60000;
>>> +     * }
>>> +     * <p/>
>>> +     * appserver {
>>> +     * hosts                   appserver.cloud-test.wso2.com,
>>> as.cloud-test.wso2.com;
>>> +     * domains   {
>>> +     * wso2.as1.domain {
>>> +     * tenant_range    1-100;
>>> +     * }
>>> +     * wso2.as2.domain {
>>> +     * tenant_range    101-200;
>>> +     * }
>>> +     * wso2.as3.domain {
>>> +     * tenant_range    *;
>>> +     * }
>>> +     * }
>>> +     * }
>>> +     * }
>>> +     *
>>> +     * @param servicesConfigNode services element's Node
>>> +     */
>>> +    public List<ServiceConfiguration> createServicesConfig(Node
>>> servicesConfigNode) {
>>> +
>>> +        // current list of service configs
>>> +        List<ServiceConfiguration> currentServiceConfigs = new
>>> ArrayList<ServiceConfiguration>();
>>> +
>>> +        // Building default configuration
>>> +        Node defaultNode =
>>> servicesConfigNode.findChildNodeByName(Constants.DEFAULTS_ELEMENT);
>>> +
>>> +        if (defaultNode != null) {
>>> +
>>> +            createConfiguration(defaultServiceConfig = new
>>> ServiceConfiguration(), defaultNode);
>>> +        }
>>> +
>>> +        // Building custom services configuration
>>> +        for (Node serviceNode : servicesConfigNode.getChildNodes()) {
>>> +            //skip default node
>>> +            if (serviceNode != defaultNode) {
>>> +
>>> +                String serviceName = serviceNode.getName();
>>> +
>>> +                // reading domains
>>> +
>>> +                Node domainsNode;
>>> +
>>> +                if (serviceNode.getChildNodes().isEmpty() ||
>>> +                        !(domainsNode =
>>> serviceNode.getChildNodes().get(0)).getName().equals(
>>> +                                Constants.DOMAIN_ELEMENT)) {
>>> +
>>> +                    String msg = "The mandatory domains element, child
>>> of the " + serviceName +
>>> +                            " element is not specified in the
>>> configuration file. \n"+
>>> +                            serviceNode.toString();
>>> +                    log.error(msg);
>>> +                    throw new RuntimeException(msg);
>>> +                }
>>> +
>>> +                if (domainsNode.getChildNodes().isEmpty()) {
>>> +                    // this is probably a mistake, so we don't proceed
>>> +                    String msg = "No domain is specified under " +
>>> Constants.DOMAIN_ELEMENT +
>>> +                            " of " + serviceName + " element.";
>>> +                    log.error(msg);
>>> +                    throw new RuntimeException(msg);
>>> +                }
>>> +
>>> +                ServiceConfiguration serviceConfig;
>>> +
>>> +                // iterates through all the service domain specified in
>>> this service element.
>>> +                for (Node domain : domainsNode.getChildNodes()) {
>>> +
>>> +                    // create a new service configuration
>>> +                    serviceConfig = new ServiceConfiguration();
>>> +
>>> +                    // set service name
>>> +                    serviceConfig.setServiceName(serviceName);
>>> +
>>> +                    // set domain name
>>> +                    serviceConfig.setDomain(domain.getName());
>>> +
>>> +                    // let's set properties common to all domains
>>> specified in this service element.
>>> +                    createConfiguration(serviceConfig, serviceNode);
>>> +
>>> +                    // load properties specified under this service
>>> domain element.
>>> +                    createConfiguration(serviceConfig, domain);
>>> +
>>> +                    // check host name duplication
>>> +                    if(isDuplicatedHost(serviceNode.getName(),
>>> serviceConfig)){
>>> +                        // this is probably a mistake, so we don't
>>> proceed
>>> +                        String msg = "Duplicated host names detected
>>> for different service domains.\n" +
>>> +                                "Element: \n"+serviceNode.toString();
>>> +                        log.error(msg);
>>> +                        throw new RuntimeException(msg);
>>> +                    }
>>> +
>>> +                    currentServiceConfigs.add(serviceConfig);
>>> +
>>> +                }
>>> +            }
>>> +        }
>>> +
>>> +        for (ServiceConfiguration serviceConfiguration :
>>> currentServiceConfigs) {
>>> +
>>> +            // add the built ServiceConfiguration, to the map
>>> +            addServiceConfiguration(serviceConfiguration);
>>> +
>>> +        }
>>> +
>>> +        return currentServiceConfigs;
>>> +
>>> +    }
>>> +
>>> +
>>> +    public boolean addServiceConfiguration(ServiceConfiguration
>>> serviceConfig) {
>>> +
>>> +        Map<String, ServiceConfiguration> map;
>>> +        String domain = serviceConfig.getDomain();
>>> +
>>> +        if(domain == null){
>>> +            String msg = "Domain of a Service Configuration cannot be
>>> null. Hence this " +
>>> +                       "Configuration will be neglected.";
>>> +            log.error(msg);
>>> +            return false;
>>> +        }
>>> +
>>> +        String subDomain = serviceConfig.getSubDomain();
>>> +
>>> +        if (serviceConfigurations.containsKey(domain)) {
>>> +            map = serviceConfigurations.get(domain);
>>> +        } else {
>>> +            map = new HashMap<String, ServiceConfiguration>();
>>> +        }
>>> +        // put this serviceConfig
>>> +        map.put(subDomain, serviceConfig);
>>> +
>>> +        // update the parent map
>>> +        serviceConfigurations.put(domain, map);
>>> +
>>> +        // add to serviceNameToServiceConfiguration map
>>> +        List<ServiceConfiguration> configs;
>>> +
>>>  if(serviceNameToServiceConfigurations.get(serviceConfig.getServiceName())
>>> == null){
>>> +               configs = new ArrayList<ServiceConfiguration>();
>>> +
>>> +        }else{
>>> +               configs =
>>> serviceNameToServiceConfigurations.get(serviceConfig.getServiceName());
>>> +        }
>>> +
>>> +        if(!configs.contains(serviceConfig)){
>>> +               configs.add(serviceConfig);
>>> +        }
>>> +
>>>  serviceNameToServiceConfigurations.put(serviceConfig.getServiceName(),
>>> configs);
>>> +
>>> +        return true;
>>> +    }
>>> +
>>> +    public ServiceConfiguration removeServiceConfiguration(String
>>> domain, String subDomain) {
>>> +
>>> +        Map<String, ServiceConfiguration> map;
>>> +        ServiceConfiguration serviceConfig = null;
>>> +
>>> +        if(domain == null){
>>> +            String msg = "Domain of a Service Configuration cannot be
>>> null. Hence this " +
>>> +                       "Configuration will be neglected.";
>>> +            log.error(msg);
>>> +            return null;
>>> +        }
>>> +
>>> +        if (serviceConfigurations.containsKey(domain)) {
>>> +            map = serviceConfigurations.get(domain);
>>> +
>>> +            if(map != null){
>>> +               serviceConfig = map.remove(subDomain);
>>> +            }
>>> +        }
>>> +
>>> +        if(serviceConfig == null){
>>> +               String msg = "No matching service configuration found
>>> for domain: "+domain+
>>> +                               ", sub domain: "+subDomain;
>>> +            log.error(msg);
>>> +               return null;
>>> +        }
>>> +
>>> +        String serviceName = serviceConfig.getServiceName();
>>> +
>>> +        if (serviceName != null &&
>>> serviceNameToServiceConfigurations.containsKey(serviceName)) {
>>> +            if(serviceConfig != null){
>>> +               List<ServiceConfiguration> list =
>>> serviceNameToServiceConfigurations.get(serviceName);
>>> +
>>> +               list.remove(serviceConfig);
>>> +
>>> +               serviceNameToServiceConfigurations.put(serviceName,
>>> list);
>>> +            }
>>> +        }
>>> +
>>> +        Set<String> allHosts;
>>> +
>>> +        if (hostNamesTracker.containsKey(serviceName)) {
>>> +            allHosts = hostNamesTracker.get(serviceName);
>>> +
>>> +            for (String hostName : serviceConfig.getHosts()) {
>>> +
>>> +                               if (hostName != null) {
>>> +
>>> +                                       allHosts.remove(hostName);
>>> +
>>> +                                       hostCtxt.remove(hostName);
>>> +                               }
>>> +            }
>>> +        }
>>> +
>>> +        return serviceConfig;
>>> +    }
>>> +
>>> +    public void resetData(){
>>> +       serviceConfigurations =
>>> +                new HashMap<String, Map<String,
>>> ServiceConfiguration>>();
>>> +
>>> +       serviceNameToServiceConfigurations =
>>> +                       new HashMap<String,
>>> List<ServiceConfiguration>>();
>>> +
>>> +    }
>>> +
>>> +
>>> +    /**
>>> +     * Duplications can only be seen, when you traverse down the
>>> configuration file.
>>> +     *
>>> +     */
>>> +    public boolean isDuplicatedHost(String name, ServiceConfiguration
>>> serviceConfig) {
>>> +
>>> +        /**
>>> +         * This will be populated with host names of all other services
>>> other than the
>>> +         * service subjected to the test.
>>> +         */
>>> +        List<String> hostsOtherThanMine = new
>>> ArrayList<String>(hostNamesTracker.values().size());
>>> +
>>> +        for (Map.Entry<String, Set<String>> entry :
>>> hostNamesTracker.entrySet()) {
>>> +            if (!entry.getKey().equals(name)) {
>>> +                hostsOtherThanMine.addAll(entry.getValue());
>>> +            }
>>> +        }
>>> +
>>> +        for (String host : serviceConfig.getHosts()) {
>>> +            if (!hostsOtherThanMine.isEmpty() &&
>>> hostsOtherThanMine.contains(host)) {
>>> +                return true;
>>> +            }
>>> +        }
>>> +
>>> +        addToHostNameTrackerMap(name, serviceConfig.getHosts());
>>> +
>>> +        return false;
>>> +    }
>>> +
>>> +
>>> +    public void addToHostNameTrackerMap(String name, List<String>
>>> hosts) {
>>> +
>>> +        Set<String> allHosts;
>>> +
>>> +        if (hostNamesTracker.containsKey(name)) {
>>> +            allHosts = hostNamesTracker.get(name);
>>> +            allHosts.addAll(hosts);
>>> +        } else {
>>> +            allHosts = new HashSet<String>(hosts);
>>> +        }
>>> +        hostNamesTracker.put(name, allHosts);
>>> +    }
>>> +
>>> +    public void addToHostContextMap(String hostName, HostContext ctxt) {
>>> +
>>> +        if (hostName != null && ctxt != null) {
>>> +            hostCtxt.put(hostName, ctxt);
>>> +        }
>>> +    }
>>> +
>>> +    /**
>>> +     * Return a map of {@link
>>> org.apache.stratos.load.balancer.conf.util.HostContext}.
>>> +     * @return
>>> +     */
>>> +    public Map<String, HostContext> getHostContextMap() {
>>> +
>>> +        List<Integer> tenantIds;
>>> +        Map<String, String> URLSuffixes;
>>> +
>>> +        // FIXME if possible! I couldn't think of any other way to do
>>> this, at this moment.
>>> +        // Note: some of these for-loops are pretty small, thus no
>>> considerable performance overhead.
>>> +        // iterate through each service
>>> +        for (Iterator<Set<String>> it =
>>> hostNamesTracker.values().iterator(); it.hasNext();) {
>>> +
>>> +            // iterate through host names of this service
>>> +            for (String hostName : ((Set<String>) it.next())) {
>>> +
>>> +                // building HostContext
>>> +                HostContext ctxt = new HostContext(hostName);
>>> +
>>> +                // iterate through domains of this host
>>> +                for (Map.Entry<String, Map<String,
>>> ServiceConfiguration>> parentMap : serviceConfigurations.entrySet()) {
>>> +
>>> +                    // iterate through sub domain of this domain
>>> +                    for (Map.Entry<String, ServiceConfiguration>
>>> childMap : parentMap.getValue()
>>> +                            .entrySet()) {
>>> +                        // iterate through hosts of this
>>> +                        for (String host :
>>> childMap.getValue().getHosts()) {
>>> +                            // if a matching Service configuration is
>>> found.
>>> +                            if (host.equals(hostName)) {
>>> +
>>> +                                String tenantRange =
>>> childMap.getValue().getTenantRange();
>>> +                                String domain = parentMap.getKey();
>>> +                                String subDomain = childMap.getKey();
>>> +
>>> +
>>>  ctxt.addTenantDomainContexts(LoadBalancerConfigUtil.getTenantDomainContexts(tenantRange,
>>> domain, subDomain));
>>> +
>>> +                                break;
>>> +                            }
>>> +                        }
>>> +
>>> +                        //iterate through URL suffixes
>>> +                        for(Map.Entry<String, String> entry :
>>> childMap.getValue().getUrl_suffix().entrySet()) {
>>> +                            if(entry.getKey().equals(hostName)) {
>>> +
>>> +                                ctxt.setUrlSuffix(entry.getValue());
>>> +
>>> +                                break;
>>> +                            }
>>> +
>>> +                        }
>>> +                    }
>>> +                }
>>> +
>>> +                // add this hostCtxt
>>> +                hostCtxt.put(hostName, ctxt);
>>> +            }
>>> +
>>> +        }
>>> +
>>> +        return hostCtxt;
>>> +
>>> +    }
>>> +
>>> +    protected void createConfiguration(Configuration config, Node node)
>>> {
>>> +
>>> +        if (node == null) {
>>> +            String msg = "The configuration element for " +
>>> +                    config.getClass().getName() + " is null.";
>>> +            throw new RuntimeException(msg);
>>> +        }
>>> +
>>> +        try {
>>> +            // load properties
>>> +            for (Map.Entry<String, String> entry :
>>> node.getProperties().entrySet()) {
>>> +                String key = entry.getKey();
>>> +                String value = entry.getValue();
>>> +
>>> +                PropertyHelper.setInstanceProperty(key, value, config);
>>> +            }
>>> +
>>> +        } catch (Exception e) {
>>> +            String msg = "Error setting values to " +
>>> config.getClass().getName();
>>> +            log.error(msg, e);
>>> +            throw new RuntimeException(msg, e);
>>> +        }
>>> +    }
>>> +
>>> +    public LBConfiguration getLoadBalancerConfig() {
>>> +        return lbConfig;
>>> +    }
>>> +
>>> +    public String[] getServiceDomains() {
>>> +
>>> +        Object[] objs = serviceConfigurations.keySet().toArray();
>>> +
>>> +        return Arrays.copyOf(objs, objs.length, String[].class);
>>> +
>>> +    }
>>> +
>>> +    public String[] getServiceSubDomains(String domain) {
>>> +
>>> +        if (serviceConfigurations.get(domain) != null) {
>>> +            Object[] objs =
>>> serviceConfigurations.get(domain).keySet().toArray();
>>> +            return Arrays.copyOf(objs, objs.length, String[].class);
>>> +        }
>>> +
>>> +        return new String[0];
>>> +    }
>>> +
>>> +    public ServiceConfiguration getServiceConfig(String domain, String
>>> subDomain) {
>>> +        if (serviceConfigurations.get(domain) != null) {
>>> +            return serviceConfigurations.get(domain).get(subDomain);
>>> +        }
>>> +        return null;
>>> +    }
>>> +
>>> +
>>> +    public List<ServiceConfiguration> getServiceConfigs(String
>>> serviceName) {
>>> +        return serviceNameToServiceConfigurations.get(serviceName);
>>> +    }
>>> +
>>> +    /**
>>> +     * Convert given configuration file to a single String
>>> +     *
>>> +     * @param configFileName - file name to convert
>>> +     * @return String with complete lb configuration
>>> +     * @throws java.io.FileNotFoundException
>>> +     */
>>> +    public String createLBConfigString(String configFileName) throws
>>> FileNotFoundException {
>>> +        StringBuilder lbConfigString = new StringBuilder("");
>>> +
>>> +        File configFile = new File(configFileName);
>>> +        Scanner scanner;
>>> +
>>> +        scanner = new Scanner(configFile);
>>> +
>>> +        while (scanner.hasNextLine()) {
>>> +            lbConfigString.append(scanner.nextLine().trim() + "\n");
>>> +        }
>>> +
>>> +        return lbConfigString.toString().trim();
>>> +    }
>>> +
>>> +    public String createLBConfigString(InputStream configFileName)
>>> throws IOException {
>>> +
>>> +        // read the stream with BufferedReader
>>> +        BufferedReader br = new BufferedReader(new
>>> InputStreamReader(configFileName));
>>> +
>>> +        StringBuilder sb = new StringBuilder();
>>> +
>>> +        String line;
>>> +        while ((line = br.readLine()) != null) {
>>> +            sb.append(line.trim() + "\n");
>>> +        }
>>> +
>>> +        return sb.toString().trim();
>>> +    }
>>> +
>>> +    public abstract class Configuration implements Serializable {
>>> +
>>> +        private static final long serialVersionUID =
>>> -5433889427746551250L;
>>> +        protected String imageId = System.getenv("ami_id");
>>> +        protected String payload;
>>> +        protected boolean payloadSet;
>>> +
>>> +        protected String availability_zone = "us-east-1c";
>>> +        protected boolean availabilityZoneSet;
>>> +
>>> +        protected String[] security_groups = new String[]{"default"};
>>> +        protected boolean securityGroupsSet;
>>> +
>>> +        protected String instance_type = "m1.large";
>>> +        protected boolean instanceTypeSet;
>>> +
>>> +        protected String additional_info;
>>> +
>>> +        public String getImageId() {
>>> +            return imageId;
>>> +        }
>>> +
>>> +        public String getAdditionalInfo() {
>>> +            return additional_info;
>>> +        }
>>> +
>>> +        public String getAvailability_zone() {
>>> +            if (this instanceof LBConfiguration) {
>>> +                return availability_zone;
>>> +            }
>>> +            if (availabilityZoneSet) {
>>> +                return availability_zone;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.availabilityZoneSet) {
>>> +                return defaultServiceConfig.availability_zone;
>>> +            }
>>> +            return availability_zone;
>>> +        }
>>> +
>>> +        public String[] getSecurityGroups() {
>>> +            if (this instanceof LBConfiguration) {
>>> +                return security_groups;
>>> +            }
>>> +            if (securityGroupsSet) {
>>> +                return security_groups;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.securityGroupsSet) {
>>> +                return defaultServiceConfig.security_groups;
>>> +            }
>>> +            return security_groups;
>>> +        }
>>> +
>>> +        public String getInstanceType() {
>>> +            if (this instanceof LBConfiguration) {
>>> +                return instance_type;
>>> +            }
>>> +            if (instanceTypeSet) {
>>> +                return instance_type;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.instanceTypeSet) {
>>> +                return defaultServiceConfig.instance_type;
>>> +            }
>>> +            return instance_type;
>>> +        }
>>> +
>>> +
>>> +        public String getUserData() {
>>> +            if (payload == null) {
>>> +                payload =
>>> LoadBalancerConfigUtil.getUserData("resources/cluster_node.zip");
>>> +            }
>>> +            if (this instanceof LBConfiguration) {
>>> +                return payload;
>>> +            }
>>> +            if (payloadSet) {
>>> +                return payload;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.payloadSet) {
>>> +                return defaultServiceConfig.payload;
>>> +            }
>>> +            return payload;
>>> +        }
>>> +
>>> +        public void setPayload(String payload) {
>>> +            this.payload =
>>> LoadBalancerConfigUtil.getUserData(LoadBalancerConfigUtil.replaceVariables(payload));
>>> +            this.payloadSet = true;
>>> +        }
>>> +
>>> +        public void setAvailability_zone(String availabilityZone) {
>>> +            this.availability_zone =
>>> LoadBalancerConfigUtil.replaceVariables(availabilityZone);
>>> +            this.availabilityZoneSet = true;
>>> +        }
>>> +
>>> +        public void setSecurity_groups(String securityGroups) {
>>> +            this.security_groups =
>>> LoadBalancerConfigUtil.replaceVariables(securityGroups).split(",");
>>> +            this.securityGroupsSet = true;
>>> +        }
>>> +
>>> +        public void setInstance_type(String instanceType) {
>>> +            this.instance_type =
>>> LoadBalancerConfigUtil.replaceVariables(instanceType);
>>> +            this.instanceTypeSet = true;
>>> +        }
>>> +
>>> +    }
>>> +
>>> +    public class LBConfiguration extends Configuration implements
>>> Serializable {
>>> +
>>> +        private static final long serialVersionUID =
>>> 1357143883932816418L;
>>> +        private String elasticIP;//=
>>> LoadBalancerConfigUtil.replaceVariables("${ELASTIC_IP}");
>>> +        private int instances = 1;
>>> +        private boolean isAutoscaleEnabled;
>>> +        private int autoscalerTaskInterval = 30000;
>>> +        private String autoscalerServiceEpr;
>>> +        private int serverStartupDelay = 60000;
>>> +        private int sizeOfCache = 0 ;
>>> +        private boolean failOver;
>>> +        private int sessionTimeOut = -1;
>>> +        private String groupManagementAgentClass;
>>> +        private String autoscalerTaskClass;
>>> +        private String mbServerUrl;
>>> +        private boolean useEmbeddedAutoscaler = true;
>>> +        private String algorithm =
>>> "org.apache.synapse.endpoints.algorithms.RoundRobin";
>>> +
>>> +        public String getElasticIP() {
>>> +            return elasticIP;
>>> +        }
>>> +
>>> +        public int getInstances() {
>>> +            return instances;
>>> +        }
>>> +
>>> +        public boolean isAutoscaleEnabled() {
>>> +            return isAutoscaleEnabled;
>>> +        }
>>> +
>>> +        public boolean useEmbeddedAutoscaler() {
>>> +            return useEmbeddedAutoscaler;
>>> +        }
>>> +
>>> +        public boolean getFailOver() {
>>> +            return failOver;
>>> +        }
>>> +
>>> +        public String getAutoscalerServiceEpr() {
>>> +            return autoscalerServiceEpr;
>>> +        }
>>> +
>>> +        public int getAutoscalerTaskInterval() {
>>> +            return autoscalerTaskInterval;
>>> +        }
>>> +
>>> +        public int getServerStartupDelay() {
>>> +            return serverStartupDelay;
>>> +        }
>>> +
>>> +        public int getSessionTimeOut() {
>>> +            return sessionTimeOut;
>>> +        }
>>> +
>>> +        public void setElasticIP(String elasticIP) {
>>> +            this.elasticIP =
>>> LoadBalancerConfigUtil.replaceVariables(elasticIP);
>>> +        }
>>> +
>>> +        public void setInstances(int instances) {
>>> +            this.instances = instances;
>>> +        }
>>> +
>>> +        public void setEnable_autoscaler(String isEnabled) {
>>> +            this.isAutoscaleEnabled = Boolean.parseBoolean(isEnabled);
>>> +        }
>>> +
>>> +        public void setUse_embedded_autoscaler(String use) {
>>> +            this.useEmbeddedAutoscaler = Boolean.parseBoolean(use);
>>> +        }
>>> +
>>> +        public void setFail_over(String isEnabled) {
>>> +            this.failOver = Boolean.parseBoolean(isEnabled);
>>> +        }
>>> +
>>> +        public void setAutoscaler_service_epr(String epr) {
>>> +            this.autoscalerServiceEpr = epr;
>>> +        }
>>> +
>>> +        public void setMb_server_url(String url) {
>>> +            this.mbServerUrl = url;
>>> +        }
>>> +
>>> +        public String getMbServerUrl() {
>>> +               return mbServerUrl;
>>> +        }
>>> +
>>> +               public void setAutoscaler_task_interval(String interval)
>>> {
>>> +            this.autoscalerTaskInterval = Integer.parseInt(interval);
>>> +        }
>>> +
>>> +        public void setServer_startup_delay(String delay) {
>>> +            this.serverStartupDelay = Integer.parseInt(delay);
>>> +        }
>>> +
>>> +        public void setSession_timeout(String timeout) {
>>> +            this.sessionTimeOut = Integer.parseInt(timeout);
>>> +        }
>>> +
>>> +        public String getAlgorithm() {
>>> +            return algorithm;
>>> +        }
>>> +
>>> +        public void setAlgorithm(String algorithm) {
>>> +            if (algorithm != null) {
>>> +                this.algorithm = algorithm;
>>> +            }
>>> +        }
>>> +
>>> +        public int getSizeOfCache() {
>>> +            return sizeOfCache;
>>> +        }
>>> +
>>> +        public void setSize_of_cache(int sizeOfCache) {
>>> +            this.sizeOfCache = sizeOfCache;
>>> +        }
>>> +
>>> +        public String getGroupManagementAgentClass() {
>>> +            return groupManagementAgentClass;
>>> +        }
>>> +
>>> +        public String getAutoscalerTaskClass() {
>>> +            return autoscalerTaskClass;
>>> +        }
>>> +
>>> +        public void setGroup_mgt_agent(String
>>> groupManagementAgentClass){
>>> +            this.groupManagementAgentClass = groupManagementAgentClass;
>>> +        }
>>> +
>>> +        public void setAutoscaler_task(String autoscalerTaskClass){
>>> +            this.autoscalerTaskClass = autoscalerTaskClass;
>>> +        }
>>> +    }
>>> +
>>> +    public class ServiceConfiguration extends Configuration implements
>>> Serializable {
>>> +
>>> +       private String serviceName;
>>> +
>>> +        public String getServiceName() {
>>> +               return serviceName;
>>> +        }
>>> +
>>> +               public void setServiceName(String name) {
>>> +               this.serviceName = name;
>>> +        }
>>> +
>>> +               public String getPublicIp() {
>>> +               return publicIp;
>>> +        }
>>> +
>>> +               public void setPublic_ip(String publicIp) {
>>> +               this.publicIp = publicIp;
>>> +        }
>>> +
>>> +               private String publicIp;
>>> +
>>> +               private static final long serialVersionUID =
>>> 8707314702788040116L;
>>> +        private int minAppInstances = 1;
>>> +        private boolean minAppInstancesSet;
>>> +
>>> +        private int maxAppInstances = 3;
>>> +        private boolean maxAppInstancesSet;
>>> +
>>> +        private int maxRequestsPerSecond = 100;
>>> +        private boolean maxRequestsPerSecondSet;
>>> +
>>> +        private double alarmingUpperRate = 0.7;
>>> +        private boolean alarmingUpperRateSet;
>>> +
>>> +        private double alarmingLowerRate = 0.2;
>>> +        private boolean alarmingLowerRateSet;
>>> +
>>> +        private double scaleDownFactor = 0.25;
>>> +        private boolean scaleDownFactorSet;
>>> +
>>> +        private int roundsToAverage = 10;
>>> +        private boolean roundsToAverageSet;
>>> +
>>> +        private int instancesPerScaleUp = 1;
>>> +        private boolean instancesPerScaleUpSet;
>>> +
>>> +        private int messageExpiryTime = 60000; // milliseconds
>>> +        private boolean messageExpiryTimeSet;
>>> +
>>> +        private List<String> hosts = new ArrayList<String>();
>>> +        private Map<String, String> urlSuffixes = new HashMap<String,
>>> String>();
>>> +        private boolean hostsSet;
>>> +
>>> +        private String domain;
>>> +
>>> +        private String tenantRange;
>>> +        private boolean tenantRangeSet;
>>> +
>>> +        private String subDomain = Constants.DEFAULT_SUB_DOMAIN;
>>> +        private boolean subDomainSet;
>>> +
>>> +        public String getTenantRange() {
>>> +            if (tenantRangeSet) {
>>> +                return tenantRange;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.tenantRangeSet) {
>>> +                return defaultServiceConfig.tenantRange;
>>> +            }
>>> +            return tenantRange;
>>> +        }
>>> +
>>> +        public String getDomain() {
>>> +            return domain;
>>> +        }
>>> +
>>> +        public List<String> getHosts() {
>>> +            if (hostsSet) {
>>> +                return hosts;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.hostsSet) {
>>> +                return defaultServiceConfig.hosts;
>>> +            }
>>> +            return hosts;
>>> +        }
>>> +
>>> +        public int getMinAppInstances() {
>>> +            if (minAppInstancesSet) {
>>> +                return minAppInstances;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.minAppInstancesSet) {
>>> +                return defaultServiceConfig.minAppInstances;
>>> +            }
>>> +            return minAppInstances;
>>> +        }
>>> +
>>> +        public int getMaxAppInstances() {
>>> +            if (maxAppInstancesSet) {
>>> +                return maxAppInstances;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.maxAppInstancesSet) {
>>> +                return defaultServiceConfig.maxAppInstances;
>>> +            }
>>> +            return maxAppInstances;
>>> +        }
>>> +
>>> +        public int getMaxRequestsPerSecond() {
>>> +            if (maxRequestsPerSecondSet) {
>>> +                return maxRequestsPerSecond;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.maxRequestsPerSecondSet) {
>>> +                return defaultServiceConfig.maxRequestsPerSecond;
>>> +            }
>>> +            return maxRequestsPerSecond;
>>> +        }
>>> +
>>> +        public int getRoundsToAverage() {
>>> +            if (roundsToAverageSet) {
>>> +                return roundsToAverage;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.roundsToAverageSet) {
>>> +                return defaultServiceConfig.roundsToAverage;
>>> +            }
>>> +            return roundsToAverage;
>>> +        }
>>> +
>>> +        public int getInstancesPerScaleUp() {
>>> +            if (instancesPerScaleUpSet) {
>>> +                return instancesPerScaleUp;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.instancesPerScaleUpSet) {
>>> +                return defaultServiceConfig.instancesPerScaleUp;
>>> +            }
>>> +            return instancesPerScaleUp;
>>> +        }
>>> +
>>> +        public int getMessageExpiryTime() {
>>> +            if (messageExpiryTimeSet) {
>>> +                return messageExpiryTime;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.messageExpiryTimeSet) {
>>> +                return defaultServiceConfig.messageExpiryTime;
>>> +            }
>>> +            return messageExpiryTime;
>>> +        }
>>> +
>>> +        public String getSubDomain() {
>>> +            if (subDomainSet) {
>>> +                return subDomain;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.subDomainSet) {
>>> +                return defaultServiceConfig.subDomain;
>>> +            }
>>> +            return subDomain;
>>> +        }
>>> +
>>> +        public void setMin_app_instances(int minAppInstances) {
>>> +            this.minAppInstances = minAppInstances;
>>> +            this.minAppInstancesSet = true;
>>> +        }
>>> +
>>> +        public void setMax_app_instances(int maxAppInstances) {
>>> +            if (maxAppInstances < 1) {
>>> +                LoadBalancerConfigUtil.handleException("maxAppInstances
>>> in the autoscaler task configuration " +
>>> +                        "should be at least 1");
>>> +            }
>>> +            this.maxAppInstances = maxAppInstances;
>>> +            this.maxAppInstancesSet = true;
>>> +        }
>>> +
>>> +               public void setAlarming_upper_rate(double rate) {
>>> +                       if (rate > 0 && rate <= 1) {
>>> +                               this.alarmingUpperRate = rate;
>>> +                               this.alarmingUpperRateSet = true;
>>> +                       }
>>> +               }
>>> +
>>> +        public void setAlarming_lower_rate(double rate) {
>>> +                       if (rate > 0 && rate <= 1) {
>>> +                               this.alarmingLowerRate = rate;
>>> +                               this.alarmingLowerRateSet = true;
>>> +                       }
>>> +        }
>>> +
>>> +               public void setScale_down_factor(double factor) {
>>> +                       if (factor > 0 && factor <= 1) {
>>> +                               this.scaleDownFactor = factor;
>>> +                               this.scaleDownFactorSet = true;
>>> +                       }
>>> +               }
>>> +
>>> +        public void setMax_requests_per_second(int rps) {
>>> +            this.maxRequestsPerSecond = rps;
>>> +            this.maxRequestsPerSecondSet = true;
>>> +        }
>>> +
>>> +        public void setRounds_to_average(int roundsToAverage) {
>>> +            this.roundsToAverage = roundsToAverage;
>>> +            this.roundsToAverageSet = true;
>>> +        }
>>> +
>>> +        public void setInstances_per_scale_up(int instancesPerScaleUp) {
>>> +            if (instancesPerScaleUp < 1) {
>>> +
>>>  LoadBalancerConfigUtil.handleException("instancesPerScaleUp in the
>>> autoscaler task configuration " +
>>> +                        "should be at least 1");
>>> +            }
>>> +            this.instancesPerScaleUp = instancesPerScaleUp;
>>> +            this.instancesPerScaleUpSet = true;
>>> +        }
>>> +
>>> +        public void setMessage_expiry_time(int messageExpiryTime) {
>>> +            if (messageExpiryTime < 1) {
>>> +
>>>  LoadBalancerConfigUtil.handleException("messageExpiryTime in the
>>> autoscaler task configuration " +
>>> +                        "should be at least 1");
>>> +            }
>>> +            this.messageExpiryTime = messageExpiryTime;
>>> +            this.messageExpiryTimeSet = true;
>>> +        }
>>> +
>>> +        public void setHosts(String hostsStr) {
>>> +            // clear all unnecessary values --> property will get
>>> overwritten
>>> +            hosts = new ArrayList<String>();
>>> +            // there can be multiple hosts, let's find out.
>>> +            String[] host = hostsStr.split(Constants.HOSTS_DELIMITER);
>>> +
>>> +            for (String string : host) {
>>> +                if (!string.isEmpty()) {
>>> +                    this.hosts.add(string);
>>> +                }
>>> +            }
>>> +
>>> +        }
>>> +
>>> +        public void setUrl_suffix(String suffix) {
>>> +            // clear all unnecessary values --> property will get
>>> overwritten
>>> +            //hosts = new ArrayList<String>();
>>> +            // there can be multiple hosts, let's find out.
>>> +            String[] suffixes = suffix.split(Constants.HOSTS_DELIMITER);
>>> +            int count = 0;
>>> +            if(suffixes.length == this.hosts.size()) {
>>> +                for (String string : suffixes) {
>>> +                    if (!string.isEmpty()) {
>>> +                        this.urlSuffixes.put(this.hosts.get(count),
>>> string);
>>> +                        count++;
>>> +                    }
>>> +                }
>>> +
>>> +            } else {
>>> +                //Error
>>> +            }
>>> +        }
>>> +
>>> +        public Map<String, String> getUrl_suffix() {
>>> +            return this.urlSuffixes;
>>> +        }
>>> +
>>> +        public void setTenant_range(String range) {
>>> +            this.tenantRange = range;
>>> +        }
>>> +
>>> +        public void setSub_domain(String subDomain) {
>>> +            this.subDomain = subDomain;
>>> +            this.subDomainSet = true;
>>> +        }
>>> +
>>> +        public void setDomain(String domain) {
>>> +            this.domain = domain;
>>> +        }
>>> +
>>> +        public boolean equals(ServiceConfiguration config) {
>>> +            return this.domain.equals(config.getDomain()) &&
>>> +                    this.subDomain.equals(config.getSubDomain());
>>> +        }
>>> +
>>> +        public int hashCode() {
>>> +            return new HashCodeBuilder(17, 31). // two randomly chosen
>>> prime numbers
>>> +                    append(domain).
>>> +                    append(subDomain).
>>> +                    toHashCode();
>>> +        }
>>> +
>>> +        public double getAlarmingUpperRate() {
>>> +            if (alarmingUpperRateSet) {
>>> +                return alarmingUpperRate;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.alarmingUpperRateSet) {
>>> +                return defaultServiceConfig.alarmingUpperRate;
>>> +            }
>>> +            return alarmingUpperRate;
>>> +        }
>>> +
>>> +        public double getAlarmingLowerRate() {
>>> +            if (alarmingLowerRateSet) {
>>> +                return alarmingLowerRate;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.alarmingLowerRateSet) {
>>> +                return defaultServiceConfig.alarmingLowerRate;
>>> +            }
>>> +            return alarmingLowerRate;
>>> +        }
>>> +
>>> +        public double getScaleDownFactor() {
>>> +            if (scaleDownFactorSet) {
>>> +                return scaleDownFactor;
>>> +            } else if (defaultServiceConfig != null &&
>>> defaultServiceConfig.scaleDownFactorSet) {
>>> +                return defaultServiceConfig.scaleDownFactor;
>>> +            }
>>> +            return scaleDownFactor;
>>> +        }
>>> +    }
>>> +
>>> +    public Map<String, Set<String>> getHostNamesTracker() {
>>> +        return hostNamesTracker;
>>> +    }
>>> +
>>> +
>>> +    public Map<String, Map<String, ServiceConfiguration>>
>>> getServiceConfigurations() {
>>> +        return serviceConfigurations;
>>> +    }
>>> +
>>> +
>>> +    public Node getRootNode() {
>>> +        return rootNode;
>>> +    }
>>> +
>>> +
>>> +    public void setRootNode(Node rootNode) {
>>> +        this.rootNode = rootNode;
>>> +    }
>>> +
>>> +    public static void setInstance(LoadBalancerConfiguration instance) {
>>> +        LoadBalancerConfiguration.instance = instance;
>>> +    }
>>> +
>>> +       public Map<String, List<ServiceConfiguration>>
>>> getServiceNameToServiceConfigurations() {
>>> +       return serviceNameToServiceConfigurations;
>>> +    }
>>> +
>>> +}
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
>>> new file mode 100755
>>> index 0000000..c4820a7
>>> --- /dev/null
>>> +++
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
>>> @@ -0,0 +1,356 @@
>>> +/**
>>> + *  Licensed to the Apache Software Foundation (ASF) under one
>>> + *  or more contributor license agreements.  See the NOTICE file
>>> + *  distributed with this work for additional information
>>> + *  regarding copyright ownership.  The ASF 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
>>> +
>>> + *  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 org.apache.stratos.load.balancer.conf.structure;
>>> +
>>> +import java.io.Serializable;
>>> +import java.util.ArrayList;
>>> +import java.util.Iterator;
>>> +import java.util.LinkedHashMap;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +import java.util.Map.Entry;
>>> +
>>> +import org.apache.commons.lang.builder.HashCodeBuilder;
>>> +
>>> +/**
>>> + * This is the basic data structure which holds a <i>Nginx</i>
>>> formatted configuration file.
>>> + *
>>> + */
>>> +public class Node implements Serializable{
>>> +
>>> +    private static final long serialVersionUID = 4071569903421115370L;
>>> +
>>> +    /**
>>> +     * Name of this Node element
>>> +     */
>>> +    private String name;
>>> +
>>> +    /**
>>> +     * Every node can have 0..n child nodes.
>>> +     * They are kept in a List.
>>> +     */
>>> +    private List<Node> childNodes = new ArrayList<Node>();
>>> +
>>> +    /**
>>> +     * Every node can have 0..n properties.
>>> +     * They are kept in a Map, in the order they appear.
>>> +     * Key: property name
>>> +     * Value: property value
>>> +     */
>>> +    private Map<String, String> properties = new LinkedHashMap<String,
>>> String>();
>>> +
>>> +    public void setChildNodes(List<Node> childNodes) {
>>> +        this.childNodes = childNodes;
>>> +    }
>>> +
>>> +    public void setProperties(Map<String, String> properties) {
>>> +        this.properties = properties;
>>> +    }
>>> +
>>> +    /**
>>> +     * This will convert each child Node of this Node to a String.
>>> +     * @return a string which represents child nodes of this node.
>>> +     */
>>> +    public String childNodesToString(int indentation) {
>>> +        StringBuilder childNodesString = new StringBuilder();
>>> +        indentation++;
>>> +
>>> +        for (Node node : childNodes) {
>>> +            childNodesString.append(node.toString(indentation)+"\n");
>>> +        }
>>> +
>>> +        return childNodesString.toString();
>>> +    }
>>> +
>>> +    /**
>>> +     * This will try to find a child Node of this Node, which has the
>>> given name.
>>> +     * @param name name of the child node to find.
>>> +     * @return child Node object if found or else <code>null</code>.
>>> +     */
>>> +    public Node findChildNodeByName(String name) {
>>> +        for (Node aNode : childNodes) {
>>> +            if (aNode.getName().equals(name)) {
>>> +                return aNode;
>>> +            }
>>> +        }
>>> +
>>> +        return null;
>>> +    }
>>> +
>>> +    /**
>>> +     * Returns the name of this Node.
>>> +     * @return name of the node.
>>> +     */
>>> +    public String getName() {
>>> +        return name;
>>> +    }
>>> +
>>> +    /**
>>> +     * Returns child nodes List of this Node.
>>> +     * @return List of Node
>>> +     */
>>> +    public List<Node> getChildNodes() {
>>> +        return childNodes;
>>> +    }
>>> +
>>> +    /**
>>> +     * Returns properties Map of this Node.
>>> +     * @return Map whose keys and values are String.
>>> +     */
>>> +    public Map<String, String> getProperties() {
>>> +        return properties;
>>> +    }
>>> +
>>> +    /**
>>> +     * Returns the value of a given property.
>>> +     * @param key name of a property.
>>> +     * @return trimmed value if the property is found in this Node, or
>>> else <code>null</code>.
>>> +     */
>>> +    public String getProperty(String key) {
>>> +        if (properties.get(key) == null) {
>>> +            return null;
>>> +        }
>>> +        return properties.get(key).trim();
>>> +    }
>>> +
>>> +    /**
>>> +     * Returns all the properties of this Node as a String.
>>> +     * Key and value of the property is separated by a tab (\t)
>>> character and
>>> +     * each property is separated by a new line character.
>>> +     * @param indentation relative number of tabs
>>> +     * @return properties of this node as a String.
>>> +     */
>>> +    public String propertiesToString(int indentation) {
>>> +
>>> +        String indent = getIndentation(indentation);
>>> +
>>> +        StringBuilder sb = new StringBuilder();
>>> +        for (Entry<String, String> entry : properties.entrySet()) {
>>> +            // hack to get a quick fix in.
>>> +            if (!"tenant_id".equals(entry.getKey()) &&
>>> !"alias".equals(entry.getKey())) {
>>> +                sb.append(indent + entry.getKey() + "\t" +
>>> entry.getValue() + ";\n");
>>> +            }
>>> +        }
>>> +        return sb.toString();
>>> +    }
>>> +
>>> +    /**
>>> +     * Removes the first occurrence of a node having the given name
>>> +     * and returns the removed {@link
>>> org.apache.stratos.load.balancer.conf.structure.Node}.
>>> +     * @param name name of the child node to be removed.
>>> +     * @return removed {@link
>>> org.apache.stratos.load.balancer.conf.structure.Node} or else
>>> <code>null</code>.
>>> +     */
>>> +    public Node removeChildNode(String name) {
>>> +        Node aNode = findChildNodeByName(name);
>>> +
>>> +        if(aNode != null){
>>> +            if(childNodes.remove(aNode)){
>>> +                return aNode;
>>> +            }
>>> +        }
>>> +
>>> +        return null;
>>> +    }
>>> +
>>> +    /**
>>> +     * Removes the first occurrence of a node equals to the given node.
>>> +     * @param node {@link
>>> org.apache.stratos.load.balancer.conf.structure.Node} to be removed.
>>> +     * @return whether the removal is successful or not.
>>> +     */
>>> +    public boolean removeChildNode(Node node){
>>> +
>>> +        return childNodes.remove(node);
>>> +    }
>>> +
>>> +    /**
>>> +     * Sets the name of this Node.
>>> +     * @param name String to be set as the name.
>>> +     */
>>> +    public void setName(String name) {
>>> +        this.name = name;
>>> +    }
>>> +
>>> +    /**
>>> +     * Appends a child node at the end of the List of child nodes of
>>> this Node, if
>>> +     * a similar node is not already present as a child node.
>>> +     * @param aNode child Node to be appended.
>>> +     */
>>> +    public void appendChild(Node aNode) {
>>> +        if (aNode != null && !nodeAlreadyPresent(aNode)) {
>>> +            childNodes.add(aNode);
>>> +        }
>>> +    }
>>> +
>>> +    /**
>>> +     * Adds a new property to properties Map of this Node if and only if
>>> +     * key is not <code>null</code>.
>>> +     * @param key name of the property to be added.
>>> +     * @param value value of the property to be added.
>>> +     */
>>> +    public void addProperty(String key, String value) {
>>> +        if (key != null) {
>>> +            properties.put(key, value);
>>> +        }
>>> +    }
>>> +
>>> +    /**
>>> +     * Convert this Node to a String which is in <i>Nginx</i> format.
>>> +     * <br/>
>>> +     * Sample:
>>> +     * <br></br>
>>> +     * <code>
>>> +     * ij {
>>> +     * <br/>
>>> +     * klm n;
>>> +     * <br/>
>>> +     * pq {
>>> +     * <br/>
>>> +     * rst u;
>>> +     * <br/>
>>> +     * }
>>> +     * <br/>
>>> +     * }
>>> +     * <br/>
>>> +     * </code>
>>> +     */
>>> +    public String toString() {
>>> +
>>> +        String nodeString =
>>> +                getName()+" {\n" +
>>> +                (propertiesToString(1)) +
>>> +                (childNodesToString(1)) +
>>> +                "}";
>>> +
>>> +        return nodeString;
>>> +    }
>>> +
>>> +    public boolean equals(Object node) {
>>> +
>>> +        if(node instanceof Node){
>>> +            return this.getName().equals(((Node) node).getName()) &&
>>> +                    isIdenticalProperties(this.getProperties(), ((Node)
>>> node).getProperties()) &&
>>> +                    isIdenticalChildren(this.getChildNodes(), ((Node)
>>> node).getChildNodes());
>>> +        }
>>> +
>>> +        return false;
>>> +
>>> +    }
>>> +
>>> +    public int hashCode() {
>>> +        return new HashCodeBuilder(17, 31). // two randomly chosen
>>> prime numbers
>>> +            append(name).
>>> +            append(properties).
>>> +            append(childNodes).
>>> +            toHashCode();
>>> +    }
>>> +
>>> +    private boolean isIdenticalChildren(List<Node> childNodes1,
>>> List<Node> childNodes2) {
>>> +
>>> +        if(childNodes1.size() != childNodes2.size()){
>>> +            return false;
>>> +        }
>>> +
>>> +        for (Node node1 : childNodes1) {
>>> +            int i=0;
>>> +            for (Node node2 : childNodes2) {
>>> +
>>> +                i++;
>>> +                if(node1.equals(node2)){
>>> +                    break;
>>> +                }
>>> +
>>> +                if(i == childNodes1.size()){
>>> +                    return false;
>>> +                }
>>> +
>>> +            }
>>> +        }
>>> +
>>> +        return true;
>>> +    }
>>> +
>>> +    private boolean nodeAlreadyPresent(Node aNode){
>>> +
>>> +        for(Node node : this.childNodes){
>>> +            if(node.equals(aNode)){
>>> +                return true;
>>> +            }
>>> +        }
>>> +
>>> +        return false;
>>> +    }
>>> +
>>> +    private boolean isIdenticalProperties(Map<String, String> map1,
>>> +        Map<String, String> map2) {
>>> +
>>> +        if(map1.size() != map2.size()){
>>> +            return false;
>>> +        }
>>> +
>>> +        for (Iterator<Entry<String, String>> iterator1 =
>>> map1.entrySet().iterator(); iterator1.hasNext();) {
>>> +            Entry<String, String> entry1 = (Entry<String, String>)
>>> iterator1.next();
>>> +
>>> +            int i=0;
>>> +
>>> +            for(Iterator<Entry<String, String>> iterator2 =
>>> map2.entrySet().iterator(); iterator2.hasNext();) {
>>> +                Entry<String, String> entry2 = (Entry<String, String>)
>>> iterator2.next();
>>> +
>>> +                i++;
>>> +
>>> +                if((entry1.getKey().equals(entry2.getKey()) &&
>>> +                        entry1.getValue().equals(entry2.getValue()))){
>>> +
>>> +                    break;
>>> +                }
>>> +
>>> +                if(i == map1.size()){
>>> +                    return false;
>>> +                }
>>> +
>>> +            }
>>> +        }
>>> +
>>> +        return true;
>>> +    }
>>> +
>>> +    private String toString(int indentation){
>>> +
>>> +        String indent = getIndentation(indentation-1);
>>> +
>>> +        String nodeString =
>>> +                indent + getName()+" {\n" +
>>> +                (propertiesToString(indentation)) +
>>> +                (childNodesToString(indentation)) +
>>> +                indent + "}";
>>> +
>>> +        return nodeString;
>>> +    }
>>> +
>>> +    private String getIndentation(int tabs){
>>> +
>>> +        StringBuilder indent = new StringBuilder("");
>>> +
>>> +        for (int i = 0; i < tabs; i++) {
>>> +            indent.append("\t");
>>> +        }
>>> +
>>> +        return indent.toString();
>>> +    }
>>> +
>>> +}
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
>>> new file mode 100755
>>> index 0000000..168492d
>>> --- /dev/null
>>> +++
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
>>> @@ -0,0 +1,140 @@
>>> +/**
>>> + *  Licensed to the Apache Software Foundation (ASF) under one
>>> + *  or more contributor license agreements.  See the NOTICE file
>>> + *  distributed with this work for additional information
>>> + *  regarding copyright ownership.  The ASF 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
>>> +
>>> + *  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 org.apache.stratos.load.balancer.conf.structure;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.stratos.load.balancer.conf.util.Constants;
>>> +
>>> +/**
>>> + * This responsible for build up a Node object from a given content.
>>> + * Every closing brace should be in a new line.
>>> + */
>>> +public class NodeBuilder {
>>> +
>>> +    private static final Log log = LogFactory.getLog(NodeBuilder.class);
>>> +
>>> +    /**
>>> +     * This method is useful when you do not have a root node in your
>>> content.
>>> +     * @param aNode
>>> +     *            Node object whose name set.
>>> +     * @param content
>>> +     *            should be something similar to following.
>>> +     *
>>> +     *            abc d;
>>> +     *            efg h;
>>> +     *            # comment
>>> +     *            ij { # comment
>>> +     *              klm n;
>>> +     *
>>> +     *              pq {
>>> +     *                  rst u;
>>> +     *              }
>>> +     *            }
>>> +     *
>>> +     * @return fully constructed Node
>>> +     */
>>> +    public static Node buildNode(Node aNode, String content) {
>>> +
>>> +       if(content == null || content.isEmpty()){
>>> +               return aNode;
>>> +       }
>>> +
>>> +        String[] lines = content.split("\n");
>>> +
>>> +        for (int i = 0; i < lines.length; i++) {
>>> +            String line = lines[i].trim();
>>> +
>>> +            // avoid line comments
>>> +            if (!line.startsWith(Constants.NGINX_COMMENT)) {
>>> +
>>> +                // skip comments in-line
>>> +                if(line.contains(Constants.NGINX_COMMENT)){
>>> +                    line = line.substring(0,
>>> line.indexOf(Constants.NGINX_COMMENT));
>>> +                }
>>> +
>>> +                // another node is detected and it is not a variable
>>> starting from $
>>> +                if (line.contains(Constants.NGINX_NODE_START_BRACE) &&
>>> +                        !line.contains(Constants.NGINX_VARIABLE)) {
>>> +
>>> +                    try {
>>> +                        Node childNode = new Node();
>>> +                        childNode.setName(line.substring(0,
>>> line.indexOf(Constants.NGINX_NODE_START_BRACE)).trim());
>>> +
>>> +                        StringBuilder sb = new StringBuilder();
>>> +
>>> +                        int matchingBraceTracker = 1;
>>> +
>>> +                        while
>>> (!line.contains(Constants.NGINX_NODE_END_BRACE) || matchingBraceTracker !=
>>> 0) {
>>> +                            i++;
>>> +                            if (i == lines.length) {
>>> +                                break;
>>> +                            }
>>> +                            line = lines[i];
>>> +                            if
>>> (line.contains(Constants.NGINX_NODE_START_BRACE)) {
>>> +                                matchingBraceTracker++;
>>> +                            }
>>> +                            if
>>> (line.contains(Constants.NGINX_NODE_END_BRACE)) {
>>> +                                matchingBraceTracker--;
>>> +                            }
>>> +                            sb.append(line + "\n");
>>> +                        }
>>> +
>>> +                        childNode = buildNode(childNode, sb.toString());
>>> +                                               if (aNode == null) {
>>> +                                                       aNode =
>>> childNode;
>>> +                                               } else {
>>> +
>>> aNode.appendChild(childNode);
>>> +                                               }
>>> +
>>> +                    } catch (Exception e) {
>>> +                        String msg = "Malformatted element is defined
>>> in the configuration file. [" +
>>> +                                i + "] \n";
>>> +                        log.error(msg , e);
>>> +                        throw new RuntimeException(msg + line, e);
>>> +                    }
>>> +
>>> +                }
>>> +                // this is a property
>>> +                else {
>>> +                    if (!line.isEmpty() &&
>>> !Constants.NGINX_NODE_END_BRACE.equals(line)) {
>>> +                        String[] prop =
>>> line.split(Constants.NGINX_SPACE_REGEX);
>>> +                        String value = line.substring(prop[0].length(),
>>> line.indexOf(Constants.NGINX_LINE_DELIMITER)).trim();
>>> +                        try {
>>> +                            aNode.addProperty(prop[0], value);
>>> +                        } catch (Exception e) {
>>> +                            String msg = "Malformatted property is
>>> defined in the configuration file. [" +
>>> +                                    i + "] \n";
>>> +                            log.error(msg, e);
>>> +                            throw new RuntimeException(msg + line, e);
>>> +                        }
>>> +                    }
>>> +                }
>>> +
>>> +            }
>>> +        }
>>> +
>>> +        return aNode;
>>> +
>>> +    }
>>> +
>>> +    public static Node buildNode(String content) {
>>> +           return buildNode(null, content);
>>> +    }
>>> +}
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
>>> new file mode 100755
>>> index 0000000..31e172d
>>> --- /dev/null
>>> +++
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
>>> @@ -0,0 +1,50 @@
>>> +/**
>>> + *  Licensed to the Apache Software Foundation (ASF) under one
>>> + *  or more contributor license agreements.  See the NOTICE file
>>> + *  distributed with this work for additional information
>>> + *  regarding copyright ownership.  The ASF 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
>>> +
>>> + *  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 org.apache.stratos.load.balancer.conf.util;
>>> +
>>> +/**
>>> + * This keeps the element names used in loadbalancer.conf file
>>> + */
>>> +public class Constants {
>>> +
>>> +    public static final String LOAD_BALANCER_ELEMENT = "loadbalancer";
>>> +    public static final String SERVICES_ELEMENT = "services";
>>> +    public static final String DEFAULTS_ELEMENT = "defaults";
>>> +    public static final String HOSTS_ELEMENT = "hosts";
>>> +    public static final String HOSTS_DELIMITER = ",";
>>> +    public static final String DOMAIN_ELEMENT = "domains";
>>> +    public static final String TENANT_RANGE_ELEMENT = "tenant_range";
>>> +    public static final String SUB_DOMAIN_ELEMENT = "sub_domain";
>>> +    public static final String TENANT_RANGE_DELIMITER = "-";
>>> +    public static final String UNLIMITED_TENANT_RANGE = "*";
>>> +    public static final String AUTOSCALER_ENABLE_ELEMENT =
>>> "enable_autoscaler";
>>> +    public static final String SUB_DOMAIN_DELIMITER = "#";
>>> +    public static final String DEFAULT_SUB_DOMAIN = "__$default";
>>> +
>>> +    /* Nginx format related constants */
>>> +
>>> +    public static final String NGINX_COMMENT = "#";
>>> +    public static final String NGINX_NODE_START_BRACE = "{";
>>> +    public static final String NGINX_NODE_END_BRACE = "}";
>>> +    public static final String NGINX_VARIABLE = "${";
>>> +    public static final String NGINX_LINE_DELIMITER = ";";
>>> +    public static final String NGINX_SPACE_REGEX = "[\\s]+";
>>> +
>>> +
>>> +}
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
>>> new file mode 100755
>>> index 0000000..ecd952a
>>> --- /dev/null
>>> +++
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
>>> @@ -0,0 +1,161 @@
>>> +/**
>>> + *  Licensed to the Apache Software Foundation (ASF) under one
>>> + *  or more contributor license agreements.  See the NOTICE file
>>> + *  distributed with this work for additional information
>>> + *  regarding copyright ownership.  The ASF 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
>>> +
>>> + *  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 org.apache.stratos.load.balancer.conf.util;
>>> +
>>> +import java.util.Collection;
>>> +import java.util.HashMap;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import org.apache.synapse.endpoints.algorithms.AlgorithmContext;
>>> +import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
>>> +
>>> +/**
>>> + * For each unique host name defined in loadbalancer configuration,
>>> we'll generate
>>> + * this object.
>>> + */
>>> +public class HostContext {
>>> +
>>> +    /**
>>> +     * A unique identifier to identify this {@link #HostContext()}
>>> +     */
>>> +    private String hostName;
>>> +
>>> +    /**
>>> +     * Key - tenant id
>>> +     * Value - <code>TenantDomainContext</code> of the corresponding
>>> tenant
>>> +     */
>>> +    private Map<Integer, TenantDomainContext>
>>> tenantIdToTenantDomainContextMap = new HashMap<Integer,
>>> TenantDomainContext>();
>>> +
>>> +    /**
>>> +     * AlgorithmContext of this host
>>> +     */
>>> +    private AlgorithmContext algorithmContext;
>>> +
>>> +    /**
>>> +     * Load balance algorithm of this host
>>> +     */
>>> +    private LoadbalanceAlgorithm algorithm;
>>> +
>>> +    private String urlSuffix;
>>> +
>>> +    public HostContext(String hostName) {
>>> +        this.hostName = hostName;
>>> +    }
>>> +
>>> +    public void addTenantDomainContexts(List<TenantDomainContext>
>>> ctxts) {
>>> +
>>> +        for (TenantDomainContext tenantDomainContext : ctxts) {
>>> +
>>>  tenantIdToTenantDomainContextMap.put(tenantDomainContext.getTenantId(),
>>> tenantDomainContext);
>>> +        }
>>> +    }
>>> +
>>> +    @Deprecated
>>> +    public void addTenantDomainContext(TenantDomainContext ctxt) {
>>> +        tenantIdToTenantDomainContextMap.put(ctxt.getTenantId(), ctxt);
>>> +    }
>>> +
>>> +    public TenantDomainContext getTenantDomainContext(int tenantId) {
>>> +        return tenantIdToTenantDomainContextMap.get(tenantId);
>>> +    }
>>> +
>>> +    /**
>>> +     * Returns all the {@link
>>> org.apache.stratos.load.balancer.conf.util.TenantDomainContext} entries.
>>> +     */
>>> +    public Collection<TenantDomainContext> getTenantDomainContexts() {
>>> +        return tenantIdToTenantDomainContextMap.values();
>>> +    }
>>> +
>>> +    /**
>>> +     * Given a tenant id, this will return its domain.
>>> +     * @param tenantId
>>> +     * @return domain if this tenant has a dedicated one, it will be
>>> returned.
>>> +     * If not, and there's a default (*) domain, it will be returned.
>>> +     * If neither of the above is defined, null will be returned.
>>> +     */
>>> +    public String getDomainFromTenantId(int tenantId) {
>>> +        if (tenantIdToTenantDomainContextMap.get(tenantId) == null) {
>>> +            // if there's no specific domain for this tenant, we will
>>> redirect it to the default
>>> +            // cluster
>>> +
>>> +            if(tenantIdToTenantDomainContextMap.get(0) == null){
>>> +                return null;
>>> +            }
>>> +
>>> +            return tenantIdToTenantDomainContextMap.get(0).getDomain();
>>> +        }
>>> +
>>> +        return
>>> tenantIdToTenantDomainContextMap.get(tenantId).getDomain();
>>> +    }
>>> +
>>> +    /**
>>> +     * Given a tenant id, this will return its sub domain.
>>> +     * @param tenantId
>>> +     * @return sub_domain if this tenant has a dedicated one, it will
>>> be returned.
>>> +     * If not, and there's a default (*) sub domain, it will be
>>> returned.
>>> +     * If neither of the above is defined, null will be returned.
>>> +     */
>>> +    public String getSubDomainFromTenantId(int tenantId) {
>>> +        if (tenantIdToTenantDomainContextMap.get(tenantId) == null) {
>>> +            // if there's no specific domain for this tenant, we will
>>> redirect it to the default
>>> +            // cluster
>>> +
>>> +            if(tenantIdToTenantDomainContextMap.get(0) == null){
>>> +                return null;
>>> +            }
>>> +
>>> +            return
>>> tenantIdToTenantDomainContextMap.get(0).getSubDomain();
>>> +        }
>>> +
>>> +        return
>>> tenantIdToTenantDomainContextMap.get(tenantId).getSubDomain();
>>> +    }
>>> +
>>> +    public String getHostName() {
>>> +        return hostName;
>>> +    }
>>> +
>>> +    public LoadbalanceAlgorithm getAlgorithm() {
>>> +        return algorithm;
>>> +    }
>>> +
>>> +    public AlgorithmContext getAlgorithmContext() {
>>> +        return algorithmContext;
>>> +    }
>>> +
>>> +    public void setAlgorithmContext(AlgorithmContext algorithmContext) {
>>> +        this.algorithmContext = algorithmContext;
>>> +    }
>>> +
>>> +    public void setAlgorithm(LoadbalanceAlgorithm algorithm) {
>>> +        this.algorithm = algorithm;
>>> +    }
>>> +
>>> +    public Map<Integer, TenantDomainContext>
>>> getTenantIdToTenantDomainContextMap() {
>>> +        return tenantIdToTenantDomainContextMap;
>>> +    }
>>> +
>>> +    public void setUrlSuffix(String suffix)  {
>>> +        this.urlSuffix = suffix;
>>> +    }
>>> +
>>> +    public String getUrlSuffix() {
>>> +        return this.urlSuffix;
>>> +    }
>>> +
>>> +}
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
>>> new file mode 100755
>>> index 0000000..fe432c9
>>> --- /dev/null
>>> +++
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
>>> @@ -0,0 +1,305 @@
>>> +/**
>>> + *  Licensed to the Apache Software Foundation (ASF) under one
>>> + *  or more contributor license agreements.  See the NOTICE file
>>> + *  distributed with this work for additional information
>>> + *  regarding copyright ownership.  The ASF 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
>>> +
>>> + *  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 org.apache.stratos.load.balancer.conf.util;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.synapse.SynapseException;
>>> +import sun.misc.BASE64Encoder;
>>> +
>>> +import java.io.File;
>>> +import java.io.FileInputStream;
>>> +import java.io.IOException;
>>> +import java.io.InputStream;
>>> +import java.util.ArrayList;
>>> +import java.util.List;
>>> +
>>> +/**
>>> + * Utility methods for Autoscale mediator
>>> + */
>>> +public final class LoadBalancerConfigUtil {
>>> +
>>> +    private static final Log log =
>>> LogFactory.getLog(LoadBalancerConfigUtil.class);
>>> +
>>> +    private LoadBalancerConfigUtil() {
>>> +    }
>>> +
>>> +    /**
>>> +     * handles the exception
>>> +     *
>>> +     * @param msg
>>> +     *            exception message
>>> +     */
>>> +    public static void handleException(String msg) {
>>> +        log.error(msg);
>>> +        throw new RuntimeException(msg);
>>> +    }
>>> +
>>> +    /**
>>> +     * handles the exception
>>> +     *
>>> +     * @param msg
>>> +     *            exception message
>>> +     * @param e
>>> +     *            exception
>>> +     */
>>> +    public static void handleException(String msg, Exception e) {
>>> +        log.error(msg, e);
>>> +        throw new SynapseException(msg, e);
>>> +    }
>>> +
>>> +    /**
>>> +     * Replaces the variables
>>> +     *
>>> +     * @param text
>>> +     *            input string
>>> +     * @return output String
>>> +     */
>>> +    public static String replaceVariables(String text) {
>>> +        int indexOfStartingChars;
>>> +        int indexOfClosingBrace;
>>> +
>>> +        // The following condition deals with properties.
>>> +        // Properties are specified as ${system.property},
>>> +        // and are assumed to be System properties
>>> +        if ((indexOfStartingChars = text.indexOf("${")) != -1 &&
>>> +            (indexOfClosingBrace = text.indexOf("}")) != -1) { // Is a
>>> property used?
>>> +            String var = text.substring(indexOfStartingChars + 2,
>>> indexOfClosingBrace);
>>> +
>>> +            String propValue = System.getProperty(var);
>>> +            if (propValue == null) {
>>> +                propValue = System.getenv(var);
>>> +            }
>>> +            if (propValue != null) {
>>> +                text =
>>> +                       text.substring(0, indexOfStartingChars) +
>>> propValue +
>>> +                               text.substring(indexOfClosingBrace + 1);
>>> +            }
>>> +        }
>>> +        return text;
>>> +    }
>>> +
>>> +    public static String getUserData(String payloadFileName) {
>>> +        String userData = null;
>>> +        try {
>>> +            File file = new File(payloadFileName);
>>> +            if (!file.exists()) {
>>> +                handleException("Payload file " + payloadFileName + "
>>> does not exist");
>>> +            }
>>> +            if (!file.canRead()) {
>>> +                handleException("Payload file " + payloadFileName + "
>>> does cannot be read");
>>> +            }
>>> +            byte[] bytes =
>>> LoadBalancerConfigUtil.getBytesFromFile(file);
>>> +            if (bytes != null) {
>>> +                BASE64Encoder encoder = new BASE64Encoder();
>>> +                userData = encoder.encode(bytes);
>>> +            }
>>> +        } catch (Exception e) {
>>> +            LoadBalancerConfigUtil.handleException("Cannot read data
>>> from payload file " +
>>> +                                                   payloadFileName, e);
>>> +
>>> +        }
>>> +        return userData;
>>> +    }
>>> +
>>> +    /**
>>> +     * Returns the contents of the file in a byte array
>>> +     *
>>> +     * @param file
>>> +     *            - Input File
>>> +     * @return Bytes from the file
>>> +     * @throws java.io.IOException
>>> +     *             , if retrieving the file contents failed.
>>> +     */
>>> +    public static byte[] getBytesFromFile(File file) throws IOException
>>> {
>>> +        if (!file.exists()) {
>>> +            log.error("Payload file " + file.getAbsolutePath() + " does
>>> not exist");
>>> +            return null;
>>> +        }
>>> +        InputStream is = new FileInputStream(file);
>>> +        byte[] bytes;
>>> +
>>> +        try {
>>> +            // Get the size of the file
>>> +            long length = file.length();
>>> +
>>> +            // You cannot create an array using a long type.
>>> +            // It needs to be an int type.
>>> +            // Before converting to an int type, check
>>> +            // to ensure that file is not larger than Integer.MAX_VALUE.
>>> +            if (length > Integer.MAX_VALUE) {
>>> +                if (log.isDebugEnabled()) {
>>> +                    log.debug("File is too large");
>>> +                }
>>> +            }
>>> +
>>> +            // Create the byte array to hold the data
>>> +            bytes = new byte[(int) length];
>>> +
>>> +            // Read in the bytes
>>> +            int offset = 0;
>>> +            int numRead;
>>> +            while (offset < bytes.length &&
>>> +                   (numRead = is.read(bytes, offset, bytes.length -
>>> offset)) >= 0) {
>>> +                offset += numRead;
>>> +            }
>>> +
>>> +            // Ensure all the bytes have been read in
>>> +            if (offset < bytes.length) {
>>> +                throw new IOException("Could not completely read file "
>>> + file.getName());
>>> +            }
>>> +        } finally {
>>> +            // Close the input stream and return bytes
>>> +            is.close();
>>> +        }
>>> +
>>> +        return bytes;
>>> +    }
>>> +
>>> +    /**
>>> +     * @deprecated
>>> +     *             Extract the domain part given a string which is in
>>> +     *             &lt;sub_domain&gt;#&lt;domain&gt; format.
>>> +     * @param str
>>> +     *            in &lt;sub_domain&gt;#&lt;domain&gt; format.
>>> +     * @return the domain part. If # is not present this will return
>>> the trimmed
>>> +     *         input string.
>>> +     */
>>> +    public static String getDomain(String str) {
>>> +        str = str.trim();
>>> +        if (!str.contains(Constants.SUB_DOMAIN_DELIMITER)) {
>>> +            return str;
>>> +        }
>>> +        return
>>> str.substring(str.indexOf(Constants.SUB_DOMAIN_DELIMITER) + 1);
>>> +    }
>>> +
>>> +    /**
>>> +     * @deprecated
>>> +     *             Extract the sub_domain part given a string which is
>>> in
>>> +     *             &lt;sub_domain&gt;#&lt;domain&gt; format.
>>> +     * @param str
>>> +     *            in &lt;sub_domain&gt;#&lt;domain&gt; format.
>>> +     * @return the sub_domain part. If # is not present this will
>>> return <code>null</code>.
>>> +     */
>>> +    public static String getSubDomain(String str) {
>>> +        str = str.trim();
>>> +        if (!str.contains(Constants.SUB_DOMAIN_DELIMITER)) {
>>> +            return null;
>>> +        }
>>> +        return str.substring(0,
>>> str.indexOf(Constants.SUB_DOMAIN_DELIMITER));
>>> +    }
>>> +
>>> +    // public static EC2InstanceManager createEC2InstanceManager(String
>>> accessKey,
>>> +    // String secretKey,
>>> +    // String instanceMgtEPR) {
>>> +    // AWSCredentials awsCredentials = new
>>> BasicAWSCredentials(accessKey, secretKey);
>>> +    // AmazonEC2Client ec2Client = new AmazonEC2Client(awsCredentials);
>>> +    // ec2Client.setEndpoint(instanceMgtEPR);
>>> +    // return new EC2InstanceManager(ec2Client);
>>> +    // }
>>> +
>>> +    public static List<TenantDomainContext>
>>> getTenantDomainContexts(String tenantRange, String domain, String
>>> subDomain) {
>>> +
>>> +        List<TenantDomainContext> ctxts = new
>>> ArrayList<TenantDomainContext>();
>>> +        List<Integer> tenantIds = getTenantIds(tenantRange);
>>> +
>>> +        // iterate through all tenant ids under this host
>>> +        for (Integer tId : tenantIds) {
>>> +
>>> +            // create a new TenantDomainContext
>>> +            TenantDomainContext tenantCtxt =
>>> +                                             new TenantDomainContext(
>>> +
>>> tId,
>>> +
>>> domain,
>>> +
>>> subDomain);
>>> +            // add it to the list
>>> +            ctxts.add(tenantCtxt);
>>> +        }
>>> +
>>> +        return ctxts;
>>> +
>>> +    }
>>> +
>>> +    /**
>>> +     * This method will read the tenant range string and return a list
>>> of tenant ids
>>> +     * which is derived from tenant range string.
>>> +     *
>>> +     * @param tenantRange
>>> +     * @return list of tenant ids.
>>> +     */
>>> +    public static List<Integer> getTenantIds(String tenantRange) {
>>> +
>>> +        List<Integer> tenantIds = new ArrayList<Integer>();
>>> +
>>> +        String[] parsedLine = tenantRange.trim().split("-");
>>> +
>>> +        if (parsedLine[0].equalsIgnoreCase("*")) {
>>> +            tenantIds.add(0);
>>> +
>>> +               } else if (parsedLine.length == 1) {
>>> +                       // if there aren't any hyphens in the string,
>>> try to see whether
>>> +                       // this is a list of ids
>>> +                       parsedLine = tenantRange.trim().split(",");
>>> +
>>> +                       // if there aren't any commas in the string, we
>>> assume this to be a
>>> +                       // one single integer.
>>> +                       if (parsedLine.length == 1) {
>>> +                               try {
>>> +                                       int tenantId =
>>> Integer.parseInt(tenantRange);
>>> +                                       tenantIds.add(tenantId);
>>> +
>>> +                               } catch (NumberFormatException e) {
>>> +                                       String msg = "Invalid tenant
>>> range is specified : "
>>> +                                                       + tenantRange;
>>> +                                       log.error(msg, e);
>>> +                                       throw new RuntimeException(msg,
>>> e);
>>> +                               }
>>> +                       } else {
>>> +                               for (int i = 0; i < parsedLine.length;
>>> i++) {
>>> +                                       int tenantId =
>>> Integer.parseInt(parsedLine[i]);
>>> +                                       tenantIds.add(tenantId);
>>> +                               }
>>> +                       }
>>> +               } else if (parsedLine.length == 2) {
>>> +            try {
>>> +
>>> +                int startIndex = Integer.parseInt(parsedLine[0]);
>>> +                int endIndex = Integer.parseInt(parsedLine[1]);
>>> +
>>> +                for (int tenantId = startIndex; tenantId <= endIndex;
>>> tenantId++) {
>>> +
>>> +                    tenantIds.add(tenantId);
>>> +                }
>>> +
>>> +            } catch (NumberFormatException e) {
>>> +                String msg = "Invalid tenant range is specified : " +
>>> tenantRange;
>>> +                log.error(msg, e);
>>> +                throw new RuntimeException(msg, e);
>>> +            }
>>> +
>>> +        } else {
>>> +            String msg = "Invalid tenant range is specified : " +
>>> tenantRange;
>>> +            log.error(msg);
>>> +            throw new RuntimeException(msg);
>>> +        }
>>> +
>>> +        return tenantIds;
>>> +    }
>>> +
>>> +}
>>> \ No newline at end of file
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
>>> new file mode 100755
>>> index 0000000..33162c5
>>> --- /dev/null
>>> +++
>>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
>>> @@ -0,0 +1,80 @@
>>> +/**
>>> + *  Licensed to the Apache Software Foundation (ASF) under one
>>> + *  or more contributor license agreements.  See the NOTICE file
>>> + *  distributed with this work for additional information
>>> + *  regarding copyright ownership.  The ASF 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
>>> +
>>> + *  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 org.apache.stratos.load.balancer.conf.util;
>>> +
>>> +/**
>>> + * This object will hold all the data related to a tenant.
>>> + */
>>> +public class TenantDomainContext {
>>> +
>>> +    /**
>>> +     * this is the unique identifier for this object
>>> +     */
>>> +    private int tenantId;
>>> +
>>> +    /**
>>> +     * Domain, which this tenant belongs to.
>>> +     */
>>> +    private String domain;
>>> +
>>> +    /**
>>> +     * Sub domain, which this tenant belongs to.
>>> +     */
>>> +    private String subDomain;
>>> +
>>> +    public TenantDomainContext(int tenantId, String domain, String
>>> subDomain) {
>>> +        this.tenantId = tenantId;
>>> +        this.domain = domain;
>>> +        this.subDomain = subDomain;
>>> +    }
>>> +
>>> +
>>> +    /** Getters and Setters **/
>>> +
>>> +    public int getTenantId() {
>>> +        return tenantId;
>>> +    }
>>> +
>>> +    public void setTenantId(int tenantId) {
>>> +        this.tenantId = tenantId;
>>> +    }
>>> +
>>> +    public String getDomain() {
>>> +        return domain;
>>> +    }
>>> +
>>> +    public void setDomain(String domain) {
>>> +        this.domain = domain;
>>> +    }
>>> +
>>> +    public String getSubDomain() {
>>> +        return subDomain;
>>> +    }
>>> +
>>> +    public void setSubDomain(String subDomain) {
>>> +        this.subDomain = subDomain;
>>> +    }
>>> +
>>> +
>>> +    /** End of Getters and Setters **/
>>> +
>>> +
>>> +
>>> +
>>> +}
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
>>> b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
>>> new file mode 100755
>>> index 0000000..c94b54c
>>> --- /dev/null
>>> +++
>>> b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
>>> @@ -0,0 +1,48 @@
>>> +/**
>>> + *  Licensed to the Apache Software Foundation (ASF) under one
>>> + *  or more contributor license agreements.  See the NOTICE file
>>> + *  distributed with this work for additional information
>>> + *  regarding copyright ownership.  The ASF 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
>>> +
>>> + *  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 org.apache.stratos.load.balancer.test;
>>> +
>>> +import java.util.Arrays;
>>> +import java.util.List;
>>> +
>>> +import
>>> org.apache.stratos.load.balancer.conf.util.LoadBalancerConfigUtil;
>>> +
>>> +import junit.framework.TestCase;
>>> +
>>> +public class LoadBalancerConfigUtilTest extends TestCase {
>>> +
>>> +    private List<Integer> tenantList1 = Arrays.asList(1,2,3);
>>> +    private List<Integer> tenantList2 = Arrays.asList(1,6,3,4);
>>> +    private List<Integer> tenantList3 = Arrays.asList(43);
>>> +    private List<Integer> tenantList4 = Arrays.asList(0);
>>> +
>>> +    @Override
>>> +    protected void setUp() throws Exception {
>>> +
>>> +    }
>>> +
>>> +    public final void testGetTenantIds() {
>>> +
>>> +        assertEquals(tenantList1,
>>> LoadBalancerConfigUtil.getTenantIds("1-3"));
>>> +        assertEquals(tenantList2,
>>> LoadBalancerConfigUtil.getTenantIds("1,6,3,4"));
>>> +        assertEquals(tenantList3,
>>> LoadBalancerConfigUtil.getTenantIds("43"));
>>> +        assertEquals(tenantList4,
>>> LoadBalancerConfigUtil.getTenantIds("*"));
>>> +    }
>>> +
>>> +}
>>>
>>>
>


-- 
Best Regards,
Nirmal

Nirmal Fernando.
PPMC Member & Committer of Apache Stratos,
Senior Software Engineer, WSO2 Inc.

Blog: http://nirmalfdo.blogspot.com/

Re: [2/3] git commit: Added load balancer configuration parser and its test cases from lb.common component

Posted by Imesh Gunaratne <im...@apache.org>.
Hi Nirmal,

Yes I agree, that would be the ideal situation.

We cleaned up previous load balancer components and created new ones.
That's the reason for checking these files as new.  If you look at the
commit message, it says these files were moved from lb.common.

Thanks
Imesh


On Mon, Nov 11, 2013 at 7:26 AM, Nirmal Fernando <ni...@gmail.com>wrote:

> Imesh,
>
> These should have been git copied/moved.
>  On Nov 10, 2013 10:40 PM, <im...@apache.org> wrote:
>
>> Added load balancer configuration parser and its test cases from
>> lb.common component
>>
>>
>> Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo
>> Commit:
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/32565547
>> Tree:
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/32565547
>> Diff:
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/32565547
>>
>> Branch: refs/heads/master
>> Commit: 32565547050e49e89dd8b76e1fcace9504e89c69
>> Parents: 59811f9
>> Author: Imesh Gunaratne <im...@apache.org>
>> Authored: Sun Nov 10 22:37:36 2013 +0530
>> Committer: Imesh Gunaratne <im...@apache.org>
>> Committed: Sun Nov 10 22:37:36 2013 +0530
>>
>> ----------------------------------------------------------------------
>>  .../conf/LoadBalancerConfiguration.java         | 1202 ++++++++++++++++++
>>  .../load/balancer/conf/structure/Node.java      |  356 ++++++
>>  .../balancer/conf/structure/NodeBuilder.java    |  140 ++
>>  .../load/balancer/conf/util/Constants.java      |   50 +
>>  .../load/balancer/conf/util/HostContext.java    |  161 +++
>>  .../conf/util/LoadBalancerConfigUtil.java       |  305 +++++
>>  .../balancer/conf/util/TenantDomainContext.java |   80 ++
>>  .../test/LoadBalancerConfigUtilTest.java        |   48 +
>>  .../test/LoadBalancerConfigurationTest.java     |  169 +++
>>  .../load/balancer/test/NodeBuilderTest.java     |  123 ++
>>  .../src/test/resources/loadbalancer.conf        |   84 ++
>>  .../src/test/resources/loadbalancer1.conf       |   60 +
>>  .../src/test/resources/loadbalancer2.conf       |   50 +
>>  .../src/test/resources/testng.xml               |   29 +
>>  14 files changed, 2857 insertions(+)
>> ----------------------------------------------------------------------
>>
>>
>>
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
>> new file mode 100755
>> index 0000000..747ba5b
>> --- /dev/null
>> +++
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
>> @@ -0,0 +1,1202 @@
>> +/**
>> + *  Licensed to the Apache Software Foundation (ASF) under one
>> + *  or more contributor license agreements.  See the NOTICE file
>> + *  distributed with this work for additional information
>> + *  regarding copyright ownership.  The ASF 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
>> +
>> + *  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 org.apache.stratos.load.balancer.conf;
>> +
>> +import org.apache.commons.lang.builder.HashCodeBuilder;
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +import org.apache.synapse.commons.util.PropertyHelper;
>> +import org.apache.stratos.load.balancer.conf.structure.Node;
>> +import org.apache.stratos.load.balancer.conf.structure.NodeBuilder;
>> +import org.apache.stratos.load.balancer.conf.util.Constants;
>> +import org.apache.stratos.load.balancer.conf.util.HostContext;
>> +import org.apache.stratos.load.balancer.conf.util.LoadBalancerConfigUtil;
>> +import org.apache.stratos.load.balancer.conf.util.TenantDomainContext;
>> +import java.io.*;
>> +import java.net.URL;
>> +import java.util.*;
>> +
>> +/**
>> + * Data object which hold configuration data of the load analyzer task
>> + */
>> +@SuppressWarnings("unused")
>> +public class LoadBalancerConfiguration implements Serializable {
>> +
>> +    protected static final long serialVersionUID = -5553545217542808233L;
>> +
>> +    private static final Log log =
>> LogFactory.getLog(LoadBalancerConfiguration.class);
>> +
>> +    /**
>> +     * This map is there to speed up the lookup time.
>> +     * Key: domain
>> +     * <p/>
>> +     * Value: A map whose key is sub domain and value is
>> ServiceConfiguration
>> +     */
>> +    private Map<String, Map<String, ServiceConfiguration>>
>> serviceConfigurations =
>> +            new HashMap<String, Map<String, ServiceConfiguration>>();
>> +
>> +    /**
>> +     * Key - host name
>> +     * Value - {@link
>> org.apache.stratos.load.balancer.conf.util.HostContext}
>> +     */
>> +    private transient Map<String, HostContext> hostCtxt = new
>> HashMap<String, HostContext>();
>> +
>> +    /**
>> +     * This map is there to speed up the lookup time.
>> +     * Key: service name/cartridge type (Stratos2). NOTE: that this is
>> not the service cluster domain.
>> +     * Value: list of {@link
>> org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration.ServiceConfiguration}
>> - corresponding objects under a service name.
>> +     */
>> +       private Map<String, List<ServiceConfiguration>>
>> serviceNameToServiceConfigurations =
>> +                       new HashMap<String, List<ServiceConfiguration>>();
>> +
>> +    /**
>> +     * This list will be used to identify host name duplications among
>> different services.
>> +     * Within a service there can be duplications, but among different
>> services you can't have duplications.
>> +     * Key - service name
>> +     * Value - hosts under the respective service.
>> +     */
>> +    private Map<String, Set<String>> hostNamesTracker = new
>> HashMap<String, Set<String>>();
>> +
>> +    protected ServiceConfiguration defaultServiceConfig;
>> +    protected LBConfiguration lbConfig;
>> +
>> +    /**
>> +     * LBConfig file as a String
>> +     */
>> +    protected String lbConfigString;
>> +
>> +    /**
>> +     * Root node object for loadbalancer.conf
>> +     */
>> +    protected Node rootNode;
>> +
>> +    private LoadBalancerConfiguration(){
>> +        init(System.getProperty("loadbalancer.conf"));
>> +    }
>> +
>> +    private static LoadBalancerConfiguration instance ;
>> +
>> +    public static LoadBalancerConfiguration getInstance(){
>> +        if(instance == null){
>> +            instance = new LoadBalancerConfiguration();
>> +        }
>> +        return instance;
>> +    }
>> +
>> +    /**
>> +     * Sample loadbalancer.conf:
>> +     * <p/>
>> +     * loadbalancer {
>> +     * # minimum number of load balancer instances
>> +     * instances           1;
>> +     * # whether autoscaling enable or not
>> +     * enable_autoscaler   true;
>> +     * # End point reference of the Autoscaler Service
>> +     * autoscaler_service_epr
>> https://10.100.3.81:9443/services/AutoscalerService/;
>> +     * # interval between two task executions in milliseconds
>> +     * autoscaler_task_interval 1000;
>> +     * # after an instance booted up, task will wait till this much of
>> time and let the server started up
>> +     * server_startup_delay 15000;
>> +     * }
>> +     * <p/>
>> +     * services {
>> +     * defaults {
>> +     * min_app_instances       1;
>> +     * max_app_instances       5;
>> +     * queue_length_per_node   400;
>> +     * rounds_to_average       10;
>> +     * instances_per_scale_up  1;
>> +     * message_expiry_time     60000;
>> +     * }
>> +     * <p/>
>> +     * appserver {
>> +     * hosts                   appserver.cloud-test.wso2.com,
>> as.cloud-test.wso2.com;
>> +     * domains   {
>> +     * wso2.as1.domain {
>> +     * tenant_range    1-100;
>> +     * }
>> +     * wso2.as2.domain {
>> +     * tenant_range    101-200;
>> +     * }
>> +     * wso2.as3.domain {
>> +     * tenant_range    *;
>> +     * }
>> +     * }
>> +     * }
>> +     * }
>> +     *
>> +     * @param configURL URL of the load balancer config
>> +     */
>> +    public void init(String configURL) {
>> +
>> +        if(configURL == null){
>> +            String msg = "Cannot locate the location of the
>> loadbalancer.conf file." +
>> +                   " You need to set the 'loadbalancer.conf' system
>> property.";
>> +            log.error(msg);
>> +            throw new RuntimeException(msg);
>> +        }
>> +
>> +        if (configURL.startsWith("$system:")) {
>> +            configURL =
>> System.getProperty(configURL.substring("$system:".length()));
>> +        }
>> +
>> +        try {
>> +
>> +            // get loadbalancer.conf file as a String
>> +            if (configURL.startsWith(File.separator)) {
>> +                lbConfigString = createLBConfigString(configURL);
>> +            } else {
>> +                lbConfigString = createLBConfigString(new
>> URL(configURL).openStream());
>> +            }
>> +
>> +        } catch (Exception e) {
>> +            String msg = "Cannot read configuration file from " +
>> configURL;
>> +            log.error(msg, e);
>> +            throw new RuntimeException(msg, e);
>> +        }
>> +
>> +        // build a Node object for whole loadbalancer.conf
>> +        rootNode = new Node();
>> +        rootNode.setName("root");
>> +        rootNode = NodeBuilder.buildNode(rootNode, lbConfigString);
>> +
>> +        // load 'loadbalancer' node
>> +        Node lbConfigNode =
>> rootNode.findChildNodeByName(Constants.LOAD_BALANCER_ELEMENT);
>> +
>> +        if(lbConfigNode != null){
>> +               createConfiguration(lbConfig = new LBConfiguration(),
>> lbConfigNode);
>> +        }
>> +
>> +        // load services node
>> +        Node servicesConfigNode =
>> rootNode.findChildNodeByName(Constants.SERVICES_ELEMENT);
>> +
>> +        if (servicesConfigNode == null) {
>> +            String msg = "Mandatory " + Constants.SERVICES_ELEMENT +
>> +                    " element can not be found in the configuration
>> file.";
>> +            log.error(msg);
>> +            throw new RuntimeException(msg);
>> +        }
>> +
>> +        // Set services configuration
>> +        createServicesConfig(servicesConfigNode);
>> +
>> +    }
>> +
>> +
>> +    /**
>> +     * Process the content of the following 'services' element
>> +     * <p/>
>> +     * services {
>> +     * defaults {
>> +     * min_app_instances       1;
>> +     * max_app_instances       5;
>> +     * queue_length_per_node   400;
>> +     * rounds_to_average       10;
>> +     * instances_per_scale_up  1;
>> +     * message_expiry_time     60000;
>> +     * }
>> +     * <p/>
>> +     * appserver {
>> +     * hosts                   appserver.cloud-test.wso2.com,
>> as.cloud-test.wso2.com;
>> +     * domains   {
>> +     * wso2.as1.domain {
>> +     * tenant_range    1-100;
>> +     * }
>> +     * wso2.as2.domain {
>> +     * tenant_range    101-200;
>> +     * }
>> +     * wso2.as3.domain {
>> +     * tenant_range    *;
>> +     * }
>> +     * }
>> +     * }
>> +     * }
>> +     *
>> +     * @param servicesConfigNode services element's Node
>> +     */
>> +    public List<ServiceConfiguration> createServicesConfig(Node
>> servicesConfigNode) {
>> +
>> +        // current list of service configs
>> +        List<ServiceConfiguration> currentServiceConfigs = new
>> ArrayList<ServiceConfiguration>();
>> +
>> +        // Building default configuration
>> +        Node defaultNode =
>> servicesConfigNode.findChildNodeByName(Constants.DEFAULTS_ELEMENT);
>> +
>> +        if (defaultNode != null) {
>> +
>> +            createConfiguration(defaultServiceConfig = new
>> ServiceConfiguration(), defaultNode);
>> +        }
>> +
>> +        // Building custom services configuration
>> +        for (Node serviceNode : servicesConfigNode.getChildNodes()) {
>> +            //skip default node
>> +            if (serviceNode != defaultNode) {
>> +
>> +                String serviceName = serviceNode.getName();
>> +
>> +                // reading domains
>> +
>> +                Node domainsNode;
>> +
>> +                if (serviceNode.getChildNodes().isEmpty() ||
>> +                        !(domainsNode =
>> serviceNode.getChildNodes().get(0)).getName().equals(
>> +                                Constants.DOMAIN_ELEMENT)) {
>> +
>> +                    String msg = "The mandatory domains element, child
>> of the " + serviceName +
>> +                            " element is not specified in the
>> configuration file. \n"+
>> +                            serviceNode.toString();
>> +                    log.error(msg);
>> +                    throw new RuntimeException(msg);
>> +                }
>> +
>> +                if (domainsNode.getChildNodes().isEmpty()) {
>> +                    // this is probably a mistake, so we don't proceed
>> +                    String msg = "No domain is specified under " +
>> Constants.DOMAIN_ELEMENT +
>> +                            " of " + serviceName + " element.";
>> +                    log.error(msg);
>> +                    throw new RuntimeException(msg);
>> +                }
>> +
>> +                ServiceConfiguration serviceConfig;
>> +
>> +                // iterates through all the service domain specified in
>> this service element.
>> +                for (Node domain : domainsNode.getChildNodes()) {
>> +
>> +                    // create a new service configuration
>> +                    serviceConfig = new ServiceConfiguration();
>> +
>> +                    // set service name
>> +                    serviceConfig.setServiceName(serviceName);
>> +
>> +                    // set domain name
>> +                    serviceConfig.setDomain(domain.getName());
>> +
>> +                    // let's set properties common to all domains
>> specified in this service element.
>> +                    createConfiguration(serviceConfig, serviceNode);
>> +
>> +                    // load properties specified under this service
>> domain element.
>> +                    createConfiguration(serviceConfig, domain);
>> +
>> +                    // check host name duplication
>> +                    if(isDuplicatedHost(serviceNode.getName(),
>> serviceConfig)){
>> +                        // this is probably a mistake, so we don't
>> proceed
>> +                        String msg = "Duplicated host names detected for
>> different service domains.\n" +
>> +                                "Element: \n"+serviceNode.toString();
>> +                        log.error(msg);
>> +                        throw new RuntimeException(msg);
>> +                    }
>> +
>> +                    currentServiceConfigs.add(serviceConfig);
>> +
>> +                }
>> +            }
>> +        }
>> +
>> +        for (ServiceConfiguration serviceConfiguration :
>> currentServiceConfigs) {
>> +
>> +            // add the built ServiceConfiguration, to the map
>> +            addServiceConfiguration(serviceConfiguration);
>> +
>> +        }
>> +
>> +        return currentServiceConfigs;
>> +
>> +    }
>> +
>> +
>> +    public boolean addServiceConfiguration(ServiceConfiguration
>> serviceConfig) {
>> +
>> +        Map<String, ServiceConfiguration> map;
>> +        String domain = serviceConfig.getDomain();
>> +
>> +        if(domain == null){
>> +            String msg = "Domain of a Service Configuration cannot be
>> null. Hence this " +
>> +                       "Configuration will be neglected.";
>> +            log.error(msg);
>> +            return false;
>> +        }
>> +
>> +        String subDomain = serviceConfig.getSubDomain();
>> +
>> +        if (serviceConfigurations.containsKey(domain)) {
>> +            map = serviceConfigurations.get(domain);
>> +        } else {
>> +            map = new HashMap<String, ServiceConfiguration>();
>> +        }
>> +        // put this serviceConfig
>> +        map.put(subDomain, serviceConfig);
>> +
>> +        // update the parent map
>> +        serviceConfigurations.put(domain, map);
>> +
>> +        // add to serviceNameToServiceConfiguration map
>> +        List<ServiceConfiguration> configs;
>> +
>>  if(serviceNameToServiceConfigurations.get(serviceConfig.getServiceName())
>> == null){
>> +               configs = new ArrayList<ServiceConfiguration>();
>> +
>> +        }else{
>> +               configs =
>> serviceNameToServiceConfigurations.get(serviceConfig.getServiceName());
>> +        }
>> +
>> +        if(!configs.contains(serviceConfig)){
>> +               configs.add(serviceConfig);
>> +        }
>> +
>>  serviceNameToServiceConfigurations.put(serviceConfig.getServiceName(),
>> configs);
>> +
>> +        return true;
>> +    }
>> +
>> +    public ServiceConfiguration removeServiceConfiguration(String
>> domain, String subDomain) {
>> +
>> +        Map<String, ServiceConfiguration> map;
>> +        ServiceConfiguration serviceConfig = null;
>> +
>> +        if(domain == null){
>> +            String msg = "Domain of a Service Configuration cannot be
>> null. Hence this " +
>> +                       "Configuration will be neglected.";
>> +            log.error(msg);
>> +            return null;
>> +        }
>> +
>> +        if (serviceConfigurations.containsKey(domain)) {
>> +            map = serviceConfigurations.get(domain);
>> +
>> +            if(map != null){
>> +               serviceConfig = map.remove(subDomain);
>> +            }
>> +        }
>> +
>> +        if(serviceConfig == null){
>> +               String msg = "No matching service configuration found for
>> domain: "+domain+
>> +                               ", sub domain: "+subDomain;
>> +            log.error(msg);
>> +               return null;
>> +        }
>> +
>> +        String serviceName = serviceConfig.getServiceName();
>> +
>> +        if (serviceName != null &&
>> serviceNameToServiceConfigurations.containsKey(serviceName)) {
>> +            if(serviceConfig != null){
>> +               List<ServiceConfiguration> list =
>> serviceNameToServiceConfigurations.get(serviceName);
>> +
>> +               list.remove(serviceConfig);
>> +
>> +               serviceNameToServiceConfigurations.put(serviceName, list);
>> +            }
>> +        }
>> +
>> +        Set<String> allHosts;
>> +
>> +        if (hostNamesTracker.containsKey(serviceName)) {
>> +            allHosts = hostNamesTracker.get(serviceName);
>> +
>> +            for (String hostName : serviceConfig.getHosts()) {
>> +
>> +                               if (hostName != null) {
>> +
>> +                                       allHosts.remove(hostName);
>> +
>> +                                       hostCtxt.remove(hostName);
>> +                               }
>> +            }
>> +        }
>> +
>> +        return serviceConfig;
>> +    }
>> +
>> +    public void resetData(){
>> +       serviceConfigurations =
>> +                new HashMap<String, Map<String, ServiceConfiguration>>();
>> +
>> +       serviceNameToServiceConfigurations =
>> +                       new HashMap<String, List<ServiceConfiguration>>();
>> +
>> +    }
>> +
>> +
>> +    /**
>> +     * Duplications can only be seen, when you traverse down the
>> configuration file.
>> +     *
>> +     */
>> +    public boolean isDuplicatedHost(String name, ServiceConfiguration
>> serviceConfig) {
>> +
>> +        /**
>> +         * This will be populated with host names of all other services
>> other than the
>> +         * service subjected to the test.
>> +         */
>> +        List<String> hostsOtherThanMine = new
>> ArrayList<String>(hostNamesTracker.values().size());
>> +
>> +        for (Map.Entry<String, Set<String>> entry :
>> hostNamesTracker.entrySet()) {
>> +            if (!entry.getKey().equals(name)) {
>> +                hostsOtherThanMine.addAll(entry.getValue());
>> +            }
>> +        }
>> +
>> +        for (String host : serviceConfig.getHosts()) {
>> +            if (!hostsOtherThanMine.isEmpty() &&
>> hostsOtherThanMine.contains(host)) {
>> +                return true;
>> +            }
>> +        }
>> +
>> +        addToHostNameTrackerMap(name, serviceConfig.getHosts());
>> +
>> +        return false;
>> +    }
>> +
>> +
>> +    public void addToHostNameTrackerMap(String name, List<String> hosts)
>> {
>> +
>> +        Set<String> allHosts;
>> +
>> +        if (hostNamesTracker.containsKey(name)) {
>> +            allHosts = hostNamesTracker.get(name);
>> +            allHosts.addAll(hosts);
>> +        } else {
>> +            allHosts = new HashSet<String>(hosts);
>> +        }
>> +        hostNamesTracker.put(name, allHosts);
>> +    }
>> +
>> +    public void addToHostContextMap(String hostName, HostContext ctxt) {
>> +
>> +        if (hostName != null && ctxt != null) {
>> +            hostCtxt.put(hostName, ctxt);
>> +        }
>> +    }
>> +
>> +    /**
>> +     * Return a map of {@link
>> org.apache.stratos.load.balancer.conf.util.HostContext}.
>> +     * @return
>> +     */
>> +    public Map<String, HostContext> getHostContextMap() {
>> +
>> +        List<Integer> tenantIds;
>> +        Map<String, String> URLSuffixes;
>> +
>> +        // FIXME if possible! I couldn't think of any other way to do
>> this, at this moment.
>> +        // Note: some of these for-loops are pretty small, thus no
>> considerable performance overhead.
>> +        // iterate through each service
>> +        for (Iterator<Set<String>> it =
>> hostNamesTracker.values().iterator(); it.hasNext();) {
>> +
>> +            // iterate through host names of this service
>> +            for (String hostName : ((Set<String>) it.next())) {
>> +
>> +                // building HostContext
>> +                HostContext ctxt = new HostContext(hostName);
>> +
>> +                // iterate through domains of this host
>> +                for (Map.Entry<String, Map<String,
>> ServiceConfiguration>> parentMap : serviceConfigurations.entrySet()) {
>> +
>> +                    // iterate through sub domain of this domain
>> +                    for (Map.Entry<String, ServiceConfiguration>
>> childMap : parentMap.getValue()
>> +                            .entrySet()) {
>> +                        // iterate through hosts of this
>> +                        for (String host :
>> childMap.getValue().getHosts()) {
>> +                            // if a matching Service configuration is
>> found.
>> +                            if (host.equals(hostName)) {
>> +
>> +                                String tenantRange =
>> childMap.getValue().getTenantRange();
>> +                                String domain = parentMap.getKey();
>> +                                String subDomain = childMap.getKey();
>> +
>> +
>>  ctxt.addTenantDomainContexts(LoadBalancerConfigUtil.getTenantDomainContexts(tenantRange,
>> domain, subDomain));
>> +
>> +                                break;
>> +                            }
>> +                        }
>> +
>> +                        //iterate through URL suffixes
>> +                        for(Map.Entry<String, String> entry :
>> childMap.getValue().getUrl_suffix().entrySet()) {
>> +                            if(entry.getKey().equals(hostName)) {
>> +
>> +                                ctxt.setUrlSuffix(entry.getValue());
>> +
>> +                                break;
>> +                            }
>> +
>> +                        }
>> +                    }
>> +                }
>> +
>> +                // add this hostCtxt
>> +                hostCtxt.put(hostName, ctxt);
>> +            }
>> +
>> +        }
>> +
>> +        return hostCtxt;
>> +
>> +    }
>> +
>> +    protected void createConfiguration(Configuration config, Node node) {
>> +
>> +        if (node == null) {
>> +            String msg = "The configuration element for " +
>> +                    config.getClass().getName() + " is null.";
>> +            throw new RuntimeException(msg);
>> +        }
>> +
>> +        try {
>> +            // load properties
>> +            for (Map.Entry<String, String> entry :
>> node.getProperties().entrySet()) {
>> +                String key = entry.getKey();
>> +                String value = entry.getValue();
>> +
>> +                PropertyHelper.setInstanceProperty(key, value, config);
>> +            }
>> +
>> +        } catch (Exception e) {
>> +            String msg = "Error setting values to " +
>> config.getClass().getName();
>> +            log.error(msg, e);
>> +            throw new RuntimeException(msg, e);
>> +        }
>> +    }
>> +
>> +    public LBConfiguration getLoadBalancerConfig() {
>> +        return lbConfig;
>> +    }
>> +
>> +    public String[] getServiceDomains() {
>> +
>> +        Object[] objs = serviceConfigurations.keySet().toArray();
>> +
>> +        return Arrays.copyOf(objs, objs.length, String[].class);
>> +
>> +    }
>> +
>> +    public String[] getServiceSubDomains(String domain) {
>> +
>> +        if (serviceConfigurations.get(domain) != null) {
>> +            Object[] objs =
>> serviceConfigurations.get(domain).keySet().toArray();
>> +            return Arrays.copyOf(objs, objs.length, String[].class);
>> +        }
>> +
>> +        return new String[0];
>> +    }
>> +
>> +    public ServiceConfiguration getServiceConfig(String domain, String
>> subDomain) {
>> +        if (serviceConfigurations.get(domain) != null) {
>> +            return serviceConfigurations.get(domain).get(subDomain);
>> +        }
>> +        return null;
>> +    }
>> +
>> +
>> +    public List<ServiceConfiguration> getServiceConfigs(String
>> serviceName) {
>> +        return serviceNameToServiceConfigurations.get(serviceName);
>> +    }
>> +
>> +    /**
>> +     * Convert given configuration file to a single String
>> +     *
>> +     * @param configFileName - file name to convert
>> +     * @return String with complete lb configuration
>> +     * @throws java.io.FileNotFoundException
>> +     */
>> +    public String createLBConfigString(String configFileName) throws
>> FileNotFoundException {
>> +        StringBuilder lbConfigString = new StringBuilder("");
>> +
>> +        File configFile = new File(configFileName);
>> +        Scanner scanner;
>> +
>> +        scanner = new Scanner(configFile);
>> +
>> +        while (scanner.hasNextLine()) {
>> +            lbConfigString.append(scanner.nextLine().trim() + "\n");
>> +        }
>> +
>> +        return lbConfigString.toString().trim();
>> +    }
>> +
>> +    public String createLBConfigString(InputStream configFileName)
>> throws IOException {
>> +
>> +        // read the stream with BufferedReader
>> +        BufferedReader br = new BufferedReader(new
>> InputStreamReader(configFileName));
>> +
>> +        StringBuilder sb = new StringBuilder();
>> +
>> +        String line;
>> +        while ((line = br.readLine()) != null) {
>> +            sb.append(line.trim() + "\n");
>> +        }
>> +
>> +        return sb.toString().trim();
>> +    }
>> +
>> +    public abstract class Configuration implements Serializable {
>> +
>> +        private static final long serialVersionUID =
>> -5433889427746551250L;
>> +        protected String imageId = System.getenv("ami_id");
>> +        protected String payload;
>> +        protected boolean payloadSet;
>> +
>> +        protected String availability_zone = "us-east-1c";
>> +        protected boolean availabilityZoneSet;
>> +
>> +        protected String[] security_groups = new String[]{"default"};
>> +        protected boolean securityGroupsSet;
>> +
>> +        protected String instance_type = "m1.large";
>> +        protected boolean instanceTypeSet;
>> +
>> +        protected String additional_info;
>> +
>> +        public String getImageId() {
>> +            return imageId;
>> +        }
>> +
>> +        public String getAdditionalInfo() {
>> +            return additional_info;
>> +        }
>> +
>> +        public String getAvailability_zone() {
>> +            if (this instanceof LBConfiguration) {
>> +                return availability_zone;
>> +            }
>> +            if (availabilityZoneSet) {
>> +                return availability_zone;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.availabilityZoneSet) {
>> +                return defaultServiceConfig.availability_zone;
>> +            }
>> +            return availability_zone;
>> +        }
>> +
>> +        public String[] getSecurityGroups() {
>> +            if (this instanceof LBConfiguration) {
>> +                return security_groups;
>> +            }
>> +            if (securityGroupsSet) {
>> +                return security_groups;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.securityGroupsSet) {
>> +                return defaultServiceConfig.security_groups;
>> +            }
>> +            return security_groups;
>> +        }
>> +
>> +        public String getInstanceType() {
>> +            if (this instanceof LBConfiguration) {
>> +                return instance_type;
>> +            }
>> +            if (instanceTypeSet) {
>> +                return instance_type;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.instanceTypeSet) {
>> +                return defaultServiceConfig.instance_type;
>> +            }
>> +            return instance_type;
>> +        }
>> +
>> +
>> +        public String getUserData() {
>> +            if (payload == null) {
>> +                payload =
>> LoadBalancerConfigUtil.getUserData("resources/cluster_node.zip");
>> +            }
>> +            if (this instanceof LBConfiguration) {
>> +                return payload;
>> +            }
>> +            if (payloadSet) {
>> +                return payload;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.payloadSet) {
>> +                return defaultServiceConfig.payload;
>> +            }
>> +            return payload;
>> +        }
>> +
>> +        public void setPayload(String payload) {
>> +            this.payload =
>> LoadBalancerConfigUtil.getUserData(LoadBalancerConfigUtil.replaceVariables(payload));
>> +            this.payloadSet = true;
>> +        }
>> +
>> +        public void setAvailability_zone(String availabilityZone) {
>> +            this.availability_zone =
>> LoadBalancerConfigUtil.replaceVariables(availabilityZone);
>> +            this.availabilityZoneSet = true;
>> +        }
>> +
>> +        public void setSecurity_groups(String securityGroups) {
>> +            this.security_groups =
>> LoadBalancerConfigUtil.replaceVariables(securityGroups).split(",");
>> +            this.securityGroupsSet = true;
>> +        }
>> +
>> +        public void setInstance_type(String instanceType) {
>> +            this.instance_type =
>> LoadBalancerConfigUtil.replaceVariables(instanceType);
>> +            this.instanceTypeSet = true;
>> +        }
>> +
>> +    }
>> +
>> +    public class LBConfiguration extends Configuration implements
>> Serializable {
>> +
>> +        private static final long serialVersionUID =
>> 1357143883932816418L;
>> +        private String elasticIP;//=
>> LoadBalancerConfigUtil.replaceVariables("${ELASTIC_IP}");
>> +        private int instances = 1;
>> +        private boolean isAutoscaleEnabled;
>> +        private int autoscalerTaskInterval = 30000;
>> +        private String autoscalerServiceEpr;
>> +        private int serverStartupDelay = 60000;
>> +        private int sizeOfCache = 0 ;
>> +        private boolean failOver;
>> +        private int sessionTimeOut = -1;
>> +        private String groupManagementAgentClass;
>> +        private String autoscalerTaskClass;
>> +        private String mbServerUrl;
>> +        private boolean useEmbeddedAutoscaler = true;
>> +        private String algorithm =
>> "org.apache.synapse.endpoints.algorithms.RoundRobin";
>> +
>> +        public String getElasticIP() {
>> +            return elasticIP;
>> +        }
>> +
>> +        public int getInstances() {
>> +            return instances;
>> +        }
>> +
>> +        public boolean isAutoscaleEnabled() {
>> +            return isAutoscaleEnabled;
>> +        }
>> +
>> +        public boolean useEmbeddedAutoscaler() {
>> +            return useEmbeddedAutoscaler;
>> +        }
>> +
>> +        public boolean getFailOver() {
>> +            return failOver;
>> +        }
>> +
>> +        public String getAutoscalerServiceEpr() {
>> +            return autoscalerServiceEpr;
>> +        }
>> +
>> +        public int getAutoscalerTaskInterval() {
>> +            return autoscalerTaskInterval;
>> +        }
>> +
>> +        public int getServerStartupDelay() {
>> +            return serverStartupDelay;
>> +        }
>> +
>> +        public int getSessionTimeOut() {
>> +            return sessionTimeOut;
>> +        }
>> +
>> +        public void setElasticIP(String elasticIP) {
>> +            this.elasticIP =
>> LoadBalancerConfigUtil.replaceVariables(elasticIP);
>> +        }
>> +
>> +        public void setInstances(int instances) {
>> +            this.instances = instances;
>> +        }
>> +
>> +        public void setEnable_autoscaler(String isEnabled) {
>> +            this.isAutoscaleEnabled = Boolean.parseBoolean(isEnabled);
>> +        }
>> +
>> +        public void setUse_embedded_autoscaler(String use) {
>> +            this.useEmbeddedAutoscaler = Boolean.parseBoolean(use);
>> +        }
>> +
>> +        public void setFail_over(String isEnabled) {
>> +            this.failOver = Boolean.parseBoolean(isEnabled);
>> +        }
>> +
>> +        public void setAutoscaler_service_epr(String epr) {
>> +            this.autoscalerServiceEpr = epr;
>> +        }
>> +
>> +        public void setMb_server_url(String url) {
>> +            this.mbServerUrl = url;
>> +        }
>> +
>> +        public String getMbServerUrl() {
>> +               return mbServerUrl;
>> +        }
>> +
>> +               public void setAutoscaler_task_interval(String interval) {
>> +            this.autoscalerTaskInterval = Integer.parseInt(interval);
>> +        }
>> +
>> +        public void setServer_startup_delay(String delay) {
>> +            this.serverStartupDelay = Integer.parseInt(delay);
>> +        }
>> +
>> +        public void setSession_timeout(String timeout) {
>> +            this.sessionTimeOut = Integer.parseInt(timeout);
>> +        }
>> +
>> +        public String getAlgorithm() {
>> +            return algorithm;
>> +        }
>> +
>> +        public void setAlgorithm(String algorithm) {
>> +            if (algorithm != null) {
>> +                this.algorithm = algorithm;
>> +            }
>> +        }
>> +
>> +        public int getSizeOfCache() {
>> +            return sizeOfCache;
>> +        }
>> +
>> +        public void setSize_of_cache(int sizeOfCache) {
>> +            this.sizeOfCache = sizeOfCache;
>> +        }
>> +
>> +        public String getGroupManagementAgentClass() {
>> +            return groupManagementAgentClass;
>> +        }
>> +
>> +        public String getAutoscalerTaskClass() {
>> +            return autoscalerTaskClass;
>> +        }
>> +
>> +        public void setGroup_mgt_agent(String groupManagementAgentClass){
>> +            this.groupManagementAgentClass = groupManagementAgentClass;
>> +        }
>> +
>> +        public void setAutoscaler_task(String autoscalerTaskClass){
>> +            this.autoscalerTaskClass = autoscalerTaskClass;
>> +        }
>> +    }
>> +
>> +    public class ServiceConfiguration extends Configuration implements
>> Serializable {
>> +
>> +       private String serviceName;
>> +
>> +        public String getServiceName() {
>> +               return serviceName;
>> +        }
>> +
>> +               public void setServiceName(String name) {
>> +               this.serviceName = name;
>> +        }
>> +
>> +               public String getPublicIp() {
>> +               return publicIp;
>> +        }
>> +
>> +               public void setPublic_ip(String publicIp) {
>> +               this.publicIp = publicIp;
>> +        }
>> +
>> +               private String publicIp;
>> +
>> +               private static final long serialVersionUID =
>> 8707314702788040116L;
>> +        private int minAppInstances = 1;
>> +        private boolean minAppInstancesSet;
>> +
>> +        private int maxAppInstances = 3;
>> +        private boolean maxAppInstancesSet;
>> +
>> +        private int maxRequestsPerSecond = 100;
>> +        private boolean maxRequestsPerSecondSet;
>> +
>> +        private double alarmingUpperRate = 0.7;
>> +        private boolean alarmingUpperRateSet;
>> +
>> +        private double alarmingLowerRate = 0.2;
>> +        private boolean alarmingLowerRateSet;
>> +
>> +        private double scaleDownFactor = 0.25;
>> +        private boolean scaleDownFactorSet;
>> +
>> +        private int roundsToAverage = 10;
>> +        private boolean roundsToAverageSet;
>> +
>> +        private int instancesPerScaleUp = 1;
>> +        private boolean instancesPerScaleUpSet;
>> +
>> +        private int messageExpiryTime = 60000; // milliseconds
>> +        private boolean messageExpiryTimeSet;
>> +
>> +        private List<String> hosts = new ArrayList<String>();
>> +        private Map<String, String> urlSuffixes = new HashMap<String,
>> String>();
>> +        private boolean hostsSet;
>> +
>> +        private String domain;
>> +
>> +        private String tenantRange;
>> +        private boolean tenantRangeSet;
>> +
>> +        private String subDomain = Constants.DEFAULT_SUB_DOMAIN;
>> +        private boolean subDomainSet;
>> +
>> +        public String getTenantRange() {
>> +            if (tenantRangeSet) {
>> +                return tenantRange;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.tenantRangeSet) {
>> +                return defaultServiceConfig.tenantRange;
>> +            }
>> +            return tenantRange;
>> +        }
>> +
>> +        public String getDomain() {
>> +            return domain;
>> +        }
>> +
>> +        public List<String> getHosts() {
>> +            if (hostsSet) {
>> +                return hosts;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.hostsSet) {
>> +                return defaultServiceConfig.hosts;
>> +            }
>> +            return hosts;
>> +        }
>> +
>> +        public int getMinAppInstances() {
>> +            if (minAppInstancesSet) {
>> +                return minAppInstances;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.minAppInstancesSet) {
>> +                return defaultServiceConfig.minAppInstances;
>> +            }
>> +            return minAppInstances;
>> +        }
>> +
>> +        public int getMaxAppInstances() {
>> +            if (maxAppInstancesSet) {
>> +                return maxAppInstances;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.maxAppInstancesSet) {
>> +                return defaultServiceConfig.maxAppInstances;
>> +            }
>> +            return maxAppInstances;
>> +        }
>> +
>> +        public int getMaxRequestsPerSecond() {
>> +            if (maxRequestsPerSecondSet) {
>> +                return maxRequestsPerSecond;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.maxRequestsPerSecondSet) {
>> +                return defaultServiceConfig.maxRequestsPerSecond;
>> +            }
>> +            return maxRequestsPerSecond;
>> +        }
>> +
>> +        public int getRoundsToAverage() {
>> +            if (roundsToAverageSet) {
>> +                return roundsToAverage;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.roundsToAverageSet) {
>> +                return defaultServiceConfig.roundsToAverage;
>> +            }
>> +            return roundsToAverage;
>> +        }
>> +
>> +        public int getInstancesPerScaleUp() {
>> +            if (instancesPerScaleUpSet) {
>> +                return instancesPerScaleUp;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.instancesPerScaleUpSet) {
>> +                return defaultServiceConfig.instancesPerScaleUp;
>> +            }
>> +            return instancesPerScaleUp;
>> +        }
>> +
>> +        public int getMessageExpiryTime() {
>> +            if (messageExpiryTimeSet) {
>> +                return messageExpiryTime;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.messageExpiryTimeSet) {
>> +                return defaultServiceConfig.messageExpiryTime;
>> +            }
>> +            return messageExpiryTime;
>> +        }
>> +
>> +        public String getSubDomain() {
>> +            if (subDomainSet) {
>> +                return subDomain;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.subDomainSet) {
>> +                return defaultServiceConfig.subDomain;
>> +            }
>> +            return subDomain;
>> +        }
>> +
>> +        public void setMin_app_instances(int minAppInstances) {
>> +            this.minAppInstances = minAppInstances;
>> +            this.minAppInstancesSet = true;
>> +        }
>> +
>> +        public void setMax_app_instances(int maxAppInstances) {
>> +            if (maxAppInstances < 1) {
>> +                LoadBalancerConfigUtil.handleException("maxAppInstances
>> in the autoscaler task configuration " +
>> +                        "should be at least 1");
>> +            }
>> +            this.maxAppInstances = maxAppInstances;
>> +            this.maxAppInstancesSet = true;
>> +        }
>> +
>> +               public void setAlarming_upper_rate(double rate) {
>> +                       if (rate > 0 && rate <= 1) {
>> +                               this.alarmingUpperRate = rate;
>> +                               this.alarmingUpperRateSet = true;
>> +                       }
>> +               }
>> +
>> +        public void setAlarming_lower_rate(double rate) {
>> +                       if (rate > 0 && rate <= 1) {
>> +                               this.alarmingLowerRate = rate;
>> +                               this.alarmingLowerRateSet = true;
>> +                       }
>> +        }
>> +
>> +               public void setScale_down_factor(double factor) {
>> +                       if (factor > 0 && factor <= 1) {
>> +                               this.scaleDownFactor = factor;
>> +                               this.scaleDownFactorSet = true;
>> +                       }
>> +               }
>> +
>> +        public void setMax_requests_per_second(int rps) {
>> +            this.maxRequestsPerSecond = rps;
>> +            this.maxRequestsPerSecondSet = true;
>> +        }
>> +
>> +        public void setRounds_to_average(int roundsToAverage) {
>> +            this.roundsToAverage = roundsToAverage;
>> +            this.roundsToAverageSet = true;
>> +        }
>> +
>> +        public void setInstances_per_scale_up(int instancesPerScaleUp) {
>> +            if (instancesPerScaleUp < 1) {
>> +
>>  LoadBalancerConfigUtil.handleException("instancesPerScaleUp in the
>> autoscaler task configuration " +
>> +                        "should be at least 1");
>> +            }
>> +            this.instancesPerScaleUp = instancesPerScaleUp;
>> +            this.instancesPerScaleUpSet = true;
>> +        }
>> +
>> +        public void setMessage_expiry_time(int messageExpiryTime) {
>> +            if (messageExpiryTime < 1) {
>> +
>>  LoadBalancerConfigUtil.handleException("messageExpiryTime in the
>> autoscaler task configuration " +
>> +                        "should be at least 1");
>> +            }
>> +            this.messageExpiryTime = messageExpiryTime;
>> +            this.messageExpiryTimeSet = true;
>> +        }
>> +
>> +        public void setHosts(String hostsStr) {
>> +            // clear all unnecessary values --> property will get
>> overwritten
>> +            hosts = new ArrayList<String>();
>> +            // there can be multiple hosts, let's find out.
>> +            String[] host = hostsStr.split(Constants.HOSTS_DELIMITER);
>> +
>> +            for (String string : host) {
>> +                if (!string.isEmpty()) {
>> +                    this.hosts.add(string);
>> +                }
>> +            }
>> +
>> +        }
>> +
>> +        public void setUrl_suffix(String suffix) {
>> +            // clear all unnecessary values --> property will get
>> overwritten
>> +            //hosts = new ArrayList<String>();
>> +            // there can be multiple hosts, let's find out.
>> +            String[] suffixes = suffix.split(Constants.HOSTS_DELIMITER);
>> +            int count = 0;
>> +            if(suffixes.length == this.hosts.size()) {
>> +                for (String string : suffixes) {
>> +                    if (!string.isEmpty()) {
>> +                        this.urlSuffixes.put(this.hosts.get(count),
>> string);
>> +                        count++;
>> +                    }
>> +                }
>> +
>> +            } else {
>> +                //Error
>> +            }
>> +        }
>> +
>> +        public Map<String, String> getUrl_suffix() {
>> +            return this.urlSuffixes;
>> +        }
>> +
>> +        public void setTenant_range(String range) {
>> +            this.tenantRange = range;
>> +        }
>> +
>> +        public void setSub_domain(String subDomain) {
>> +            this.subDomain = subDomain;
>> +            this.subDomainSet = true;
>> +        }
>> +
>> +        public void setDomain(String domain) {
>> +            this.domain = domain;
>> +        }
>> +
>> +        public boolean equals(ServiceConfiguration config) {
>> +            return this.domain.equals(config.getDomain()) &&
>> +                    this.subDomain.equals(config.getSubDomain());
>> +        }
>> +
>> +        public int hashCode() {
>> +            return new HashCodeBuilder(17, 31). // two randomly chosen
>> prime numbers
>> +                    append(domain).
>> +                    append(subDomain).
>> +                    toHashCode();
>> +        }
>> +
>> +        public double getAlarmingUpperRate() {
>> +            if (alarmingUpperRateSet) {
>> +                return alarmingUpperRate;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.alarmingUpperRateSet) {
>> +                return defaultServiceConfig.alarmingUpperRate;
>> +            }
>> +            return alarmingUpperRate;
>> +        }
>> +
>> +        public double getAlarmingLowerRate() {
>> +            if (alarmingLowerRateSet) {
>> +                return alarmingLowerRate;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.alarmingLowerRateSet) {
>> +                return defaultServiceConfig.alarmingLowerRate;
>> +            }
>> +            return alarmingLowerRate;
>> +        }
>> +
>> +        public double getScaleDownFactor() {
>> +            if (scaleDownFactorSet) {
>> +                return scaleDownFactor;
>> +            } else if (defaultServiceConfig != null &&
>> defaultServiceConfig.scaleDownFactorSet) {
>> +                return defaultServiceConfig.scaleDownFactor;
>> +            }
>> +            return scaleDownFactor;
>> +        }
>> +    }
>> +
>> +    public Map<String, Set<String>> getHostNamesTracker() {
>> +        return hostNamesTracker;
>> +    }
>> +
>> +
>> +    public Map<String, Map<String, ServiceConfiguration>>
>> getServiceConfigurations() {
>> +        return serviceConfigurations;
>> +    }
>> +
>> +
>> +    public Node getRootNode() {
>> +        return rootNode;
>> +    }
>> +
>> +
>> +    public void setRootNode(Node rootNode) {
>> +        this.rootNode = rootNode;
>> +    }
>> +
>> +    public static void setInstance(LoadBalancerConfiguration instance) {
>> +        LoadBalancerConfiguration.instance = instance;
>> +    }
>> +
>> +       public Map<String, List<ServiceConfiguration>>
>> getServiceNameToServiceConfigurations() {
>> +       return serviceNameToServiceConfigurations;
>> +    }
>> +
>> +}
>>
>>
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
>> new file mode 100755
>> index 0000000..c4820a7
>> --- /dev/null
>> +++
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
>> @@ -0,0 +1,356 @@
>> +/**
>> + *  Licensed to the Apache Software Foundation (ASF) under one
>> + *  or more contributor license agreements.  See the NOTICE file
>> + *  distributed with this work for additional information
>> + *  regarding copyright ownership.  The ASF 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
>> +
>> + *  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 org.apache.stratos.load.balancer.conf.structure;
>> +
>> +import java.io.Serializable;
>> +import java.util.ArrayList;
>> +import java.util.Iterator;
>> +import java.util.LinkedHashMap;
>> +import java.util.List;
>> +import java.util.Map;
>> +import java.util.Map.Entry;
>> +
>> +import org.apache.commons.lang.builder.HashCodeBuilder;
>> +
>> +/**
>> + * This is the basic data structure which holds a <i>Nginx</i> formatted
>> configuration file.
>> + *
>> + */
>> +public class Node implements Serializable{
>> +
>> +    private static final long serialVersionUID = 4071569903421115370L;
>> +
>> +    /**
>> +     * Name of this Node element
>> +     */
>> +    private String name;
>> +
>> +    /**
>> +     * Every node can have 0..n child nodes.
>> +     * They are kept in a List.
>> +     */
>> +    private List<Node> childNodes = new ArrayList<Node>();
>> +
>> +    /**
>> +     * Every node can have 0..n properties.
>> +     * They are kept in a Map, in the order they appear.
>> +     * Key: property name
>> +     * Value: property value
>> +     */
>> +    private Map<String, String> properties = new LinkedHashMap<String,
>> String>();
>> +
>> +    public void setChildNodes(List<Node> childNodes) {
>> +        this.childNodes = childNodes;
>> +    }
>> +
>> +    public void setProperties(Map<String, String> properties) {
>> +        this.properties = properties;
>> +    }
>> +
>> +    /**
>> +     * This will convert each child Node of this Node to a String.
>> +     * @return a string which represents child nodes of this node.
>> +     */
>> +    public String childNodesToString(int indentation) {
>> +        StringBuilder childNodesString = new StringBuilder();
>> +        indentation++;
>> +
>> +        for (Node node : childNodes) {
>> +            childNodesString.append(node.toString(indentation)+"\n");
>> +        }
>> +
>> +        return childNodesString.toString();
>> +    }
>> +
>> +    /**
>> +     * This will try to find a child Node of this Node, which has the
>> given name.
>> +     * @param name name of the child node to find.
>> +     * @return child Node object if found or else <code>null</code>.
>> +     */
>> +    public Node findChildNodeByName(String name) {
>> +        for (Node aNode : childNodes) {
>> +            if (aNode.getName().equals(name)) {
>> +                return aNode;
>> +            }
>> +        }
>> +
>> +        return null;
>> +    }
>> +
>> +    /**
>> +     * Returns the name of this Node.
>> +     * @return name of the node.
>> +     */
>> +    public String getName() {
>> +        return name;
>> +    }
>> +
>> +    /**
>> +     * Returns child nodes List of this Node.
>> +     * @return List of Node
>> +     */
>> +    public List<Node> getChildNodes() {
>> +        return childNodes;
>> +    }
>> +
>> +    /**
>> +     * Returns properties Map of this Node.
>> +     * @return Map whose keys and values are String.
>> +     */
>> +    public Map<String, String> getProperties() {
>> +        return properties;
>> +    }
>> +
>> +    /**
>> +     * Returns the value of a given property.
>> +     * @param key name of a property.
>> +     * @return trimmed value if the property is found in this Node, or
>> else <code>null</code>.
>> +     */
>> +    public String getProperty(String key) {
>> +        if (properties.get(key) == null) {
>> +            return null;
>> +        }
>> +        return properties.get(key).trim();
>> +    }
>> +
>> +    /**
>> +     * Returns all the properties of this Node as a String.
>> +     * Key and value of the property is separated by a tab (\t)
>> character and
>> +     * each property is separated by a new line character.
>> +     * @param indentation relative number of tabs
>> +     * @return properties of this node as a String.
>> +     */
>> +    public String propertiesToString(int indentation) {
>> +
>> +        String indent = getIndentation(indentation);
>> +
>> +        StringBuilder sb = new StringBuilder();
>> +        for (Entry<String, String> entry : properties.entrySet()) {
>> +            // hack to get a quick fix in.
>> +            if (!"tenant_id".equals(entry.getKey()) &&
>> !"alias".equals(entry.getKey())) {
>> +                sb.append(indent + entry.getKey() + "\t" +
>> entry.getValue() + ";\n");
>> +            }
>> +        }
>> +        return sb.toString();
>> +    }
>> +
>> +    /**
>> +     * Removes the first occurrence of a node having the given name
>> +     * and returns the removed {@link
>> org.apache.stratos.load.balancer.conf.structure.Node}.
>> +     * @param name name of the child node to be removed.
>> +     * @return removed {@link
>> org.apache.stratos.load.balancer.conf.structure.Node} or else
>> <code>null</code>.
>> +     */
>> +    public Node removeChildNode(String name) {
>> +        Node aNode = findChildNodeByName(name);
>> +
>> +        if(aNode != null){
>> +            if(childNodes.remove(aNode)){
>> +                return aNode;
>> +            }
>> +        }
>> +
>> +        return null;
>> +    }
>> +
>> +    /**
>> +     * Removes the first occurrence of a node equals to the given node.
>> +     * @param node {@link
>> org.apache.stratos.load.balancer.conf.structure.Node} to be removed.
>> +     * @return whether the removal is successful or not.
>> +     */
>> +    public boolean removeChildNode(Node node){
>> +
>> +        return childNodes.remove(node);
>> +    }
>> +
>> +    /**
>> +     * Sets the name of this Node.
>> +     * @param name String to be set as the name.
>> +     */
>> +    public void setName(String name) {
>> +        this.name = name;
>> +    }
>> +
>> +    /**
>> +     * Appends a child node at the end of the List of child nodes of
>> this Node, if
>> +     * a similar node is not already present as a child node.
>> +     * @param aNode child Node to be appended.
>> +     */
>> +    public void appendChild(Node aNode) {
>> +        if (aNode != null && !nodeAlreadyPresent(aNode)) {
>> +            childNodes.add(aNode);
>> +        }
>> +    }
>> +
>> +    /**
>> +     * Adds a new property to properties Map of this Node if and only if
>> +     * key is not <code>null</code>.
>> +     * @param key name of the property to be added.
>> +     * @param value value of the property to be added.
>> +     */
>> +    public void addProperty(String key, String value) {
>> +        if (key != null) {
>> +            properties.put(key, value);
>> +        }
>> +    }
>> +
>> +    /**
>> +     * Convert this Node to a String which is in <i>Nginx</i> format.
>> +     * <br/>
>> +     * Sample:
>> +     * <br></br>
>> +     * <code>
>> +     * ij {
>> +     * <br/>
>> +     * klm n;
>> +     * <br/>
>> +     * pq {
>> +     * <br/>
>> +     * rst u;
>> +     * <br/>
>> +     * }
>> +     * <br/>
>> +     * }
>> +     * <br/>
>> +     * </code>
>> +     */
>> +    public String toString() {
>> +
>> +        String nodeString =
>> +                getName()+" {\n" +
>> +                (propertiesToString(1)) +
>> +                (childNodesToString(1)) +
>> +                "}";
>> +
>> +        return nodeString;
>> +    }
>> +
>> +    public boolean equals(Object node) {
>> +
>> +        if(node instanceof Node){
>> +            return this.getName().equals(((Node) node).getName()) &&
>> +                    isIdenticalProperties(this.getProperties(), ((Node)
>> node).getProperties()) &&
>> +                    isIdenticalChildren(this.getChildNodes(), ((Node)
>> node).getChildNodes());
>> +        }
>> +
>> +        return false;
>> +
>> +    }
>> +
>> +    public int hashCode() {
>> +        return new HashCodeBuilder(17, 31). // two randomly chosen prime
>> numbers
>> +            append(name).
>> +            append(properties).
>> +            append(childNodes).
>> +            toHashCode();
>> +    }
>> +
>> +    private boolean isIdenticalChildren(List<Node> childNodes1,
>> List<Node> childNodes2) {
>> +
>> +        if(childNodes1.size() != childNodes2.size()){
>> +            return false;
>> +        }
>> +
>> +        for (Node node1 : childNodes1) {
>> +            int i=0;
>> +            for (Node node2 : childNodes2) {
>> +
>> +                i++;
>> +                if(node1.equals(node2)){
>> +                    break;
>> +                }
>> +
>> +                if(i == childNodes1.size()){
>> +                    return false;
>> +                }
>> +
>> +            }
>> +        }
>> +
>> +        return true;
>> +    }
>> +
>> +    private boolean nodeAlreadyPresent(Node aNode){
>> +
>> +        for(Node node : this.childNodes){
>> +            if(node.equals(aNode)){
>> +                return true;
>> +            }
>> +        }
>> +
>> +        return false;
>> +    }
>> +
>> +    private boolean isIdenticalProperties(Map<String, String> map1,
>> +        Map<String, String> map2) {
>> +
>> +        if(map1.size() != map2.size()){
>> +            return false;
>> +        }
>> +
>> +        for (Iterator<Entry<String, String>> iterator1 =
>> map1.entrySet().iterator(); iterator1.hasNext();) {
>> +            Entry<String, String> entry1 = (Entry<String, String>)
>> iterator1.next();
>> +
>> +            int i=0;
>> +
>> +            for(Iterator<Entry<String, String>> iterator2 =
>> map2.entrySet().iterator(); iterator2.hasNext();) {
>> +                Entry<String, String> entry2 = (Entry<String, String>)
>> iterator2.next();
>> +
>> +                i++;
>> +
>> +                if((entry1.getKey().equals(entry2.getKey()) &&
>> +                        entry1.getValue().equals(entry2.getValue()))){
>> +
>> +                    break;
>> +                }
>> +
>> +                if(i == map1.size()){
>> +                    return false;
>> +                }
>> +
>> +            }
>> +        }
>> +
>> +        return true;
>> +    }
>> +
>> +    private String toString(int indentation){
>> +
>> +        String indent = getIndentation(indentation-1);
>> +
>> +        String nodeString =
>> +                indent + getName()+" {\n" +
>> +                (propertiesToString(indentation)) +
>> +                (childNodesToString(indentation)) +
>> +                indent + "}";
>> +
>> +        return nodeString;
>> +    }
>> +
>> +    private String getIndentation(int tabs){
>> +
>> +        StringBuilder indent = new StringBuilder("");
>> +
>> +        for (int i = 0; i < tabs; i++) {
>> +            indent.append("\t");
>> +        }
>> +
>> +        return indent.toString();
>> +    }
>> +
>> +}
>>
>>
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
>> new file mode 100755
>> index 0000000..168492d
>> --- /dev/null
>> +++
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
>> @@ -0,0 +1,140 @@
>> +/**
>> + *  Licensed to the Apache Software Foundation (ASF) under one
>> + *  or more contributor license agreements.  See the NOTICE file
>> + *  distributed with this work for additional information
>> + *  regarding copyright ownership.  The ASF 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
>> +
>> + *  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 org.apache.stratos.load.balancer.conf.structure;
>> +
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +import org.apache.stratos.load.balancer.conf.util.Constants;
>> +
>> +/**
>> + * This responsible for build up a Node object from a given content.
>> + * Every closing brace should be in a new line.
>> + */
>> +public class NodeBuilder {
>> +
>> +    private static final Log log = LogFactory.getLog(NodeBuilder.class);
>> +
>> +    /**
>> +     * This method is useful when you do not have a root node in your
>> content.
>> +     * @param aNode
>> +     *            Node object whose name set.
>> +     * @param content
>> +     *            should be something similar to following.
>> +     *
>> +     *            abc d;
>> +     *            efg h;
>> +     *            # comment
>> +     *            ij { # comment
>> +     *              klm n;
>> +     *
>> +     *              pq {
>> +     *                  rst u;
>> +     *              }
>> +     *            }
>> +     *
>> +     * @return fully constructed Node
>> +     */
>> +    public static Node buildNode(Node aNode, String content) {
>> +
>> +       if(content == null || content.isEmpty()){
>> +               return aNode;
>> +       }
>> +
>> +        String[] lines = content.split("\n");
>> +
>> +        for (int i = 0; i < lines.length; i++) {
>> +            String line = lines[i].trim();
>> +
>> +            // avoid line comments
>> +            if (!line.startsWith(Constants.NGINX_COMMENT)) {
>> +
>> +                // skip comments in-line
>> +                if(line.contains(Constants.NGINX_COMMENT)){
>> +                    line = line.substring(0,
>> line.indexOf(Constants.NGINX_COMMENT));
>> +                }
>> +
>> +                // another node is detected and it is not a variable
>> starting from $
>> +                if (line.contains(Constants.NGINX_NODE_START_BRACE) &&
>> +                        !line.contains(Constants.NGINX_VARIABLE)) {
>> +
>> +                    try {
>> +                        Node childNode = new Node();
>> +                        childNode.setName(line.substring(0,
>> line.indexOf(Constants.NGINX_NODE_START_BRACE)).trim());
>> +
>> +                        StringBuilder sb = new StringBuilder();
>> +
>> +                        int matchingBraceTracker = 1;
>> +
>> +                        while
>> (!line.contains(Constants.NGINX_NODE_END_BRACE) || matchingBraceTracker !=
>> 0) {
>> +                            i++;
>> +                            if (i == lines.length) {
>> +                                break;
>> +                            }
>> +                            line = lines[i];
>> +                            if
>> (line.contains(Constants.NGINX_NODE_START_BRACE)) {
>> +                                matchingBraceTracker++;
>> +                            }
>> +                            if
>> (line.contains(Constants.NGINX_NODE_END_BRACE)) {
>> +                                matchingBraceTracker--;
>> +                            }
>> +                            sb.append(line + "\n");
>> +                        }
>> +
>> +                        childNode = buildNode(childNode, sb.toString());
>> +                                               if (aNode == null) {
>> +                                                       aNode = childNode;
>> +                                               } else {
>> +
>> aNode.appendChild(childNode);
>> +                                               }
>> +
>> +                    } catch (Exception e) {
>> +                        String msg = "Malformatted element is defined in
>> the configuration file. [" +
>> +                                i + "] \n";
>> +                        log.error(msg , e);
>> +                        throw new RuntimeException(msg + line, e);
>> +                    }
>> +
>> +                }
>> +                // this is a property
>> +                else {
>> +                    if (!line.isEmpty() &&
>> !Constants.NGINX_NODE_END_BRACE.equals(line)) {
>> +                        String[] prop =
>> line.split(Constants.NGINX_SPACE_REGEX);
>> +                        String value = line.substring(prop[0].length(),
>> line.indexOf(Constants.NGINX_LINE_DELIMITER)).trim();
>> +                        try {
>> +                            aNode.addProperty(prop[0], value);
>> +                        } catch (Exception e) {
>> +                            String msg = "Malformatted property is
>> defined in the configuration file. [" +
>> +                                    i + "] \n";
>> +                            log.error(msg, e);
>> +                            throw new RuntimeException(msg + line, e);
>> +                        }
>> +                    }
>> +                }
>> +
>> +            }
>> +        }
>> +
>> +        return aNode;
>> +
>> +    }
>> +
>> +    public static Node buildNode(String content) {
>> +           return buildNode(null, content);
>> +    }
>> +}
>>
>>
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
>> new file mode 100755
>> index 0000000..31e172d
>> --- /dev/null
>> +++
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
>> @@ -0,0 +1,50 @@
>> +/**
>> + *  Licensed to the Apache Software Foundation (ASF) under one
>> + *  or more contributor license agreements.  See the NOTICE file
>> + *  distributed with this work for additional information
>> + *  regarding copyright ownership.  The ASF 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
>> +
>> + *  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 org.apache.stratos.load.balancer.conf.util;
>> +
>> +/**
>> + * This keeps the element names used in loadbalancer.conf file
>> + */
>> +public class Constants {
>> +
>> +    public static final String LOAD_BALANCER_ELEMENT = "loadbalancer";
>> +    public static final String SERVICES_ELEMENT = "services";
>> +    public static final String DEFAULTS_ELEMENT = "defaults";
>> +    public static final String HOSTS_ELEMENT = "hosts";
>> +    public static final String HOSTS_DELIMITER = ",";
>> +    public static final String DOMAIN_ELEMENT = "domains";
>> +    public static final String TENANT_RANGE_ELEMENT = "tenant_range";
>> +    public static final String SUB_DOMAIN_ELEMENT = "sub_domain";
>> +    public static final String TENANT_RANGE_DELIMITER = "-";
>> +    public static final String UNLIMITED_TENANT_RANGE = "*";
>> +    public static final String AUTOSCALER_ENABLE_ELEMENT =
>> "enable_autoscaler";
>> +    public static final String SUB_DOMAIN_DELIMITER = "#";
>> +    public static final String DEFAULT_SUB_DOMAIN = "__$default";
>> +
>> +    /* Nginx format related constants */
>> +
>> +    public static final String NGINX_COMMENT = "#";
>> +    public static final String NGINX_NODE_START_BRACE = "{";
>> +    public static final String NGINX_NODE_END_BRACE = "}";
>> +    public static final String NGINX_VARIABLE = "${";
>> +    public static final String NGINX_LINE_DELIMITER = ";";
>> +    public static final String NGINX_SPACE_REGEX = "[\\s]+";
>> +
>> +
>> +}
>>
>>
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
>> new file mode 100755
>> index 0000000..ecd952a
>> --- /dev/null
>> +++
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
>> @@ -0,0 +1,161 @@
>> +/**
>> + *  Licensed to the Apache Software Foundation (ASF) under one
>> + *  or more contributor license agreements.  See the NOTICE file
>> + *  distributed with this work for additional information
>> + *  regarding copyright ownership.  The ASF 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
>> +
>> + *  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 org.apache.stratos.load.balancer.conf.util;
>> +
>> +import java.util.Collection;
>> +import java.util.HashMap;
>> +import java.util.List;
>> +import java.util.Map;
>> +
>> +import org.apache.synapse.endpoints.algorithms.AlgorithmContext;
>> +import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
>> +
>> +/**
>> + * For each unique host name defined in loadbalancer configuration,
>> we'll generate
>> + * this object.
>> + */
>> +public class HostContext {
>> +
>> +    /**
>> +     * A unique identifier to identify this {@link #HostContext()}
>> +     */
>> +    private String hostName;
>> +
>> +    /**
>> +     * Key - tenant id
>> +     * Value - <code>TenantDomainContext</code> of the corresponding
>> tenant
>> +     */
>> +    private Map<Integer, TenantDomainContext>
>> tenantIdToTenantDomainContextMap = new HashMap<Integer,
>> TenantDomainContext>();
>> +
>> +    /**
>> +     * AlgorithmContext of this host
>> +     */
>> +    private AlgorithmContext algorithmContext;
>> +
>> +    /**
>> +     * Load balance algorithm of this host
>> +     */
>> +    private LoadbalanceAlgorithm algorithm;
>> +
>> +    private String urlSuffix;
>> +
>> +    public HostContext(String hostName) {
>> +        this.hostName = hostName;
>> +    }
>> +
>> +    public void addTenantDomainContexts(List<TenantDomainContext> ctxts)
>> {
>> +
>> +        for (TenantDomainContext tenantDomainContext : ctxts) {
>> +
>>  tenantIdToTenantDomainContextMap.put(tenantDomainContext.getTenantId(),
>> tenantDomainContext);
>> +        }
>> +    }
>> +
>> +    @Deprecated
>> +    public void addTenantDomainContext(TenantDomainContext ctxt) {
>> +        tenantIdToTenantDomainContextMap.put(ctxt.getTenantId(), ctxt);
>> +    }
>> +
>> +    public TenantDomainContext getTenantDomainContext(int tenantId) {
>> +        return tenantIdToTenantDomainContextMap.get(tenantId);
>> +    }
>> +
>> +    /**
>> +     * Returns all the {@link
>> org.apache.stratos.load.balancer.conf.util.TenantDomainContext} entries.
>> +     */
>> +    public Collection<TenantDomainContext> getTenantDomainContexts() {
>> +        return tenantIdToTenantDomainContextMap.values();
>> +    }
>> +
>> +    /**
>> +     * Given a tenant id, this will return its domain.
>> +     * @param tenantId
>> +     * @return domain if this tenant has a dedicated one, it will be
>> returned.
>> +     * If not, and there's a default (*) domain, it will be returned.
>> +     * If neither of the above is defined, null will be returned.
>> +     */
>> +    public String getDomainFromTenantId(int tenantId) {
>> +        if (tenantIdToTenantDomainContextMap.get(tenantId) == null) {
>> +            // if there's no specific domain for this tenant, we will
>> redirect it to the default
>> +            // cluster
>> +
>> +            if(tenantIdToTenantDomainContextMap.get(0) == null){
>> +                return null;
>> +            }
>> +
>> +            return tenantIdToTenantDomainContextMap.get(0).getDomain();
>> +        }
>> +
>> +        return
>> tenantIdToTenantDomainContextMap.get(tenantId).getDomain();
>> +    }
>> +
>> +    /**
>> +     * Given a tenant id, this will return its sub domain.
>> +     * @param tenantId
>> +     * @return sub_domain if this tenant has a dedicated one, it will be
>> returned.
>> +     * If not, and there's a default (*) sub domain, it will be returned.
>> +     * If neither of the above is defined, null will be returned.
>> +     */
>> +    public String getSubDomainFromTenantId(int tenantId) {
>> +        if (tenantIdToTenantDomainContextMap.get(tenantId) == null) {
>> +            // if there's no specific domain for this tenant, we will
>> redirect it to the default
>> +            // cluster
>> +
>> +            if(tenantIdToTenantDomainContextMap.get(0) == null){
>> +                return null;
>> +            }
>> +
>> +            return
>> tenantIdToTenantDomainContextMap.get(0).getSubDomain();
>> +        }
>> +
>> +        return
>> tenantIdToTenantDomainContextMap.get(tenantId).getSubDomain();
>> +    }
>> +
>> +    public String getHostName() {
>> +        return hostName;
>> +    }
>> +
>> +    public LoadbalanceAlgorithm getAlgorithm() {
>> +        return algorithm;
>> +    }
>> +
>> +    public AlgorithmContext getAlgorithmContext() {
>> +        return algorithmContext;
>> +    }
>> +
>> +    public void setAlgorithmContext(AlgorithmContext algorithmContext) {
>> +        this.algorithmContext = algorithmContext;
>> +    }
>> +
>> +    public void setAlgorithm(LoadbalanceAlgorithm algorithm) {
>> +        this.algorithm = algorithm;
>> +    }
>> +
>> +    public Map<Integer, TenantDomainContext>
>> getTenantIdToTenantDomainContextMap() {
>> +        return tenantIdToTenantDomainContextMap;
>> +    }
>> +
>> +    public void setUrlSuffix(String suffix)  {
>> +        this.urlSuffix = suffix;
>> +    }
>> +
>> +    public String getUrlSuffix() {
>> +        return this.urlSuffix;
>> +    }
>> +
>> +}
>>
>>
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
>> new file mode 100755
>> index 0000000..fe432c9
>> --- /dev/null
>> +++
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
>> @@ -0,0 +1,305 @@
>> +/**
>> + *  Licensed to the Apache Software Foundation (ASF) under one
>> + *  or more contributor license agreements.  See the NOTICE file
>> + *  distributed with this work for additional information
>> + *  regarding copyright ownership.  The ASF 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
>> +
>> + *  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 org.apache.stratos.load.balancer.conf.util;
>> +
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +import org.apache.synapse.SynapseException;
>> +import sun.misc.BASE64Encoder;
>> +
>> +import java.io.File;
>> +import java.io.FileInputStream;
>> +import java.io.IOException;
>> +import java.io.InputStream;
>> +import java.util.ArrayList;
>> +import java.util.List;
>> +
>> +/**
>> + * Utility methods for Autoscale mediator
>> + */
>> +public final class LoadBalancerConfigUtil {
>> +
>> +    private static final Log log =
>> LogFactory.getLog(LoadBalancerConfigUtil.class);
>> +
>> +    private LoadBalancerConfigUtil() {
>> +    }
>> +
>> +    /**
>> +     * handles the exception
>> +     *
>> +     * @param msg
>> +     *            exception message
>> +     */
>> +    public static void handleException(String msg) {
>> +        log.error(msg);
>> +        throw new RuntimeException(msg);
>> +    }
>> +
>> +    /**
>> +     * handles the exception
>> +     *
>> +     * @param msg
>> +     *            exception message
>> +     * @param e
>> +     *            exception
>> +     */
>> +    public static void handleException(String msg, Exception e) {
>> +        log.error(msg, e);
>> +        throw new SynapseException(msg, e);
>> +    }
>> +
>> +    /**
>> +     * Replaces the variables
>> +     *
>> +     * @param text
>> +     *            input string
>> +     * @return output String
>> +     */
>> +    public static String replaceVariables(String text) {
>> +        int indexOfStartingChars;
>> +        int indexOfClosingBrace;
>> +
>> +        // The following condition deals with properties.
>> +        // Properties are specified as ${system.property},
>> +        // and are assumed to be System properties
>> +        if ((indexOfStartingChars = text.indexOf("${")) != -1 &&
>> +            (indexOfClosingBrace = text.indexOf("}")) != -1) { // Is a
>> property used?
>> +            String var = text.substring(indexOfStartingChars + 2,
>> indexOfClosingBrace);
>> +
>> +            String propValue = System.getProperty(var);
>> +            if (propValue == null) {
>> +                propValue = System.getenv(var);
>> +            }
>> +            if (propValue != null) {
>> +                text =
>> +                       text.substring(0, indexOfStartingChars) +
>> propValue +
>> +                               text.substring(indexOfClosingBrace + 1);
>> +            }
>> +        }
>> +        return text;
>> +    }
>> +
>> +    public static String getUserData(String payloadFileName) {
>> +        String userData = null;
>> +        try {
>> +            File file = new File(payloadFileName);
>> +            if (!file.exists()) {
>> +                handleException("Payload file " + payloadFileName + "
>> does not exist");
>> +            }
>> +            if (!file.canRead()) {
>> +                handleException("Payload file " + payloadFileName + "
>> does cannot be read");
>> +            }
>> +            byte[] bytes = LoadBalancerConfigUtil.getBytesFromFile(file);
>> +            if (bytes != null) {
>> +                BASE64Encoder encoder = new BASE64Encoder();
>> +                userData = encoder.encode(bytes);
>> +            }
>> +        } catch (Exception e) {
>> +            LoadBalancerConfigUtil.handleException("Cannot read data
>> from payload file " +
>> +                                                   payloadFileName, e);
>> +
>> +        }
>> +        return userData;
>> +    }
>> +
>> +    /**
>> +     * Returns the contents of the file in a byte array
>> +     *
>> +     * @param file
>> +     *            - Input File
>> +     * @return Bytes from the file
>> +     * @throws java.io.IOException
>> +     *             , if retrieving the file contents failed.
>> +     */
>> +    public static byte[] getBytesFromFile(File file) throws IOException {
>> +        if (!file.exists()) {
>> +            log.error("Payload file " + file.getAbsolutePath() + " does
>> not exist");
>> +            return null;
>> +        }
>> +        InputStream is = new FileInputStream(file);
>> +        byte[] bytes;
>> +
>> +        try {
>> +            // Get the size of the file
>> +            long length = file.length();
>> +
>> +            // You cannot create an array using a long type.
>> +            // It needs to be an int type.
>> +            // Before converting to an int type, check
>> +            // to ensure that file is not larger than Integer.MAX_VALUE.
>> +            if (length > Integer.MAX_VALUE) {
>> +                if (log.isDebugEnabled()) {
>> +                    log.debug("File is too large");
>> +                }
>> +            }
>> +
>> +            // Create the byte array to hold the data
>> +            bytes = new byte[(int) length];
>> +
>> +            // Read in the bytes
>> +            int offset = 0;
>> +            int numRead;
>> +            while (offset < bytes.length &&
>> +                   (numRead = is.read(bytes, offset, bytes.length -
>> offset)) >= 0) {
>> +                offset += numRead;
>> +            }
>> +
>> +            // Ensure all the bytes have been read in
>> +            if (offset < bytes.length) {
>> +                throw new IOException("Could not completely read file "
>> + file.getName());
>> +            }
>> +        } finally {
>> +            // Close the input stream and return bytes
>> +            is.close();
>> +        }
>> +
>> +        return bytes;
>> +    }
>> +
>> +    /**
>> +     * @deprecated
>> +     *             Extract the domain part given a string which is in
>> +     *             &lt;sub_domain&gt;#&lt;domain&gt; format.
>> +     * @param str
>> +     *            in &lt;sub_domain&gt;#&lt;domain&gt; format.
>> +     * @return the domain part. If # is not present this will return the
>> trimmed
>> +     *         input string.
>> +     */
>> +    public static String getDomain(String str) {
>> +        str = str.trim();
>> +        if (!str.contains(Constants.SUB_DOMAIN_DELIMITER)) {
>> +            return str;
>> +        }
>> +        return str.substring(str.indexOf(Constants.SUB_DOMAIN_DELIMITER)
>> + 1);
>> +    }
>> +
>> +    /**
>> +     * @deprecated
>> +     *             Extract the sub_domain part given a string which is in
>> +     *             &lt;sub_domain&gt;#&lt;domain&gt; format.
>> +     * @param str
>> +     *            in &lt;sub_domain&gt;#&lt;domain&gt; format.
>> +     * @return the sub_domain part. If # is not present this will return
>> <code>null</code>.
>> +     */
>> +    public static String getSubDomain(String str) {
>> +        str = str.trim();
>> +        if (!str.contains(Constants.SUB_DOMAIN_DELIMITER)) {
>> +            return null;
>> +        }
>> +        return str.substring(0,
>> str.indexOf(Constants.SUB_DOMAIN_DELIMITER));
>> +    }
>> +
>> +    // public static EC2InstanceManager createEC2InstanceManager(String
>> accessKey,
>> +    // String secretKey,
>> +    // String instanceMgtEPR) {
>> +    // AWSCredentials awsCredentials = new
>> BasicAWSCredentials(accessKey, secretKey);
>> +    // AmazonEC2Client ec2Client = new AmazonEC2Client(awsCredentials);
>> +    // ec2Client.setEndpoint(instanceMgtEPR);
>> +    // return new EC2InstanceManager(ec2Client);
>> +    // }
>> +
>> +    public static List<TenantDomainContext>
>> getTenantDomainContexts(String tenantRange, String domain, String
>> subDomain) {
>> +
>> +        List<TenantDomainContext> ctxts = new
>> ArrayList<TenantDomainContext>();
>> +        List<Integer> tenantIds = getTenantIds(tenantRange);
>> +
>> +        // iterate through all tenant ids under this host
>> +        for (Integer tId : tenantIds) {
>> +
>> +            // create a new TenantDomainContext
>> +            TenantDomainContext tenantCtxt =
>> +                                             new TenantDomainContext(
>> +                                                                     tId,
>> +
>> domain,
>> +
>> subDomain);
>> +            // add it to the list
>> +            ctxts.add(tenantCtxt);
>> +        }
>> +
>> +        return ctxts;
>> +
>> +    }
>> +
>> +    /**
>> +     * This method will read the tenant range string and return a list
>> of tenant ids
>> +     * which is derived from tenant range string.
>> +     *
>> +     * @param tenantRange
>> +     * @return list of tenant ids.
>> +     */
>> +    public static List<Integer> getTenantIds(String tenantRange) {
>> +
>> +        List<Integer> tenantIds = new ArrayList<Integer>();
>> +
>> +        String[] parsedLine = tenantRange.trim().split("-");
>> +
>> +        if (parsedLine[0].equalsIgnoreCase("*")) {
>> +            tenantIds.add(0);
>> +
>> +               } else if (parsedLine.length == 1) {
>> +                       // if there aren't any hyphens in the string, try
>> to see whether
>> +                       // this is a list of ids
>> +                       parsedLine = tenantRange.trim().split(",");
>> +
>> +                       // if there aren't any commas in the string, we
>> assume this to be a
>> +                       // one single integer.
>> +                       if (parsedLine.length == 1) {
>> +                               try {
>> +                                       int tenantId =
>> Integer.parseInt(tenantRange);
>> +                                       tenantIds.add(tenantId);
>> +
>> +                               } catch (NumberFormatException e) {
>> +                                       String msg = "Invalid tenant
>> range is specified : "
>> +                                                       + tenantRange;
>> +                                       log.error(msg, e);
>> +                                       throw new RuntimeException(msg,
>> e);
>> +                               }
>> +                       } else {
>> +                               for (int i = 0; i < parsedLine.length;
>> i++) {
>> +                                       int tenantId =
>> Integer.parseInt(parsedLine[i]);
>> +                                       tenantIds.add(tenantId);
>> +                               }
>> +                       }
>> +               } else if (parsedLine.length == 2) {
>> +            try {
>> +
>> +                int startIndex = Integer.parseInt(parsedLine[0]);
>> +                int endIndex = Integer.parseInt(parsedLine[1]);
>> +
>> +                for (int tenantId = startIndex; tenantId <= endIndex;
>> tenantId++) {
>> +
>> +                    tenantIds.add(tenantId);
>> +                }
>> +
>> +            } catch (NumberFormatException e) {
>> +                String msg = "Invalid tenant range is specified : " +
>> tenantRange;
>> +                log.error(msg, e);
>> +                throw new RuntimeException(msg, e);
>> +            }
>> +
>> +        } else {
>> +            String msg = "Invalid tenant range is specified : " +
>> tenantRange;
>> +            log.error(msg);
>> +            throw new RuntimeException(msg);
>> +        }
>> +
>> +        return tenantIds;
>> +    }
>> +
>> +}
>> \ No newline at end of file
>>
>>
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
>> new file mode 100755
>> index 0000000..33162c5
>> --- /dev/null
>> +++
>> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
>> @@ -0,0 +1,80 @@
>> +/**
>> + *  Licensed to the Apache Software Foundation (ASF) under one
>> + *  or more contributor license agreements.  See the NOTICE file
>> + *  distributed with this work for additional information
>> + *  regarding copyright ownership.  The ASF 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
>> +
>> + *  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 org.apache.stratos.load.balancer.conf.util;
>> +
>> +/**
>> + * This object will hold all the data related to a tenant.
>> + */
>> +public class TenantDomainContext {
>> +
>> +    /**
>> +     * this is the unique identifier for this object
>> +     */
>> +    private int tenantId;
>> +
>> +    /**
>> +     * Domain, which this tenant belongs to.
>> +     */
>> +    private String domain;
>> +
>> +    /**
>> +     * Sub domain, which this tenant belongs to.
>> +     */
>> +    private String subDomain;
>> +
>> +    public TenantDomainContext(int tenantId, String domain, String
>> subDomain) {
>> +        this.tenantId = tenantId;
>> +        this.domain = domain;
>> +        this.subDomain = subDomain;
>> +    }
>> +
>> +
>> +    /** Getters and Setters **/
>> +
>> +    public int getTenantId() {
>> +        return tenantId;
>> +    }
>> +
>> +    public void setTenantId(int tenantId) {
>> +        this.tenantId = tenantId;
>> +    }
>> +
>> +    public String getDomain() {
>> +        return domain;
>> +    }
>> +
>> +    public void setDomain(String domain) {
>> +        this.domain = domain;
>> +    }
>> +
>> +    public String getSubDomain() {
>> +        return subDomain;
>> +    }
>> +
>> +    public void setSubDomain(String subDomain) {
>> +        this.subDomain = subDomain;
>> +    }
>> +
>> +
>> +    /** End of Getters and Setters **/
>> +
>> +
>> +
>> +
>> +}
>>
>>
>> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
>> b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
>> new file mode 100755
>> index 0000000..c94b54c
>> --- /dev/null
>> +++
>> b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
>> @@ -0,0 +1,48 @@
>> +/**
>> + *  Licensed to the Apache Software Foundation (ASF) under one
>> + *  or more contributor license agreements.  See the NOTICE file
>> + *  distributed with this work for additional information
>> + *  regarding copyright ownership.  The ASF 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
>> +
>> + *  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 org.apache.stratos.load.balancer.test;
>> +
>> +import java.util.Arrays;
>> +import java.util.List;
>> +
>> +import org.apache.stratos.load.balancer.conf.util.LoadBalancerConfigUtil;
>> +
>> +import junit.framework.TestCase;
>> +
>> +public class LoadBalancerConfigUtilTest extends TestCase {
>> +
>> +    private List<Integer> tenantList1 = Arrays.asList(1,2,3);
>> +    private List<Integer> tenantList2 = Arrays.asList(1,6,3,4);
>> +    private List<Integer> tenantList3 = Arrays.asList(43);
>> +    private List<Integer> tenantList4 = Arrays.asList(0);
>> +
>> +    @Override
>> +    protected void setUp() throws Exception {
>> +
>> +    }
>> +
>> +    public final void testGetTenantIds() {
>> +
>> +        assertEquals(tenantList1,
>> LoadBalancerConfigUtil.getTenantIds("1-3"));
>> +        assertEquals(tenantList2,
>> LoadBalancerConfigUtil.getTenantIds("1,6,3,4"));
>> +        assertEquals(tenantList3,
>> LoadBalancerConfigUtil.getTenantIds("43"));
>> +        assertEquals(tenantList4,
>> LoadBalancerConfigUtil.getTenantIds("*"));
>> +    }
>> +
>> +}
>>
>>

Re: [2/3] git commit: Added load balancer configuration parser and its test cases from lb.common component

Posted by Nirmal Fernando <ni...@gmail.com>.
Imesh,

These should have been git copied/moved.
 On Nov 10, 2013 10:40 PM, <im...@apache.org> wrote:

> Added load balancer configuration parser and its test cases from lb.common
> component
>
>
> Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo
> Commit:
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/32565547
> Tree:
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/32565547
> Diff:
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/32565547
>
> Branch: refs/heads/master
> Commit: 32565547050e49e89dd8b76e1fcace9504e89c69
> Parents: 59811f9
> Author: Imesh Gunaratne <im...@apache.org>
> Authored: Sun Nov 10 22:37:36 2013 +0530
> Committer: Imesh Gunaratne <im...@apache.org>
> Committed: Sun Nov 10 22:37:36 2013 +0530
>
> ----------------------------------------------------------------------
>  .../conf/LoadBalancerConfiguration.java         | 1202 ++++++++++++++++++
>  .../load/balancer/conf/structure/Node.java      |  356 ++++++
>  .../balancer/conf/structure/NodeBuilder.java    |  140 ++
>  .../load/balancer/conf/util/Constants.java      |   50 +
>  .../load/balancer/conf/util/HostContext.java    |  161 +++
>  .../conf/util/LoadBalancerConfigUtil.java       |  305 +++++
>  .../balancer/conf/util/TenantDomainContext.java |   80 ++
>  .../test/LoadBalancerConfigUtilTest.java        |   48 +
>  .../test/LoadBalancerConfigurationTest.java     |  169 +++
>  .../load/balancer/test/NodeBuilderTest.java     |  123 ++
>  .../src/test/resources/loadbalancer.conf        |   84 ++
>  .../src/test/resources/loadbalancer1.conf       |   60 +
>  .../src/test/resources/loadbalancer2.conf       |   50 +
>  .../src/test/resources/testng.xml               |   29 +
>  14 files changed, 2857 insertions(+)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
> ----------------------------------------------------------------------
> diff --git
> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
> new file mode 100755
> index 0000000..747ba5b
> --- /dev/null
> +++
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
> @@ -0,0 +1,1202 @@
> +/**
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF 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
> +
> + *  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 org.apache.stratos.load.balancer.conf;
> +
> +import org.apache.commons.lang.builder.HashCodeBuilder;
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +import org.apache.synapse.commons.util.PropertyHelper;
> +import org.apache.stratos.load.balancer.conf.structure.Node;
> +import org.apache.stratos.load.balancer.conf.structure.NodeBuilder;
> +import org.apache.stratos.load.balancer.conf.util.Constants;
> +import org.apache.stratos.load.balancer.conf.util.HostContext;
> +import org.apache.stratos.load.balancer.conf.util.LoadBalancerConfigUtil;
> +import org.apache.stratos.load.balancer.conf.util.TenantDomainContext;
> +import java.io.*;
> +import java.net.URL;
> +import java.util.*;
> +
> +/**
> + * Data object which hold configuration data of the load analyzer task
> + */
> +@SuppressWarnings("unused")
> +public class LoadBalancerConfiguration implements Serializable {
> +
> +    protected static final long serialVersionUID = -5553545217542808233L;
> +
> +    private static final Log log =
> LogFactory.getLog(LoadBalancerConfiguration.class);
> +
> +    /**
> +     * This map is there to speed up the lookup time.
> +     * Key: domain
> +     * <p/>
> +     * Value: A map whose key is sub domain and value is
> ServiceConfiguration
> +     */
> +    private Map<String, Map<String, ServiceConfiguration>>
> serviceConfigurations =
> +            new HashMap<String, Map<String, ServiceConfiguration>>();
> +
> +    /**
> +     * Key - host name
> +     * Value - {@link
> org.apache.stratos.load.balancer.conf.util.HostContext}
> +     */
> +    private transient Map<String, HostContext> hostCtxt = new
> HashMap<String, HostContext>();
> +
> +    /**
> +     * This map is there to speed up the lookup time.
> +     * Key: service name/cartridge type (Stratos2). NOTE: that this is
> not the service cluster domain.
> +     * Value: list of {@link
> org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration.ServiceConfiguration}
> - corresponding objects under a service name.
> +     */
> +       private Map<String, List<ServiceConfiguration>>
> serviceNameToServiceConfigurations =
> +                       new HashMap<String, List<ServiceConfiguration>>();
> +
> +    /**
> +     * This list will be used to identify host name duplications among
> different services.
> +     * Within a service there can be duplications, but among different
> services you can't have duplications.
> +     * Key - service name
> +     * Value - hosts under the respective service.
> +     */
> +    private Map<String, Set<String>> hostNamesTracker = new
> HashMap<String, Set<String>>();
> +
> +    protected ServiceConfiguration defaultServiceConfig;
> +    protected LBConfiguration lbConfig;
> +
> +    /**
> +     * LBConfig file as a String
> +     */
> +    protected String lbConfigString;
> +
> +    /**
> +     * Root node object for loadbalancer.conf
> +     */
> +    protected Node rootNode;
> +
> +    private LoadBalancerConfiguration(){
> +        init(System.getProperty("loadbalancer.conf"));
> +    }
> +
> +    private static LoadBalancerConfiguration instance ;
> +
> +    public static LoadBalancerConfiguration getInstance(){
> +        if(instance == null){
> +            instance = new LoadBalancerConfiguration();
> +        }
> +        return instance;
> +    }
> +
> +    /**
> +     * Sample loadbalancer.conf:
> +     * <p/>
> +     * loadbalancer {
> +     * # minimum number of load balancer instances
> +     * instances           1;
> +     * # whether autoscaling enable or not
> +     * enable_autoscaler   true;
> +     * # End point reference of the Autoscaler Service
> +     * autoscaler_service_epr
> https://10.100.3.81:9443/services/AutoscalerService/;
> +     * # interval between two task executions in milliseconds
> +     * autoscaler_task_interval 1000;
> +     * # after an instance booted up, task will wait till this much of
> time and let the server started up
> +     * server_startup_delay 15000;
> +     * }
> +     * <p/>
> +     * services {
> +     * defaults {
> +     * min_app_instances       1;
> +     * max_app_instances       5;
> +     * queue_length_per_node   400;
> +     * rounds_to_average       10;
> +     * instances_per_scale_up  1;
> +     * message_expiry_time     60000;
> +     * }
> +     * <p/>
> +     * appserver {
> +     * hosts                   appserver.cloud-test.wso2.com,
> as.cloud-test.wso2.com;
> +     * domains   {
> +     * wso2.as1.domain {
> +     * tenant_range    1-100;
> +     * }
> +     * wso2.as2.domain {
> +     * tenant_range    101-200;
> +     * }
> +     * wso2.as3.domain {
> +     * tenant_range    *;
> +     * }
> +     * }
> +     * }
> +     * }
> +     *
> +     * @param configURL URL of the load balancer config
> +     */
> +    public void init(String configURL) {
> +
> +        if(configURL == null){
> +            String msg = "Cannot locate the location of the
> loadbalancer.conf file." +
> +                   " You need to set the 'loadbalancer.conf' system
> property.";
> +            log.error(msg);
> +            throw new RuntimeException(msg);
> +        }
> +
> +        if (configURL.startsWith("$system:")) {
> +            configURL =
> System.getProperty(configURL.substring("$system:".length()));
> +        }
> +
> +        try {
> +
> +            // get loadbalancer.conf file as a String
> +            if (configURL.startsWith(File.separator)) {
> +                lbConfigString = createLBConfigString(configURL);
> +            } else {
> +                lbConfigString = createLBConfigString(new
> URL(configURL).openStream());
> +            }
> +
> +        } catch (Exception e) {
> +            String msg = "Cannot read configuration file from " +
> configURL;
> +            log.error(msg, e);
> +            throw new RuntimeException(msg, e);
> +        }
> +
> +        // build a Node object for whole loadbalancer.conf
> +        rootNode = new Node();
> +        rootNode.setName("root");
> +        rootNode = NodeBuilder.buildNode(rootNode, lbConfigString);
> +
> +        // load 'loadbalancer' node
> +        Node lbConfigNode =
> rootNode.findChildNodeByName(Constants.LOAD_BALANCER_ELEMENT);
> +
> +        if(lbConfigNode != null){
> +               createConfiguration(lbConfig = new LBConfiguration(),
> lbConfigNode);
> +        }
> +
> +        // load services node
> +        Node servicesConfigNode =
> rootNode.findChildNodeByName(Constants.SERVICES_ELEMENT);
> +
> +        if (servicesConfigNode == null) {
> +            String msg = "Mandatory " + Constants.SERVICES_ELEMENT +
> +                    " element can not be found in the configuration
> file.";
> +            log.error(msg);
> +            throw new RuntimeException(msg);
> +        }
> +
> +        // Set services configuration
> +        createServicesConfig(servicesConfigNode);
> +
> +    }
> +
> +
> +    /**
> +     * Process the content of the following 'services' element
> +     * <p/>
> +     * services {
> +     * defaults {
> +     * min_app_instances       1;
> +     * max_app_instances       5;
> +     * queue_length_per_node   400;
> +     * rounds_to_average       10;
> +     * instances_per_scale_up  1;
> +     * message_expiry_time     60000;
> +     * }
> +     * <p/>
> +     * appserver {
> +     * hosts                   appserver.cloud-test.wso2.com,
> as.cloud-test.wso2.com;
> +     * domains   {
> +     * wso2.as1.domain {
> +     * tenant_range    1-100;
> +     * }
> +     * wso2.as2.domain {
> +     * tenant_range    101-200;
> +     * }
> +     * wso2.as3.domain {
> +     * tenant_range    *;
> +     * }
> +     * }
> +     * }
> +     * }
> +     *
> +     * @param servicesConfigNode services element's Node
> +     */
> +    public List<ServiceConfiguration> createServicesConfig(Node
> servicesConfigNode) {
> +
> +        // current list of service configs
> +        List<ServiceConfiguration> currentServiceConfigs = new
> ArrayList<ServiceConfiguration>();
> +
> +        // Building default configuration
> +        Node defaultNode =
> servicesConfigNode.findChildNodeByName(Constants.DEFAULTS_ELEMENT);
> +
> +        if (defaultNode != null) {
> +
> +            createConfiguration(defaultServiceConfig = new
> ServiceConfiguration(), defaultNode);
> +        }
> +
> +        // Building custom services configuration
> +        for (Node serviceNode : servicesConfigNode.getChildNodes()) {
> +            //skip default node
> +            if (serviceNode != defaultNode) {
> +
> +                String serviceName = serviceNode.getName();
> +
> +                // reading domains
> +
> +                Node domainsNode;
> +
> +                if (serviceNode.getChildNodes().isEmpty() ||
> +                        !(domainsNode =
> serviceNode.getChildNodes().get(0)).getName().equals(
> +                                Constants.DOMAIN_ELEMENT)) {
> +
> +                    String msg = "The mandatory domains element, child of
> the " + serviceName +
> +                            " element is not specified in the
> configuration file. \n"+
> +                            serviceNode.toString();
> +                    log.error(msg);
> +                    throw new RuntimeException(msg);
> +                }
> +
> +                if (domainsNode.getChildNodes().isEmpty()) {
> +                    // this is probably a mistake, so we don't proceed
> +                    String msg = "No domain is specified under " +
> Constants.DOMAIN_ELEMENT +
> +                            " of " + serviceName + " element.";
> +                    log.error(msg);
> +                    throw new RuntimeException(msg);
> +                }
> +
> +                ServiceConfiguration serviceConfig;
> +
> +                // iterates through all the service domain specified in
> this service element.
> +                for (Node domain : domainsNode.getChildNodes()) {
> +
> +                    // create a new service configuration
> +                    serviceConfig = new ServiceConfiguration();
> +
> +                    // set service name
> +                    serviceConfig.setServiceName(serviceName);
> +
> +                    // set domain name
> +                    serviceConfig.setDomain(domain.getName());
> +
> +                    // let's set properties common to all domains
> specified in this service element.
> +                    createConfiguration(serviceConfig, serviceNode);
> +
> +                    // load properties specified under this service
> domain element.
> +                    createConfiguration(serviceConfig, domain);
> +
> +                    // check host name duplication
> +                    if(isDuplicatedHost(serviceNode.getName(),
> serviceConfig)){
> +                        // this is probably a mistake, so we don't proceed
> +                        String msg = "Duplicated host names detected for
> different service domains.\n" +
> +                                "Element: \n"+serviceNode.toString();
> +                        log.error(msg);
> +                        throw new RuntimeException(msg);
> +                    }
> +
> +                    currentServiceConfigs.add(serviceConfig);
> +
> +                }
> +            }
> +        }
> +
> +        for (ServiceConfiguration serviceConfiguration :
> currentServiceConfigs) {
> +
> +            // add the built ServiceConfiguration, to the map
> +            addServiceConfiguration(serviceConfiguration);
> +
> +        }
> +
> +        return currentServiceConfigs;
> +
> +    }
> +
> +
> +    public boolean addServiceConfiguration(ServiceConfiguration
> serviceConfig) {
> +
> +        Map<String, ServiceConfiguration> map;
> +        String domain = serviceConfig.getDomain();
> +
> +        if(domain == null){
> +            String msg = "Domain of a Service Configuration cannot be
> null. Hence this " +
> +                       "Configuration will be neglected.";
> +            log.error(msg);
> +            return false;
> +        }
> +
> +        String subDomain = serviceConfig.getSubDomain();
> +
> +        if (serviceConfigurations.containsKey(domain)) {
> +            map = serviceConfigurations.get(domain);
> +        } else {
> +            map = new HashMap<String, ServiceConfiguration>();
> +        }
> +        // put this serviceConfig
> +        map.put(subDomain, serviceConfig);
> +
> +        // update the parent map
> +        serviceConfigurations.put(domain, map);
> +
> +        // add to serviceNameToServiceConfiguration map
> +        List<ServiceConfiguration> configs;
> +
>  if(serviceNameToServiceConfigurations.get(serviceConfig.getServiceName())
> == null){
> +               configs = new ArrayList<ServiceConfiguration>();
> +
> +        }else{
> +               configs =
> serviceNameToServiceConfigurations.get(serviceConfig.getServiceName());
> +        }
> +
> +        if(!configs.contains(serviceConfig)){
> +               configs.add(serviceConfig);
> +        }
> +
>  serviceNameToServiceConfigurations.put(serviceConfig.getServiceName(),
> configs);
> +
> +        return true;
> +    }
> +
> +    public ServiceConfiguration removeServiceConfiguration(String domain,
> String subDomain) {
> +
> +        Map<String, ServiceConfiguration> map;
> +        ServiceConfiguration serviceConfig = null;
> +
> +        if(domain == null){
> +            String msg = "Domain of a Service Configuration cannot be
> null. Hence this " +
> +                       "Configuration will be neglected.";
> +            log.error(msg);
> +            return null;
> +        }
> +
> +        if (serviceConfigurations.containsKey(domain)) {
> +            map = serviceConfigurations.get(domain);
> +
> +            if(map != null){
> +               serviceConfig = map.remove(subDomain);
> +            }
> +        }
> +
> +        if(serviceConfig == null){
> +               String msg = "No matching service configuration found for
> domain: "+domain+
> +                               ", sub domain: "+subDomain;
> +            log.error(msg);
> +               return null;
> +        }
> +
> +        String serviceName = serviceConfig.getServiceName();
> +
> +        if (serviceName != null &&
> serviceNameToServiceConfigurations.containsKey(serviceName)) {
> +            if(serviceConfig != null){
> +               List<ServiceConfiguration> list =
> serviceNameToServiceConfigurations.get(serviceName);
> +
> +               list.remove(serviceConfig);
> +
> +               serviceNameToServiceConfigurations.put(serviceName, list);
> +            }
> +        }
> +
> +        Set<String> allHosts;
> +
> +        if (hostNamesTracker.containsKey(serviceName)) {
> +            allHosts = hostNamesTracker.get(serviceName);
> +
> +            for (String hostName : serviceConfig.getHosts()) {
> +
> +                               if (hostName != null) {
> +
> +                                       allHosts.remove(hostName);
> +
> +                                       hostCtxt.remove(hostName);
> +                               }
> +            }
> +        }
> +
> +        return serviceConfig;
> +    }
> +
> +    public void resetData(){
> +       serviceConfigurations =
> +                new HashMap<String, Map<String, ServiceConfiguration>>();
> +
> +       serviceNameToServiceConfigurations =
> +                       new HashMap<String, List<ServiceConfiguration>>();
> +
> +    }
> +
> +
> +    /**
> +     * Duplications can only be seen, when you traverse down the
> configuration file.
> +     *
> +     */
> +    public boolean isDuplicatedHost(String name, ServiceConfiguration
> serviceConfig) {
> +
> +        /**
> +         * This will be populated with host names of all other services
> other than the
> +         * service subjected to the test.
> +         */
> +        List<String> hostsOtherThanMine = new
> ArrayList<String>(hostNamesTracker.values().size());
> +
> +        for (Map.Entry<String, Set<String>> entry :
> hostNamesTracker.entrySet()) {
> +            if (!entry.getKey().equals(name)) {
> +                hostsOtherThanMine.addAll(entry.getValue());
> +            }
> +        }
> +
> +        for (String host : serviceConfig.getHosts()) {
> +            if (!hostsOtherThanMine.isEmpty() &&
> hostsOtherThanMine.contains(host)) {
> +                return true;
> +            }
> +        }
> +
> +        addToHostNameTrackerMap(name, serviceConfig.getHosts());
> +
> +        return false;
> +    }
> +
> +
> +    public void addToHostNameTrackerMap(String name, List<String> hosts) {
> +
> +        Set<String> allHosts;
> +
> +        if (hostNamesTracker.containsKey(name)) {
> +            allHosts = hostNamesTracker.get(name);
> +            allHosts.addAll(hosts);
> +        } else {
> +            allHosts = new HashSet<String>(hosts);
> +        }
> +        hostNamesTracker.put(name, allHosts);
> +    }
> +
> +    public void addToHostContextMap(String hostName, HostContext ctxt) {
> +
> +        if (hostName != null && ctxt != null) {
> +            hostCtxt.put(hostName, ctxt);
> +        }
> +    }
> +
> +    /**
> +     * Return a map of {@link
> org.apache.stratos.load.balancer.conf.util.HostContext}.
> +     * @return
> +     */
> +    public Map<String, HostContext> getHostContextMap() {
> +
> +        List<Integer> tenantIds;
> +        Map<String, String> URLSuffixes;
> +
> +        // FIXME if possible! I couldn't think of any other way to do
> this, at this moment.
> +        // Note: some of these for-loops are pretty small, thus no
> considerable performance overhead.
> +        // iterate through each service
> +        for (Iterator<Set<String>> it =
> hostNamesTracker.values().iterator(); it.hasNext();) {
> +
> +            // iterate through host names of this service
> +            for (String hostName : ((Set<String>) it.next())) {
> +
> +                // building HostContext
> +                HostContext ctxt = new HostContext(hostName);
> +
> +                // iterate through domains of this host
> +                for (Map.Entry<String, Map<String, ServiceConfiguration>>
> parentMap : serviceConfigurations.entrySet()) {
> +
> +                    // iterate through sub domain of this domain
> +                    for (Map.Entry<String, ServiceConfiguration> childMap
> : parentMap.getValue()
> +                            .entrySet()) {
> +                        // iterate through hosts of this
> +                        for (String host :
> childMap.getValue().getHosts()) {
> +                            // if a matching Service configuration is
> found.
> +                            if (host.equals(hostName)) {
> +
> +                                String tenantRange =
> childMap.getValue().getTenantRange();
> +                                String domain = parentMap.getKey();
> +                                String subDomain = childMap.getKey();
> +
> +
>  ctxt.addTenantDomainContexts(LoadBalancerConfigUtil.getTenantDomainContexts(tenantRange,
> domain, subDomain));
> +
> +                                break;
> +                            }
> +                        }
> +
> +                        //iterate through URL suffixes
> +                        for(Map.Entry<String, String> entry :
> childMap.getValue().getUrl_suffix().entrySet()) {
> +                            if(entry.getKey().equals(hostName)) {
> +
> +                                ctxt.setUrlSuffix(entry.getValue());
> +
> +                                break;
> +                            }
> +
> +                        }
> +                    }
> +                }
> +
> +                // add this hostCtxt
> +                hostCtxt.put(hostName, ctxt);
> +            }
> +
> +        }
> +
> +        return hostCtxt;
> +
> +    }
> +
> +    protected void createConfiguration(Configuration config, Node node) {
> +
> +        if (node == null) {
> +            String msg = "The configuration element for " +
> +                    config.getClass().getName() + " is null.";
> +            throw new RuntimeException(msg);
> +        }
> +
> +        try {
> +            // load properties
> +            for (Map.Entry<String, String> entry :
> node.getProperties().entrySet()) {
> +                String key = entry.getKey();
> +                String value = entry.getValue();
> +
> +                PropertyHelper.setInstanceProperty(key, value, config);
> +            }
> +
> +        } catch (Exception e) {
> +            String msg = "Error setting values to " +
> config.getClass().getName();
> +            log.error(msg, e);
> +            throw new RuntimeException(msg, e);
> +        }
> +    }
> +
> +    public LBConfiguration getLoadBalancerConfig() {
> +        return lbConfig;
> +    }
> +
> +    public String[] getServiceDomains() {
> +
> +        Object[] objs = serviceConfigurations.keySet().toArray();
> +
> +        return Arrays.copyOf(objs, objs.length, String[].class);
> +
> +    }
> +
> +    public String[] getServiceSubDomains(String domain) {
> +
> +        if (serviceConfigurations.get(domain) != null) {
> +            Object[] objs =
> serviceConfigurations.get(domain).keySet().toArray();
> +            return Arrays.copyOf(objs, objs.length, String[].class);
> +        }
> +
> +        return new String[0];
> +    }
> +
> +    public ServiceConfiguration getServiceConfig(String domain, String
> subDomain) {
> +        if (serviceConfigurations.get(domain) != null) {
> +            return serviceConfigurations.get(domain).get(subDomain);
> +        }
> +        return null;
> +    }
> +
> +
> +    public List<ServiceConfiguration> getServiceConfigs(String
> serviceName) {
> +        return serviceNameToServiceConfigurations.get(serviceName);
> +    }
> +
> +    /**
> +     * Convert given configuration file to a single String
> +     *
> +     * @param configFileName - file name to convert
> +     * @return String with complete lb configuration
> +     * @throws java.io.FileNotFoundException
> +     */
> +    public String createLBConfigString(String configFileName) throws
> FileNotFoundException {
> +        StringBuilder lbConfigString = new StringBuilder("");
> +
> +        File configFile = new File(configFileName);
> +        Scanner scanner;
> +
> +        scanner = new Scanner(configFile);
> +
> +        while (scanner.hasNextLine()) {
> +            lbConfigString.append(scanner.nextLine().trim() + "\n");
> +        }
> +
> +        return lbConfigString.toString().trim();
> +    }
> +
> +    public String createLBConfigString(InputStream configFileName) throws
> IOException {
> +
> +        // read the stream with BufferedReader
> +        BufferedReader br = new BufferedReader(new
> InputStreamReader(configFileName));
> +
> +        StringBuilder sb = new StringBuilder();
> +
> +        String line;
> +        while ((line = br.readLine()) != null) {
> +            sb.append(line.trim() + "\n");
> +        }
> +
> +        return sb.toString().trim();
> +    }
> +
> +    public abstract class Configuration implements Serializable {
> +
> +        private static final long serialVersionUID =
> -5433889427746551250L;
> +        protected String imageId = System.getenv("ami_id");
> +        protected String payload;
> +        protected boolean payloadSet;
> +
> +        protected String availability_zone = "us-east-1c";
> +        protected boolean availabilityZoneSet;
> +
> +        protected String[] security_groups = new String[]{"default"};
> +        protected boolean securityGroupsSet;
> +
> +        protected String instance_type = "m1.large";
> +        protected boolean instanceTypeSet;
> +
> +        protected String additional_info;
> +
> +        public String getImageId() {
> +            return imageId;
> +        }
> +
> +        public String getAdditionalInfo() {
> +            return additional_info;
> +        }
> +
> +        public String getAvailability_zone() {
> +            if (this instanceof LBConfiguration) {
> +                return availability_zone;
> +            }
> +            if (availabilityZoneSet) {
> +                return availability_zone;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.availabilityZoneSet) {
> +                return defaultServiceConfig.availability_zone;
> +            }
> +            return availability_zone;
> +        }
> +
> +        public String[] getSecurityGroups() {
> +            if (this instanceof LBConfiguration) {
> +                return security_groups;
> +            }
> +            if (securityGroupsSet) {
> +                return security_groups;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.securityGroupsSet) {
> +                return defaultServiceConfig.security_groups;
> +            }
> +            return security_groups;
> +        }
> +
> +        public String getInstanceType() {
> +            if (this instanceof LBConfiguration) {
> +                return instance_type;
> +            }
> +            if (instanceTypeSet) {
> +                return instance_type;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.instanceTypeSet) {
> +                return defaultServiceConfig.instance_type;
> +            }
> +            return instance_type;
> +        }
> +
> +
> +        public String getUserData() {
> +            if (payload == null) {
> +                payload =
> LoadBalancerConfigUtil.getUserData("resources/cluster_node.zip");
> +            }
> +            if (this instanceof LBConfiguration) {
> +                return payload;
> +            }
> +            if (payloadSet) {
> +                return payload;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.payloadSet) {
> +                return defaultServiceConfig.payload;
> +            }
> +            return payload;
> +        }
> +
> +        public void setPayload(String payload) {
> +            this.payload =
> LoadBalancerConfigUtil.getUserData(LoadBalancerConfigUtil.replaceVariables(payload));
> +            this.payloadSet = true;
> +        }
> +
> +        public void setAvailability_zone(String availabilityZone) {
> +            this.availability_zone =
> LoadBalancerConfigUtil.replaceVariables(availabilityZone);
> +            this.availabilityZoneSet = true;
> +        }
> +
> +        public void setSecurity_groups(String securityGroups) {
> +            this.security_groups =
> LoadBalancerConfigUtil.replaceVariables(securityGroups).split(",");
> +            this.securityGroupsSet = true;
> +        }
> +
> +        public void setInstance_type(String instanceType) {
> +            this.instance_type =
> LoadBalancerConfigUtil.replaceVariables(instanceType);
> +            this.instanceTypeSet = true;
> +        }
> +
> +    }
> +
> +    public class LBConfiguration extends Configuration implements
> Serializable {
> +
> +        private static final long serialVersionUID = 1357143883932816418L;
> +        private String elasticIP;//=
> LoadBalancerConfigUtil.replaceVariables("${ELASTIC_IP}");
> +        private int instances = 1;
> +        private boolean isAutoscaleEnabled;
> +        private int autoscalerTaskInterval = 30000;
> +        private String autoscalerServiceEpr;
> +        private int serverStartupDelay = 60000;
> +        private int sizeOfCache = 0 ;
> +        private boolean failOver;
> +        private int sessionTimeOut = -1;
> +        private String groupManagementAgentClass;
> +        private String autoscalerTaskClass;
> +        private String mbServerUrl;
> +        private boolean useEmbeddedAutoscaler = true;
> +        private String algorithm =
> "org.apache.synapse.endpoints.algorithms.RoundRobin";
> +
> +        public String getElasticIP() {
> +            return elasticIP;
> +        }
> +
> +        public int getInstances() {
> +            return instances;
> +        }
> +
> +        public boolean isAutoscaleEnabled() {
> +            return isAutoscaleEnabled;
> +        }
> +
> +        public boolean useEmbeddedAutoscaler() {
> +            return useEmbeddedAutoscaler;
> +        }
> +
> +        public boolean getFailOver() {
> +            return failOver;
> +        }
> +
> +        public String getAutoscalerServiceEpr() {
> +            return autoscalerServiceEpr;
> +        }
> +
> +        public int getAutoscalerTaskInterval() {
> +            return autoscalerTaskInterval;
> +        }
> +
> +        public int getServerStartupDelay() {
> +            return serverStartupDelay;
> +        }
> +
> +        public int getSessionTimeOut() {
> +            return sessionTimeOut;
> +        }
> +
> +        public void setElasticIP(String elasticIP) {
> +            this.elasticIP =
> LoadBalancerConfigUtil.replaceVariables(elasticIP);
> +        }
> +
> +        public void setInstances(int instances) {
> +            this.instances = instances;
> +        }
> +
> +        public void setEnable_autoscaler(String isEnabled) {
> +            this.isAutoscaleEnabled = Boolean.parseBoolean(isEnabled);
> +        }
> +
> +        public void setUse_embedded_autoscaler(String use) {
> +            this.useEmbeddedAutoscaler = Boolean.parseBoolean(use);
> +        }
> +
> +        public void setFail_over(String isEnabled) {
> +            this.failOver = Boolean.parseBoolean(isEnabled);
> +        }
> +
> +        public void setAutoscaler_service_epr(String epr) {
> +            this.autoscalerServiceEpr = epr;
> +        }
> +
> +        public void setMb_server_url(String url) {
> +            this.mbServerUrl = url;
> +        }
> +
> +        public String getMbServerUrl() {
> +               return mbServerUrl;
> +        }
> +
> +               public void setAutoscaler_task_interval(String interval) {
> +            this.autoscalerTaskInterval = Integer.parseInt(interval);
> +        }
> +
> +        public void setServer_startup_delay(String delay) {
> +            this.serverStartupDelay = Integer.parseInt(delay);
> +        }
> +
> +        public void setSession_timeout(String timeout) {
> +            this.sessionTimeOut = Integer.parseInt(timeout);
> +        }
> +
> +        public String getAlgorithm() {
> +            return algorithm;
> +        }
> +
> +        public void setAlgorithm(String algorithm) {
> +            if (algorithm != null) {
> +                this.algorithm = algorithm;
> +            }
> +        }
> +
> +        public int getSizeOfCache() {
> +            return sizeOfCache;
> +        }
> +
> +        public void setSize_of_cache(int sizeOfCache) {
> +            this.sizeOfCache = sizeOfCache;
> +        }
> +
> +        public String getGroupManagementAgentClass() {
> +            return groupManagementAgentClass;
> +        }
> +
> +        public String getAutoscalerTaskClass() {
> +            return autoscalerTaskClass;
> +        }
> +
> +        public void setGroup_mgt_agent(String groupManagementAgentClass){
> +            this.groupManagementAgentClass = groupManagementAgentClass;
> +        }
> +
> +        public void setAutoscaler_task(String autoscalerTaskClass){
> +            this.autoscalerTaskClass = autoscalerTaskClass;
> +        }
> +    }
> +
> +    public class ServiceConfiguration extends Configuration implements
> Serializable {
> +
> +       private String serviceName;
> +
> +        public String getServiceName() {
> +               return serviceName;
> +        }
> +
> +               public void setServiceName(String name) {
> +               this.serviceName = name;
> +        }
> +
> +               public String getPublicIp() {
> +               return publicIp;
> +        }
> +
> +               public void setPublic_ip(String publicIp) {
> +               this.publicIp = publicIp;
> +        }
> +
> +               private String publicIp;
> +
> +               private static final long serialVersionUID =
> 8707314702788040116L;
> +        private int minAppInstances = 1;
> +        private boolean minAppInstancesSet;
> +
> +        private int maxAppInstances = 3;
> +        private boolean maxAppInstancesSet;
> +
> +        private int maxRequestsPerSecond = 100;
> +        private boolean maxRequestsPerSecondSet;
> +
> +        private double alarmingUpperRate = 0.7;
> +        private boolean alarmingUpperRateSet;
> +
> +        private double alarmingLowerRate = 0.2;
> +        private boolean alarmingLowerRateSet;
> +
> +        private double scaleDownFactor = 0.25;
> +        private boolean scaleDownFactorSet;
> +
> +        private int roundsToAverage = 10;
> +        private boolean roundsToAverageSet;
> +
> +        private int instancesPerScaleUp = 1;
> +        private boolean instancesPerScaleUpSet;
> +
> +        private int messageExpiryTime = 60000; // milliseconds
> +        private boolean messageExpiryTimeSet;
> +
> +        private List<String> hosts = new ArrayList<String>();
> +        private Map<String, String> urlSuffixes = new HashMap<String,
> String>();
> +        private boolean hostsSet;
> +
> +        private String domain;
> +
> +        private String tenantRange;
> +        private boolean tenantRangeSet;
> +
> +        private String subDomain = Constants.DEFAULT_SUB_DOMAIN;
> +        private boolean subDomainSet;
> +
> +        public String getTenantRange() {
> +            if (tenantRangeSet) {
> +                return tenantRange;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.tenantRangeSet) {
> +                return defaultServiceConfig.tenantRange;
> +            }
> +            return tenantRange;
> +        }
> +
> +        public String getDomain() {
> +            return domain;
> +        }
> +
> +        public List<String> getHosts() {
> +            if (hostsSet) {
> +                return hosts;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.hostsSet) {
> +                return defaultServiceConfig.hosts;
> +            }
> +            return hosts;
> +        }
> +
> +        public int getMinAppInstances() {
> +            if (minAppInstancesSet) {
> +                return minAppInstances;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.minAppInstancesSet) {
> +                return defaultServiceConfig.minAppInstances;
> +            }
> +            return minAppInstances;
> +        }
> +
> +        public int getMaxAppInstances() {
> +            if (maxAppInstancesSet) {
> +                return maxAppInstances;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.maxAppInstancesSet) {
> +                return defaultServiceConfig.maxAppInstances;
> +            }
> +            return maxAppInstances;
> +        }
> +
> +        public int getMaxRequestsPerSecond() {
> +            if (maxRequestsPerSecondSet) {
> +                return maxRequestsPerSecond;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.maxRequestsPerSecondSet) {
> +                return defaultServiceConfig.maxRequestsPerSecond;
> +            }
> +            return maxRequestsPerSecond;
> +        }
> +
> +        public int getRoundsToAverage() {
> +            if (roundsToAverageSet) {
> +                return roundsToAverage;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.roundsToAverageSet) {
> +                return defaultServiceConfig.roundsToAverage;
> +            }
> +            return roundsToAverage;
> +        }
> +
> +        public int getInstancesPerScaleUp() {
> +            if (instancesPerScaleUpSet) {
> +                return instancesPerScaleUp;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.instancesPerScaleUpSet) {
> +                return defaultServiceConfig.instancesPerScaleUp;
> +            }
> +            return instancesPerScaleUp;
> +        }
> +
> +        public int getMessageExpiryTime() {
> +            if (messageExpiryTimeSet) {
> +                return messageExpiryTime;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.messageExpiryTimeSet) {
> +                return defaultServiceConfig.messageExpiryTime;
> +            }
> +            return messageExpiryTime;
> +        }
> +
> +        public String getSubDomain() {
> +            if (subDomainSet) {
> +                return subDomain;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.subDomainSet) {
> +                return defaultServiceConfig.subDomain;
> +            }
> +            return subDomain;
> +        }
> +
> +        public void setMin_app_instances(int minAppInstances) {
> +            this.minAppInstances = minAppInstances;
> +            this.minAppInstancesSet = true;
> +        }
> +
> +        public void setMax_app_instances(int maxAppInstances) {
> +            if (maxAppInstances < 1) {
> +                LoadBalancerConfigUtil.handleException("maxAppInstances
> in the autoscaler task configuration " +
> +                        "should be at least 1");
> +            }
> +            this.maxAppInstances = maxAppInstances;
> +            this.maxAppInstancesSet = true;
> +        }
> +
> +               public void setAlarming_upper_rate(double rate) {
> +                       if (rate > 0 && rate <= 1) {
> +                               this.alarmingUpperRate = rate;
> +                               this.alarmingUpperRateSet = true;
> +                       }
> +               }
> +
> +        public void setAlarming_lower_rate(double rate) {
> +                       if (rate > 0 && rate <= 1) {
> +                               this.alarmingLowerRate = rate;
> +                               this.alarmingLowerRateSet = true;
> +                       }
> +        }
> +
> +               public void setScale_down_factor(double factor) {
> +                       if (factor > 0 && factor <= 1) {
> +                               this.scaleDownFactor = factor;
> +                               this.scaleDownFactorSet = true;
> +                       }
> +               }
> +
> +        public void setMax_requests_per_second(int rps) {
> +            this.maxRequestsPerSecond = rps;
> +            this.maxRequestsPerSecondSet = true;
> +        }
> +
> +        public void setRounds_to_average(int roundsToAverage) {
> +            this.roundsToAverage = roundsToAverage;
> +            this.roundsToAverageSet = true;
> +        }
> +
> +        public void setInstances_per_scale_up(int instancesPerScaleUp) {
> +            if (instancesPerScaleUp < 1) {
> +
>  LoadBalancerConfigUtil.handleException("instancesPerScaleUp in the
> autoscaler task configuration " +
> +                        "should be at least 1");
> +            }
> +            this.instancesPerScaleUp = instancesPerScaleUp;
> +            this.instancesPerScaleUpSet = true;
> +        }
> +
> +        public void setMessage_expiry_time(int messageExpiryTime) {
> +            if (messageExpiryTime < 1) {
> +                LoadBalancerConfigUtil.handleException("messageExpiryTime
> in the autoscaler task configuration " +
> +                        "should be at least 1");
> +            }
> +            this.messageExpiryTime = messageExpiryTime;
> +            this.messageExpiryTimeSet = true;
> +        }
> +
> +        public void setHosts(String hostsStr) {
> +            // clear all unnecessary values --> property will get
> overwritten
> +            hosts = new ArrayList<String>();
> +            // there can be multiple hosts, let's find out.
> +            String[] host = hostsStr.split(Constants.HOSTS_DELIMITER);
> +
> +            for (String string : host) {
> +                if (!string.isEmpty()) {
> +                    this.hosts.add(string);
> +                }
> +            }
> +
> +        }
> +
> +        public void setUrl_suffix(String suffix) {
> +            // clear all unnecessary values --> property will get
> overwritten
> +            //hosts = new ArrayList<String>();
> +            // there can be multiple hosts, let's find out.
> +            String[] suffixes = suffix.split(Constants.HOSTS_DELIMITER);
> +            int count = 0;
> +            if(suffixes.length == this.hosts.size()) {
> +                for (String string : suffixes) {
> +                    if (!string.isEmpty()) {
> +                        this.urlSuffixes.put(this.hosts.get(count),
> string);
> +                        count++;
> +                    }
> +                }
> +
> +            } else {
> +                //Error
> +            }
> +        }
> +
> +        public Map<String, String> getUrl_suffix() {
> +            return this.urlSuffixes;
> +        }
> +
> +        public void setTenant_range(String range) {
> +            this.tenantRange = range;
> +        }
> +
> +        public void setSub_domain(String subDomain) {
> +            this.subDomain = subDomain;
> +            this.subDomainSet = true;
> +        }
> +
> +        public void setDomain(String domain) {
> +            this.domain = domain;
> +        }
> +
> +        public boolean equals(ServiceConfiguration config) {
> +            return this.domain.equals(config.getDomain()) &&
> +                    this.subDomain.equals(config.getSubDomain());
> +        }
> +
> +        public int hashCode() {
> +            return new HashCodeBuilder(17, 31). // two randomly chosen
> prime numbers
> +                    append(domain).
> +                    append(subDomain).
> +                    toHashCode();
> +        }
> +
> +        public double getAlarmingUpperRate() {
> +            if (alarmingUpperRateSet) {
> +                return alarmingUpperRate;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.alarmingUpperRateSet) {
> +                return defaultServiceConfig.alarmingUpperRate;
> +            }
> +            return alarmingUpperRate;
> +        }
> +
> +        public double getAlarmingLowerRate() {
> +            if (alarmingLowerRateSet) {
> +                return alarmingLowerRate;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.alarmingLowerRateSet) {
> +                return defaultServiceConfig.alarmingLowerRate;
> +            }
> +            return alarmingLowerRate;
> +        }
> +
> +        public double getScaleDownFactor() {
> +            if (scaleDownFactorSet) {
> +                return scaleDownFactor;
> +            } else if (defaultServiceConfig != null &&
> defaultServiceConfig.scaleDownFactorSet) {
> +                return defaultServiceConfig.scaleDownFactor;
> +            }
> +            return scaleDownFactor;
> +        }
> +    }
> +
> +    public Map<String, Set<String>> getHostNamesTracker() {
> +        return hostNamesTracker;
> +    }
> +
> +
> +    public Map<String, Map<String, ServiceConfiguration>>
> getServiceConfigurations() {
> +        return serviceConfigurations;
> +    }
> +
> +
> +    public Node getRootNode() {
> +        return rootNode;
> +    }
> +
> +
> +    public void setRootNode(Node rootNode) {
> +        this.rootNode = rootNode;
> +    }
> +
> +    public static void setInstance(LoadBalancerConfiguration instance) {
> +        LoadBalancerConfiguration.instance = instance;
> +    }
> +
> +       public Map<String, List<ServiceConfiguration>>
> getServiceNameToServiceConfigurations() {
> +       return serviceNameToServiceConfigurations;
> +    }
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
> ----------------------------------------------------------------------
> diff --git
> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
> new file mode 100755
> index 0000000..c4820a7
> --- /dev/null
> +++
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
> @@ -0,0 +1,356 @@
> +/**
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF 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
> +
> + *  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 org.apache.stratos.load.balancer.conf.structure;
> +
> +import java.io.Serializable;
> +import java.util.ArrayList;
> +import java.util.Iterator;
> +import java.util.LinkedHashMap;
> +import java.util.List;
> +import java.util.Map;
> +import java.util.Map.Entry;
> +
> +import org.apache.commons.lang.builder.HashCodeBuilder;
> +
> +/**
> + * This is the basic data structure which holds a <i>Nginx</i> formatted
> configuration file.
> + *
> + */
> +public class Node implements Serializable{
> +
> +    private static final long serialVersionUID = 4071569903421115370L;
> +
> +    /**
> +     * Name of this Node element
> +     */
> +    private String name;
> +
> +    /**
> +     * Every node can have 0..n child nodes.
> +     * They are kept in a List.
> +     */
> +    private List<Node> childNodes = new ArrayList<Node>();
> +
> +    /**
> +     * Every node can have 0..n properties.
> +     * They are kept in a Map, in the order they appear.
> +     * Key: property name
> +     * Value: property value
> +     */
> +    private Map<String, String> properties = new LinkedHashMap<String,
> String>();
> +
> +    public void setChildNodes(List<Node> childNodes) {
> +        this.childNodes = childNodes;
> +    }
> +
> +    public void setProperties(Map<String, String> properties) {
> +        this.properties = properties;
> +    }
> +
> +    /**
> +     * This will convert each child Node of this Node to a String.
> +     * @return a string which represents child nodes of this node.
> +     */
> +    public String childNodesToString(int indentation) {
> +        StringBuilder childNodesString = new StringBuilder();
> +        indentation++;
> +
> +        for (Node node : childNodes) {
> +            childNodesString.append(node.toString(indentation)+"\n");
> +        }
> +
> +        return childNodesString.toString();
> +    }
> +
> +    /**
> +     * This will try to find a child Node of this Node, which has the
> given name.
> +     * @param name name of the child node to find.
> +     * @return child Node object if found or else <code>null</code>.
> +     */
> +    public Node findChildNodeByName(String name) {
> +        for (Node aNode : childNodes) {
> +            if (aNode.getName().equals(name)) {
> +                return aNode;
> +            }
> +        }
> +
> +        return null;
> +    }
> +
> +    /**
> +     * Returns the name of this Node.
> +     * @return name of the node.
> +     */
> +    public String getName() {
> +        return name;
> +    }
> +
> +    /**
> +     * Returns child nodes List of this Node.
> +     * @return List of Node
> +     */
> +    public List<Node> getChildNodes() {
> +        return childNodes;
> +    }
> +
> +    /**
> +     * Returns properties Map of this Node.
> +     * @return Map whose keys and values are String.
> +     */
> +    public Map<String, String> getProperties() {
> +        return properties;
> +    }
> +
> +    /**
> +     * Returns the value of a given property.
> +     * @param key name of a property.
> +     * @return trimmed value if the property is found in this Node, or
> else <code>null</code>.
> +     */
> +    public String getProperty(String key) {
> +        if (properties.get(key) == null) {
> +            return null;
> +        }
> +        return properties.get(key).trim();
> +    }
> +
> +    /**
> +     * Returns all the properties of this Node as a String.
> +     * Key and value of the property is separated by a tab (\t) character
> and
> +     * each property is separated by a new line character.
> +     * @param indentation relative number of tabs
> +     * @return properties of this node as a String.
> +     */
> +    public String propertiesToString(int indentation) {
> +
> +        String indent = getIndentation(indentation);
> +
> +        StringBuilder sb = new StringBuilder();
> +        for (Entry<String, String> entry : properties.entrySet()) {
> +            // hack to get a quick fix in.
> +            if (!"tenant_id".equals(entry.getKey()) &&
> !"alias".equals(entry.getKey())) {
> +                sb.append(indent + entry.getKey() + "\t" +
> entry.getValue() + ";\n");
> +            }
> +        }
> +        return sb.toString();
> +    }
> +
> +    /**
> +     * Removes the first occurrence of a node having the given name
> +     * and returns the removed {@link
> org.apache.stratos.load.balancer.conf.structure.Node}.
> +     * @param name name of the child node to be removed.
> +     * @return removed {@link
> org.apache.stratos.load.balancer.conf.structure.Node} or else
> <code>null</code>.
> +     */
> +    public Node removeChildNode(String name) {
> +        Node aNode = findChildNodeByName(name);
> +
> +        if(aNode != null){
> +            if(childNodes.remove(aNode)){
> +                return aNode;
> +            }
> +        }
> +
> +        return null;
> +    }
> +
> +    /**
> +     * Removes the first occurrence of a node equals to the given node.
> +     * @param node {@link
> org.apache.stratos.load.balancer.conf.structure.Node} to be removed.
> +     * @return whether the removal is successful or not.
> +     */
> +    public boolean removeChildNode(Node node){
> +
> +        return childNodes.remove(node);
> +    }
> +
> +    /**
> +     * Sets the name of this Node.
> +     * @param name String to be set as the name.
> +     */
> +    public void setName(String name) {
> +        this.name = name;
> +    }
> +
> +    /**
> +     * Appends a child node at the end of the List of child nodes of this
> Node, if
> +     * a similar node is not already present as a child node.
> +     * @param aNode child Node to be appended.
> +     */
> +    public void appendChild(Node aNode) {
> +        if (aNode != null && !nodeAlreadyPresent(aNode)) {
> +            childNodes.add(aNode);
> +        }
> +    }
> +
> +    /**
> +     * Adds a new property to properties Map of this Node if and only if
> +     * key is not <code>null</code>.
> +     * @param key name of the property to be added.
> +     * @param value value of the property to be added.
> +     */
> +    public void addProperty(String key, String value) {
> +        if (key != null) {
> +            properties.put(key, value);
> +        }
> +    }
> +
> +    /**
> +     * Convert this Node to a String which is in <i>Nginx</i> format.
> +     * <br/>
> +     * Sample:
> +     * <br></br>
> +     * <code>
> +     * ij {
> +     * <br/>
> +     * klm n;
> +     * <br/>
> +     * pq {
> +     * <br/>
> +     * rst u;
> +     * <br/>
> +     * }
> +     * <br/>
> +     * }
> +     * <br/>
> +     * </code>
> +     */
> +    public String toString() {
> +
> +        String nodeString =
> +                getName()+" {\n" +
> +                (propertiesToString(1)) +
> +                (childNodesToString(1)) +
> +                "}";
> +
> +        return nodeString;
> +    }
> +
> +    public boolean equals(Object node) {
> +
> +        if(node instanceof Node){
> +            return this.getName().equals(((Node) node).getName()) &&
> +                    isIdenticalProperties(this.getProperties(), ((Node)
> node).getProperties()) &&
> +                    isIdenticalChildren(this.getChildNodes(), ((Node)
> node).getChildNodes());
> +        }
> +
> +        return false;
> +
> +    }
> +
> +    public int hashCode() {
> +        return new HashCodeBuilder(17, 31). // two randomly chosen prime
> numbers
> +            append(name).
> +            append(properties).
> +            append(childNodes).
> +            toHashCode();
> +    }
> +
> +    private boolean isIdenticalChildren(List<Node> childNodes1,
> List<Node> childNodes2) {
> +
> +        if(childNodes1.size() != childNodes2.size()){
> +            return false;
> +        }
> +
> +        for (Node node1 : childNodes1) {
> +            int i=0;
> +            for (Node node2 : childNodes2) {
> +
> +                i++;
> +                if(node1.equals(node2)){
> +                    break;
> +                }
> +
> +                if(i == childNodes1.size()){
> +                    return false;
> +                }
> +
> +            }
> +        }
> +
> +        return true;
> +    }
> +
> +    private boolean nodeAlreadyPresent(Node aNode){
> +
> +        for(Node node : this.childNodes){
> +            if(node.equals(aNode)){
> +                return true;
> +            }
> +        }
> +
> +        return false;
> +    }
> +
> +    private boolean isIdenticalProperties(Map<String, String> map1,
> +        Map<String, String> map2) {
> +
> +        if(map1.size() != map2.size()){
> +            return false;
> +        }
> +
> +        for (Iterator<Entry<String, String>> iterator1 =
> map1.entrySet().iterator(); iterator1.hasNext();) {
> +            Entry<String, String> entry1 = (Entry<String, String>)
> iterator1.next();
> +
> +            int i=0;
> +
> +            for(Iterator<Entry<String, String>> iterator2 =
> map2.entrySet().iterator(); iterator2.hasNext();) {
> +                Entry<String, String> entry2 = (Entry<String, String>)
> iterator2.next();
> +
> +                i++;
> +
> +                if((entry1.getKey().equals(entry2.getKey()) &&
> +                        entry1.getValue().equals(entry2.getValue()))){
> +
> +                    break;
> +                }
> +
> +                if(i == map1.size()){
> +                    return false;
> +                }
> +
> +            }
> +        }
> +
> +        return true;
> +    }
> +
> +    private String toString(int indentation){
> +
> +        String indent = getIndentation(indentation-1);
> +
> +        String nodeString =
> +                indent + getName()+" {\n" +
> +                (propertiesToString(indentation)) +
> +                (childNodesToString(indentation)) +
> +                indent + "}";
> +
> +        return nodeString;
> +    }
> +
> +    private String getIndentation(int tabs){
> +
> +        StringBuilder indent = new StringBuilder("");
> +
> +        for (int i = 0; i < tabs; i++) {
> +            indent.append("\t");
> +        }
> +
> +        return indent.toString();
> +    }
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
> ----------------------------------------------------------------------
> diff --git
> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
> new file mode 100755
> index 0000000..168492d
> --- /dev/null
> +++
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
> @@ -0,0 +1,140 @@
> +/**
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF 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
> +
> + *  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 org.apache.stratos.load.balancer.conf.structure;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +import org.apache.stratos.load.balancer.conf.util.Constants;
> +
> +/**
> + * This responsible for build up a Node object from a given content.
> + * Every closing brace should be in a new line.
> + */
> +public class NodeBuilder {
> +
> +    private static final Log log = LogFactory.getLog(NodeBuilder.class);
> +
> +    /**
> +     * This method is useful when you do not have a root node in your
> content.
> +     * @param aNode
> +     *            Node object whose name set.
> +     * @param content
> +     *            should be something similar to following.
> +     *
> +     *            abc d;
> +     *            efg h;
> +     *            # comment
> +     *            ij { # comment
> +     *              klm n;
> +     *
> +     *              pq {
> +     *                  rst u;
> +     *              }
> +     *            }
> +     *
> +     * @return fully constructed Node
> +     */
> +    public static Node buildNode(Node aNode, String content) {
> +
> +       if(content == null || content.isEmpty()){
> +               return aNode;
> +       }
> +
> +        String[] lines = content.split("\n");
> +
> +        for (int i = 0; i < lines.length; i++) {
> +            String line = lines[i].trim();
> +
> +            // avoid line comments
> +            if (!line.startsWith(Constants.NGINX_COMMENT)) {
> +
> +                // skip comments in-line
> +                if(line.contains(Constants.NGINX_COMMENT)){
> +                    line = line.substring(0,
> line.indexOf(Constants.NGINX_COMMENT));
> +                }
> +
> +                // another node is detected and it is not a variable
> starting from $
> +                if (line.contains(Constants.NGINX_NODE_START_BRACE) &&
> +                        !line.contains(Constants.NGINX_VARIABLE)) {
> +
> +                    try {
> +                        Node childNode = new Node();
> +                        childNode.setName(line.substring(0,
> line.indexOf(Constants.NGINX_NODE_START_BRACE)).trim());
> +
> +                        StringBuilder sb = new StringBuilder();
> +
> +                        int matchingBraceTracker = 1;
> +
> +                        while
> (!line.contains(Constants.NGINX_NODE_END_BRACE) || matchingBraceTracker !=
> 0) {
> +                            i++;
> +                            if (i == lines.length) {
> +                                break;
> +                            }
> +                            line = lines[i];
> +                            if
> (line.contains(Constants.NGINX_NODE_START_BRACE)) {
> +                                matchingBraceTracker++;
> +                            }
> +                            if
> (line.contains(Constants.NGINX_NODE_END_BRACE)) {
> +                                matchingBraceTracker--;
> +                            }
> +                            sb.append(line + "\n");
> +                        }
> +
> +                        childNode = buildNode(childNode, sb.toString());
> +                                               if (aNode == null) {
> +                                                       aNode = childNode;
> +                                               } else {
> +
> aNode.appendChild(childNode);
> +                                               }
> +
> +                    } catch (Exception e) {
> +                        String msg = "Malformatted element is defined in
> the configuration file. [" +
> +                                i + "] \n";
> +                        log.error(msg , e);
> +                        throw new RuntimeException(msg + line, e);
> +                    }
> +
> +                }
> +                // this is a property
> +                else {
> +                    if (!line.isEmpty() &&
> !Constants.NGINX_NODE_END_BRACE.equals(line)) {
> +                        String[] prop =
> line.split(Constants.NGINX_SPACE_REGEX);
> +                        String value = line.substring(prop[0].length(),
> line.indexOf(Constants.NGINX_LINE_DELIMITER)).trim();
> +                        try {
> +                            aNode.addProperty(prop[0], value);
> +                        } catch (Exception e) {
> +                            String msg = "Malformatted property is
> defined in the configuration file. [" +
> +                                    i + "] \n";
> +                            log.error(msg, e);
> +                            throw new RuntimeException(msg + line, e);
> +                        }
> +                    }
> +                }
> +
> +            }
> +        }
> +
> +        return aNode;
> +
> +    }
> +
> +    public static Node buildNode(String content) {
> +           return buildNode(null, content);
> +    }
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
> ----------------------------------------------------------------------
> diff --git
> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
> new file mode 100755
> index 0000000..31e172d
> --- /dev/null
> +++
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
> @@ -0,0 +1,50 @@
> +/**
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF 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
> +
> + *  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 org.apache.stratos.load.balancer.conf.util;
> +
> +/**
> + * This keeps the element names used in loadbalancer.conf file
> + */
> +public class Constants {
> +
> +    public static final String LOAD_BALANCER_ELEMENT = "loadbalancer";
> +    public static final String SERVICES_ELEMENT = "services";
> +    public static final String DEFAULTS_ELEMENT = "defaults";
> +    public static final String HOSTS_ELEMENT = "hosts";
> +    public static final String HOSTS_DELIMITER = ",";
> +    public static final String DOMAIN_ELEMENT = "domains";
> +    public static final String TENANT_RANGE_ELEMENT = "tenant_range";
> +    public static final String SUB_DOMAIN_ELEMENT = "sub_domain";
> +    public static final String TENANT_RANGE_DELIMITER = "-";
> +    public static final String UNLIMITED_TENANT_RANGE = "*";
> +    public static final String AUTOSCALER_ENABLE_ELEMENT =
> "enable_autoscaler";
> +    public static final String SUB_DOMAIN_DELIMITER = "#";
> +    public static final String DEFAULT_SUB_DOMAIN = "__$default";
> +
> +    /* Nginx format related constants */
> +
> +    public static final String NGINX_COMMENT = "#";
> +    public static final String NGINX_NODE_START_BRACE = "{";
> +    public static final String NGINX_NODE_END_BRACE = "}";
> +    public static final String NGINX_VARIABLE = "${";
> +    public static final String NGINX_LINE_DELIMITER = ";";
> +    public static final String NGINX_SPACE_REGEX = "[\\s]+";
> +
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
> ----------------------------------------------------------------------
> diff --git
> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
> new file mode 100755
> index 0000000..ecd952a
> --- /dev/null
> +++
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
> @@ -0,0 +1,161 @@
> +/**
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF 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
> +
> + *  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 org.apache.stratos.load.balancer.conf.util;
> +
> +import java.util.Collection;
> +import java.util.HashMap;
> +import java.util.List;
> +import java.util.Map;
> +
> +import org.apache.synapse.endpoints.algorithms.AlgorithmContext;
> +import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
> +
> +/**
> + * For each unique host name defined in loadbalancer configuration, we'll
> generate
> + * this object.
> + */
> +public class HostContext {
> +
> +    /**
> +     * A unique identifier to identify this {@link #HostContext()}
> +     */
> +    private String hostName;
> +
> +    /**
> +     * Key - tenant id
> +     * Value - <code>TenantDomainContext</code> of the corresponding
> tenant
> +     */
> +    private Map<Integer, TenantDomainContext>
> tenantIdToTenantDomainContextMap = new HashMap<Integer,
> TenantDomainContext>();
> +
> +    /**
> +     * AlgorithmContext of this host
> +     */
> +    private AlgorithmContext algorithmContext;
> +
> +    /**
> +     * Load balance algorithm of this host
> +     */
> +    private LoadbalanceAlgorithm algorithm;
> +
> +    private String urlSuffix;
> +
> +    public HostContext(String hostName) {
> +        this.hostName = hostName;
> +    }
> +
> +    public void addTenantDomainContexts(List<TenantDomainContext> ctxts) {
> +
> +        for (TenantDomainContext tenantDomainContext : ctxts) {
> +
>  tenantIdToTenantDomainContextMap.put(tenantDomainContext.getTenantId(),
> tenantDomainContext);
> +        }
> +    }
> +
> +    @Deprecated
> +    public void addTenantDomainContext(TenantDomainContext ctxt) {
> +        tenantIdToTenantDomainContextMap.put(ctxt.getTenantId(), ctxt);
> +    }
> +
> +    public TenantDomainContext getTenantDomainContext(int tenantId) {
> +        return tenantIdToTenantDomainContextMap.get(tenantId);
> +    }
> +
> +    /**
> +     * Returns all the {@link
> org.apache.stratos.load.balancer.conf.util.TenantDomainContext} entries.
> +     */
> +    public Collection<TenantDomainContext> getTenantDomainContexts() {
> +        return tenantIdToTenantDomainContextMap.values();
> +    }
> +
> +    /**
> +     * Given a tenant id, this will return its domain.
> +     * @param tenantId
> +     * @return domain if this tenant has a dedicated one, it will be
> returned.
> +     * If not, and there's a default (*) domain, it will be returned.
> +     * If neither of the above is defined, null will be returned.
> +     */
> +    public String getDomainFromTenantId(int tenantId) {
> +        if (tenantIdToTenantDomainContextMap.get(tenantId) == null) {
> +            // if there's no specific domain for this tenant, we will
> redirect it to the default
> +            // cluster
> +
> +            if(tenantIdToTenantDomainContextMap.get(0) == null){
> +                return null;
> +            }
> +
> +            return tenantIdToTenantDomainContextMap.get(0).getDomain();
> +        }
> +
> +        return tenantIdToTenantDomainContextMap.get(tenantId).getDomain();
> +    }
> +
> +    /**
> +     * Given a tenant id, this will return its sub domain.
> +     * @param tenantId
> +     * @return sub_domain if this tenant has a dedicated one, it will be
> returned.
> +     * If not, and there's a default (*) sub domain, it will be returned.
> +     * If neither of the above is defined, null will be returned.
> +     */
> +    public String getSubDomainFromTenantId(int tenantId) {
> +        if (tenantIdToTenantDomainContextMap.get(tenantId) == null) {
> +            // if there's no specific domain for this tenant, we will
> redirect it to the default
> +            // cluster
> +
> +            if(tenantIdToTenantDomainContextMap.get(0) == null){
> +                return null;
> +            }
> +
> +            return tenantIdToTenantDomainContextMap.get(0).getSubDomain();
> +        }
> +
> +        return
> tenantIdToTenantDomainContextMap.get(tenantId).getSubDomain();
> +    }
> +
> +    public String getHostName() {
> +        return hostName;
> +    }
> +
> +    public LoadbalanceAlgorithm getAlgorithm() {
> +        return algorithm;
> +    }
> +
> +    public AlgorithmContext getAlgorithmContext() {
> +        return algorithmContext;
> +    }
> +
> +    public void setAlgorithmContext(AlgorithmContext algorithmContext) {
> +        this.algorithmContext = algorithmContext;
> +    }
> +
> +    public void setAlgorithm(LoadbalanceAlgorithm algorithm) {
> +        this.algorithm = algorithm;
> +    }
> +
> +    public Map<Integer, TenantDomainContext>
> getTenantIdToTenantDomainContextMap() {
> +        return tenantIdToTenantDomainContextMap;
> +    }
> +
> +    public void setUrlSuffix(String suffix)  {
> +        this.urlSuffix = suffix;
> +    }
> +
> +    public String getUrlSuffix() {
> +        return this.urlSuffix;
> +    }
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
> ----------------------------------------------------------------------
> diff --git
> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
> new file mode 100755
> index 0000000..fe432c9
> --- /dev/null
> +++
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
> @@ -0,0 +1,305 @@
> +/**
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF 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
> +
> + *  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 org.apache.stratos.load.balancer.conf.util;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +import org.apache.synapse.SynapseException;
> +import sun.misc.BASE64Encoder;
> +
> +import java.io.File;
> +import java.io.FileInputStream;
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.util.ArrayList;
> +import java.util.List;
> +
> +/**
> + * Utility methods for Autoscale mediator
> + */
> +public final class LoadBalancerConfigUtil {
> +
> +    private static final Log log =
> LogFactory.getLog(LoadBalancerConfigUtil.class);
> +
> +    private LoadBalancerConfigUtil() {
> +    }
> +
> +    /**
> +     * handles the exception
> +     *
> +     * @param msg
> +     *            exception message
> +     */
> +    public static void handleException(String msg) {
> +        log.error(msg);
> +        throw new RuntimeException(msg);
> +    }
> +
> +    /**
> +     * handles the exception
> +     *
> +     * @param msg
> +     *            exception message
> +     * @param e
> +     *            exception
> +     */
> +    public static void handleException(String msg, Exception e) {
> +        log.error(msg, e);
> +        throw new SynapseException(msg, e);
> +    }
> +
> +    /**
> +     * Replaces the variables
> +     *
> +     * @param text
> +     *            input string
> +     * @return output String
> +     */
> +    public static String replaceVariables(String text) {
> +        int indexOfStartingChars;
> +        int indexOfClosingBrace;
> +
> +        // The following condition deals with properties.
> +        // Properties are specified as ${system.property},
> +        // and are assumed to be System properties
> +        if ((indexOfStartingChars = text.indexOf("${")) != -1 &&
> +            (indexOfClosingBrace = text.indexOf("}")) != -1) { // Is a
> property used?
> +            String var = text.substring(indexOfStartingChars + 2,
> indexOfClosingBrace);
> +
> +            String propValue = System.getProperty(var);
> +            if (propValue == null) {
> +                propValue = System.getenv(var);
> +            }
> +            if (propValue != null) {
> +                text =
> +                       text.substring(0, indexOfStartingChars) +
> propValue +
> +                               text.substring(indexOfClosingBrace + 1);
> +            }
> +        }
> +        return text;
> +    }
> +
> +    public static String getUserData(String payloadFileName) {
> +        String userData = null;
> +        try {
> +            File file = new File(payloadFileName);
> +            if (!file.exists()) {
> +                handleException("Payload file " + payloadFileName + "
> does not exist");
> +            }
> +            if (!file.canRead()) {
> +                handleException("Payload file " + payloadFileName + "
> does cannot be read");
> +            }
> +            byte[] bytes = LoadBalancerConfigUtil.getBytesFromFile(file);
> +            if (bytes != null) {
> +                BASE64Encoder encoder = new BASE64Encoder();
> +                userData = encoder.encode(bytes);
> +            }
> +        } catch (Exception e) {
> +            LoadBalancerConfigUtil.handleException("Cannot read data from
> payload file " +
> +                                                   payloadFileName, e);
> +
> +        }
> +        return userData;
> +    }
> +
> +    /**
> +     * Returns the contents of the file in a byte array
> +     *
> +     * @param file
> +     *            - Input File
> +     * @return Bytes from the file
> +     * @throws java.io.IOException
> +     *             , if retrieving the file contents failed.
> +     */
> +    public static byte[] getBytesFromFile(File file) throws IOException {
> +        if (!file.exists()) {
> +            log.error("Payload file " + file.getAbsolutePath() + " does
> not exist");
> +            return null;
> +        }
> +        InputStream is = new FileInputStream(file);
> +        byte[] bytes;
> +
> +        try {
> +            // Get the size of the file
> +            long length = file.length();
> +
> +            // You cannot create an array using a long type.
> +            // It needs to be an int type.
> +            // Before converting to an int type, check
> +            // to ensure that file is not larger than Integer.MAX_VALUE.
> +            if (length > Integer.MAX_VALUE) {
> +                if (log.isDebugEnabled()) {
> +                    log.debug("File is too large");
> +                }
> +            }
> +
> +            // Create the byte array to hold the data
> +            bytes = new byte[(int) length];
> +
> +            // Read in the bytes
> +            int offset = 0;
> +            int numRead;
> +            while (offset < bytes.length &&
> +                   (numRead = is.read(bytes, offset, bytes.length -
> offset)) >= 0) {
> +                offset += numRead;
> +            }
> +
> +            // Ensure all the bytes have been read in
> +            if (offset < bytes.length) {
> +                throw new IOException("Could not completely read file " +
> file.getName());
> +            }
> +        } finally {
> +            // Close the input stream and return bytes
> +            is.close();
> +        }
> +
> +        return bytes;
> +    }
> +
> +    /**
> +     * @deprecated
> +     *             Extract the domain part given a string which is in
> +     *             &lt;sub_domain&gt;#&lt;domain&gt; format.
> +     * @param str
> +     *            in &lt;sub_domain&gt;#&lt;domain&gt; format.
> +     * @return the domain part. If # is not present this will return the
> trimmed
> +     *         input string.
> +     */
> +    public static String getDomain(String str) {
> +        str = str.trim();
> +        if (!str.contains(Constants.SUB_DOMAIN_DELIMITER)) {
> +            return str;
> +        }
> +        return str.substring(str.indexOf(Constants.SUB_DOMAIN_DELIMITER)
> + 1);
> +    }
> +
> +    /**
> +     * @deprecated
> +     *             Extract the sub_domain part given a string which is in
> +     *             &lt;sub_domain&gt;#&lt;domain&gt; format.
> +     * @param str
> +     *            in &lt;sub_domain&gt;#&lt;domain&gt; format.
> +     * @return the sub_domain part. If # is not present this will return
> <code>null</code>.
> +     */
> +    public static String getSubDomain(String str) {
> +        str = str.trim();
> +        if (!str.contains(Constants.SUB_DOMAIN_DELIMITER)) {
> +            return null;
> +        }
> +        return str.substring(0,
> str.indexOf(Constants.SUB_DOMAIN_DELIMITER));
> +    }
> +
> +    // public static EC2InstanceManager createEC2InstanceManager(String
> accessKey,
> +    // String secretKey,
> +    // String instanceMgtEPR) {
> +    // AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey,
> secretKey);
> +    // AmazonEC2Client ec2Client = new AmazonEC2Client(awsCredentials);
> +    // ec2Client.setEndpoint(instanceMgtEPR);
> +    // return new EC2InstanceManager(ec2Client);
> +    // }
> +
> +    public static List<TenantDomainContext>
> getTenantDomainContexts(String tenantRange, String domain, String
> subDomain) {
> +
> +        List<TenantDomainContext> ctxts = new
> ArrayList<TenantDomainContext>();
> +        List<Integer> tenantIds = getTenantIds(tenantRange);
> +
> +        // iterate through all tenant ids under this host
> +        for (Integer tId : tenantIds) {
> +
> +            // create a new TenantDomainContext
> +            TenantDomainContext tenantCtxt =
> +                                             new TenantDomainContext(
> +                                                                     tId,
> +
> domain,
> +
> subDomain);
> +            // add it to the list
> +            ctxts.add(tenantCtxt);
> +        }
> +
> +        return ctxts;
> +
> +    }
> +
> +    /**
> +     * This method will read the tenant range string and return a list of
> tenant ids
> +     * which is derived from tenant range string.
> +     *
> +     * @param tenantRange
> +     * @return list of tenant ids.
> +     */
> +    public static List<Integer> getTenantIds(String tenantRange) {
> +
> +        List<Integer> tenantIds = new ArrayList<Integer>();
> +
> +        String[] parsedLine = tenantRange.trim().split("-");
> +
> +        if (parsedLine[0].equalsIgnoreCase("*")) {
> +            tenantIds.add(0);
> +
> +               } else if (parsedLine.length == 1) {
> +                       // if there aren't any hyphens in the string, try
> to see whether
> +                       // this is a list of ids
> +                       parsedLine = tenantRange.trim().split(",");
> +
> +                       // if there aren't any commas in the string, we
> assume this to be a
> +                       // one single integer.
> +                       if (parsedLine.length == 1) {
> +                               try {
> +                                       int tenantId =
> Integer.parseInt(tenantRange);
> +                                       tenantIds.add(tenantId);
> +
> +                               } catch (NumberFormatException e) {
> +                                       String msg = "Invalid tenant range
> is specified : "
> +                                                       + tenantRange;
> +                                       log.error(msg, e);
> +                                       throw new RuntimeException(msg, e);
> +                               }
> +                       } else {
> +                               for (int i = 0; i < parsedLine.length;
> i++) {
> +                                       int tenantId =
> Integer.parseInt(parsedLine[i]);
> +                                       tenantIds.add(tenantId);
> +                               }
> +                       }
> +               } else if (parsedLine.length == 2) {
> +            try {
> +
> +                int startIndex = Integer.parseInt(parsedLine[0]);
> +                int endIndex = Integer.parseInt(parsedLine[1]);
> +
> +                for (int tenantId = startIndex; tenantId <= endIndex;
> tenantId++) {
> +
> +                    tenantIds.add(tenantId);
> +                }
> +
> +            } catch (NumberFormatException e) {
> +                String msg = "Invalid tenant range is specified : " +
> tenantRange;
> +                log.error(msg, e);
> +                throw new RuntimeException(msg, e);
> +            }
> +
> +        } else {
> +            String msg = "Invalid tenant range is specified : " +
> tenantRange;
> +            log.error(msg);
> +            throw new RuntimeException(msg);
> +        }
> +
> +        return tenantIds;
> +    }
> +
> +}
> \ No newline at end of file
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
> ----------------------------------------------------------------------
> diff --git
> a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
> new file mode 100755
> index 0000000..33162c5
> --- /dev/null
> +++
> b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
> @@ -0,0 +1,80 @@
> +/**
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF 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
> +
> + *  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 org.apache.stratos.load.balancer.conf.util;
> +
> +/**
> + * This object will hold all the data related to a tenant.
> + */
> +public class TenantDomainContext {
> +
> +    /**
> +     * this is the unique identifier for this object
> +     */
> +    private int tenantId;
> +
> +    /**
> +     * Domain, which this tenant belongs to.
> +     */
> +    private String domain;
> +
> +    /**
> +     * Sub domain, which this tenant belongs to.
> +     */
> +    private String subDomain;
> +
> +    public TenantDomainContext(int tenantId, String domain, String
> subDomain) {
> +        this.tenantId = tenantId;
> +        this.domain = domain;
> +        this.subDomain = subDomain;
> +    }
> +
> +
> +    /** Getters and Setters **/
> +
> +    public int getTenantId() {
> +        return tenantId;
> +    }
> +
> +    public void setTenantId(int tenantId) {
> +        this.tenantId = tenantId;
> +    }
> +
> +    public String getDomain() {
> +        return domain;
> +    }
> +
> +    public void setDomain(String domain) {
> +        this.domain = domain;
> +    }
> +
> +    public String getSubDomain() {
> +        return subDomain;
> +    }
> +
> +    public void setSubDomain(String subDomain) {
> +        this.subDomain = subDomain;
> +    }
> +
> +
> +    /** End of Getters and Setters **/
> +
> +
> +
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
> ----------------------------------------------------------------------
> diff --git
> a/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
> b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
> new file mode 100755
> index 0000000..c94b54c
> --- /dev/null
> +++
> b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
> @@ -0,0 +1,48 @@
> +/**
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF 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
> +
> + *  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 org.apache.stratos.load.balancer.test;
> +
> +import java.util.Arrays;
> +import java.util.List;
> +
> +import org.apache.stratos.load.balancer.conf.util.LoadBalancerConfigUtil;
> +
> +import junit.framework.TestCase;
> +
> +public class LoadBalancerConfigUtilTest extends TestCase {
> +
> +    private List<Integer> tenantList1 = Arrays.asList(1,2,3);
> +    private List<Integer> tenantList2 = Arrays.asList(1,6,3,4);
> +    private List<Integer> tenantList3 = Arrays.asList(43);
> +    private List<Integer> tenantList4 = Arrays.asList(0);
> +
> +    @Override
> +    protected void setUp() throws Exception {
> +
> +    }
> +
> +    public final void testGetTenantIds() {
> +
> +        assertEquals(tenantList1,
> LoadBalancerConfigUtil.getTenantIds("1-3"));
> +        assertEquals(tenantList2,
> LoadBalancerConfigUtil.getTenantIds("1,6,3,4"));
> +        assertEquals(tenantList3,
> LoadBalancerConfigUtil.getTenantIds("43"));
> +        assertEquals(tenantList4,
> LoadBalancerConfigUtil.getTenantIds("*"));
> +    }
> +
> +}
>
>

[2/3] git commit: Added load balancer configuration parser and its test cases from lb.common component

Posted by im...@apache.org.
Added load balancer configuration parser and its test cases from lb.common component


Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/32565547
Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/32565547
Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/32565547

Branch: refs/heads/master
Commit: 32565547050e49e89dd8b76e1fcace9504e89c69
Parents: 59811f9
Author: Imesh Gunaratne <im...@apache.org>
Authored: Sun Nov 10 22:37:36 2013 +0530
Committer: Imesh Gunaratne <im...@apache.org>
Committed: Sun Nov 10 22:37:36 2013 +0530

----------------------------------------------------------------------
 .../conf/LoadBalancerConfiguration.java         | 1202 ++++++++++++++++++
 .../load/balancer/conf/structure/Node.java      |  356 ++++++
 .../balancer/conf/structure/NodeBuilder.java    |  140 ++
 .../load/balancer/conf/util/Constants.java      |   50 +
 .../load/balancer/conf/util/HostContext.java    |  161 +++
 .../conf/util/LoadBalancerConfigUtil.java       |  305 +++++
 .../balancer/conf/util/TenantDomainContext.java |   80 ++
 .../test/LoadBalancerConfigUtilTest.java        |   48 +
 .../test/LoadBalancerConfigurationTest.java     |  169 +++
 .../load/balancer/test/NodeBuilderTest.java     |  123 ++
 .../src/test/resources/loadbalancer.conf        |   84 ++
 .../src/test/resources/loadbalancer1.conf       |   60 +
 .../src/test/resources/loadbalancer2.conf       |   50 +
 .../src/test/resources/testng.xml               |   29 +
 14 files changed, 2857 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
new file mode 100755
index 0000000..747ba5b
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
@@ -0,0 +1,1202 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.conf;
+
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.synapse.commons.util.PropertyHelper;
+import org.apache.stratos.load.balancer.conf.structure.Node;
+import org.apache.stratos.load.balancer.conf.structure.NodeBuilder;
+import org.apache.stratos.load.balancer.conf.util.Constants;
+import org.apache.stratos.load.balancer.conf.util.HostContext;
+import org.apache.stratos.load.balancer.conf.util.LoadBalancerConfigUtil;
+import org.apache.stratos.load.balancer.conf.util.TenantDomainContext;
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * Data object which hold configuration data of the load analyzer task
+ */
+@SuppressWarnings("unused")
+public class LoadBalancerConfiguration implements Serializable {
+
+    protected static final long serialVersionUID = -5553545217542808233L;
+
+    private static final Log log = LogFactory.getLog(LoadBalancerConfiguration.class);
+
+    /**
+     * This map is there to speed up the lookup time.
+     * Key: domain
+     * <p/>
+     * Value: A map whose key is sub domain and value is ServiceConfiguration
+     */
+    private Map<String, Map<String, ServiceConfiguration>> serviceConfigurations =
+            new HashMap<String, Map<String, ServiceConfiguration>>();
+    
+    /**
+     * Key - host name
+     * Value - {@link org.apache.stratos.load.balancer.conf.util.HostContext}
+     */
+    private transient Map<String, HostContext> hostCtxt = new HashMap<String, HostContext>();
+    
+    /**
+     * This map is there to speed up the lookup time.
+     * Key: service name/cartridge type (Stratos2). NOTE: that this is not the service cluster domain.
+     * Value: list of {@link org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration.ServiceConfiguration} - corresponding objects under a service name.
+     */
+	private Map<String, List<ServiceConfiguration>> serviceNameToServiceConfigurations =
+			new HashMap<String, List<ServiceConfiguration>>();
+
+    /**
+     * This list will be used to identify host name duplications among different services.
+     * Within a service there can be duplications, but among different services you can't have duplications.
+     * Key - service name
+     * Value - hosts under the respective service.
+     */
+    private Map<String, Set<String>> hostNamesTracker = new HashMap<String, Set<String>>();
+
+    protected ServiceConfiguration defaultServiceConfig;
+    protected LBConfiguration lbConfig;
+
+    /**
+     * LBConfig file as a String
+     */
+    protected String lbConfigString;
+
+    /**
+     * Root node object for loadbalancer.conf
+     */
+    protected Node rootNode;
+
+    private LoadBalancerConfiguration(){
+        init(System.getProperty("loadbalancer.conf"));
+    }
+
+    private static LoadBalancerConfiguration instance ;
+    
+    public static LoadBalancerConfiguration getInstance(){
+        if(instance == null){
+            instance = new LoadBalancerConfiguration();
+        }
+        return instance;
+    }
+
+    /**
+     * Sample loadbalancer.conf:
+     * <p/>
+     * loadbalancer {
+     * # minimum number of load balancer instances
+     * instances           1;
+     * # whether autoscaling enable or not
+     * enable_autoscaler   true;
+     * # End point reference of the Autoscaler Service
+     * autoscaler_service_epr  https://10.100.3.81:9443/services/AutoscalerService/;
+     * # interval between two task executions in milliseconds
+     * autoscaler_task_interval 1000;
+     * # after an instance booted up, task will wait till this much of time and let the server started up
+     * server_startup_delay 15000;
+     * }
+     * <p/>
+     * services {
+     * defaults {
+     * min_app_instances       1;
+     * max_app_instances       5;
+     * queue_length_per_node   400;
+     * rounds_to_average       10;
+     * instances_per_scale_up  1;
+     * message_expiry_time     60000;
+     * }
+     * <p/>
+     * appserver {
+     * hosts                   appserver.cloud-test.wso2.com,as.cloud-test.wso2.com;
+     * domains   {
+     * wso2.as1.domain {
+     * tenant_range    1-100;
+     * }
+     * wso2.as2.domain {
+     * tenant_range    101-200;
+     * }
+     * wso2.as3.domain {
+     * tenant_range    *;
+     * }
+     * }
+     * }
+     * }
+     *
+     * @param configURL URL of the load balancer config
+     */
+    public void init(String configURL) {
+
+        if(configURL == null){
+            String msg = "Cannot locate the location of the loadbalancer.conf file." +
+                   " You need to set the 'loadbalancer.conf' system property.";
+            log.error(msg);
+            throw new RuntimeException(msg);
+        }
+        
+        if (configURL.startsWith("$system:")) {
+            configURL = System.getProperty(configURL.substring("$system:".length()));
+        }
+
+        try {
+
+            // get loadbalancer.conf file as a String
+            if (configURL.startsWith(File.separator)) {
+                lbConfigString = createLBConfigString(configURL);
+            } else {
+                lbConfigString = createLBConfigString(new URL(configURL).openStream());
+            }
+
+        } catch (Exception e) {
+            String msg = "Cannot read configuration file from " + configURL;
+            log.error(msg, e);
+            throw new RuntimeException(msg, e);
+        }
+
+        // build a Node object for whole loadbalancer.conf
+        rootNode = new Node();
+        rootNode.setName("root");
+        rootNode = NodeBuilder.buildNode(rootNode, lbConfigString);
+
+        // load 'loadbalancer' node
+        Node lbConfigNode = rootNode.findChildNodeByName(Constants.LOAD_BALANCER_ELEMENT);
+
+        if(lbConfigNode != null){
+        	createConfiguration(lbConfig = new LBConfiguration(), lbConfigNode);
+        }
+
+        // load services node
+        Node servicesConfigNode = rootNode.findChildNodeByName(Constants.SERVICES_ELEMENT);
+
+        if (servicesConfigNode == null) {
+            String msg = "Mandatory " + Constants.SERVICES_ELEMENT +
+                    " element can not be found in the configuration file.";
+            log.error(msg);
+            throw new RuntimeException(msg);
+        }
+
+        // Set services configuration
+        createServicesConfig(servicesConfigNode);
+
+    }
+
+
+    /**
+     * Process the content of the following 'services' element
+     * <p/>
+     * services {
+     * defaults {
+     * min_app_instances       1;
+     * max_app_instances       5;
+     * queue_length_per_node   400;
+     * rounds_to_average       10;
+     * instances_per_scale_up  1;
+     * message_expiry_time     60000;
+     * }
+     * <p/>
+     * appserver {
+     * hosts                   appserver.cloud-test.wso2.com,as.cloud-test.wso2.com;
+     * domains   {
+     * wso2.as1.domain {
+     * tenant_range    1-100;
+     * }
+     * wso2.as2.domain {
+     * tenant_range    101-200;
+     * }
+     * wso2.as3.domain {
+     * tenant_range    *;
+     * }
+     * }
+     * }
+     * }
+     *
+     * @param servicesConfigNode services element's Node
+     */
+    public List<ServiceConfiguration> createServicesConfig(Node servicesConfigNode) {
+
+        // current list of service configs
+        List<ServiceConfiguration> currentServiceConfigs = new ArrayList<ServiceConfiguration>();
+        
+        // Building default configuration
+        Node defaultNode = servicesConfigNode.findChildNodeByName(Constants.DEFAULTS_ELEMENT);
+
+        if (defaultNode != null) {
+
+            createConfiguration(defaultServiceConfig = new ServiceConfiguration(), defaultNode);
+        }
+
+        // Building custom services configuration
+        for (Node serviceNode : servicesConfigNode.getChildNodes()) {
+            //skip default node
+            if (serviceNode != defaultNode) {
+
+                String serviceName = serviceNode.getName();
+
+                // reading domains
+
+                Node domainsNode;
+
+                if (serviceNode.getChildNodes().isEmpty() ||
+                        !(domainsNode = serviceNode.getChildNodes().get(0)).getName().equals(
+                                Constants.DOMAIN_ELEMENT)) {
+
+                    String msg = "The mandatory domains element, child of the " + serviceName +
+                            " element is not specified in the configuration file. \n"+
+                            serviceNode.toString();
+                    log.error(msg);
+                    throw new RuntimeException(msg);
+                }
+
+                if (domainsNode.getChildNodes().isEmpty()) {
+                    // this is probably a mistake, so we don't proceed
+                    String msg = "No domain is specified under " + Constants.DOMAIN_ELEMENT +
+                            " of " + serviceName + " element.";
+                    log.error(msg);
+                    throw new RuntimeException(msg);
+                }
+
+                ServiceConfiguration serviceConfig;
+
+                // iterates through all the service domain specified in this service element. 
+                for (Node domain : domainsNode.getChildNodes()) {
+
+                    // create a new service configuration
+                    serviceConfig = new ServiceConfiguration();
+
+                    // set service name
+                    serviceConfig.setServiceName(serviceName);
+                    
+                    // set domain name
+                    serviceConfig.setDomain(domain.getName());
+
+                    // let's set properties common to all domains specified in this service element.
+                    createConfiguration(serviceConfig, serviceNode);
+
+                    // load properties specified under this service domain element.
+                    createConfiguration(serviceConfig, domain);
+
+                    // check host name duplication 
+                    if(isDuplicatedHost(serviceNode.getName(), serviceConfig)){
+                        // this is probably a mistake, so we don't proceed
+                        String msg = "Duplicated host names detected for different service domains.\n" +
+                                "Element: \n"+serviceNode.toString();
+                        log.error(msg);
+                        throw new RuntimeException(msg);
+                    }
+                    
+                    currentServiceConfigs.add(serviceConfig);
+
+                }
+            }
+        }
+
+        for (ServiceConfiguration serviceConfiguration : currentServiceConfigs) {
+            
+            // add the built ServiceConfiguration, to the map
+            addServiceConfiguration(serviceConfiguration);
+            
+        }
+        
+        return currentServiceConfigs;
+
+    }
+
+
+    public boolean addServiceConfiguration(ServiceConfiguration serviceConfig) {
+
+        Map<String, ServiceConfiguration> map;
+        String domain = serviceConfig.getDomain();
+        
+        if(domain == null){
+            String msg = "Domain of a Service Configuration cannot be null. Hence this " +
+            		"Configuration will be neglected.";
+            log.error(msg);
+            return false;
+        }
+        
+        String subDomain = serviceConfig.getSubDomain();
+
+        if (serviceConfigurations.containsKey(domain)) {
+            map = serviceConfigurations.get(domain);
+        } else {
+            map = new HashMap<String, ServiceConfiguration>();
+        }
+        // put this serviceConfig
+        map.put(subDomain, serviceConfig);
+
+        // update the parent map
+        serviceConfigurations.put(domain, map);
+        
+        // add to serviceNameToServiceConfiguration map
+        List<ServiceConfiguration> configs;
+        if(serviceNameToServiceConfigurations.get(serviceConfig.getServiceName()) == null){
+        	configs = new ArrayList<ServiceConfiguration>();
+        	
+        }else{
+        	configs = serviceNameToServiceConfigurations.get(serviceConfig.getServiceName());
+        }
+        
+        if(!configs.contains(serviceConfig)){
+        	configs.add(serviceConfig);
+        }
+        serviceNameToServiceConfigurations.put(serviceConfig.getServiceName(), configs);
+        
+        return true;
+    }
+    
+    public ServiceConfiguration removeServiceConfiguration(String domain, String subDomain) {
+
+        Map<String, ServiceConfiguration> map;
+        ServiceConfiguration serviceConfig = null;
+        
+        if(domain == null){
+            String msg = "Domain of a Service Configuration cannot be null. Hence this " +
+            		"Configuration will be neglected.";
+            log.error(msg);
+            return null;
+        }
+
+        if (serviceConfigurations.containsKey(domain)) {
+            map = serviceConfigurations.get(domain);
+            
+            if(map != null){
+            	serviceConfig = map.remove(subDomain);
+            }
+        } 
+        
+        if(serviceConfig == null){
+        	String msg = "No matching service configuration found for domain: "+domain+
+        			", sub domain: "+subDomain;
+            log.error(msg);
+        	return null;
+        }
+        
+        String serviceName = serviceConfig.getServiceName();
+        
+        if (serviceName != null && serviceNameToServiceConfigurations.containsKey(serviceName)) {
+            if(serviceConfig != null){
+            	List<ServiceConfiguration> list = serviceNameToServiceConfigurations.get(serviceName);
+            	
+            	list.remove(serviceConfig);
+            	
+            	serviceNameToServiceConfigurations.put(serviceName, list);
+            }
+        } 
+        
+        Set<String> allHosts;
+
+        if (hostNamesTracker.containsKey(serviceName)) {
+            allHosts = hostNamesTracker.get(serviceName);
+            
+            for (String hostName : serviceConfig.getHosts()) {
+	            
+				if (hostName != null) {
+					
+					allHosts.remove(hostName);
+
+					hostCtxt.remove(hostName);
+				}
+            }
+        }
+        
+        return serviceConfig;
+    }
+    
+    public void resetData(){
+    	serviceConfigurations =
+                new HashMap<String, Map<String, ServiceConfiguration>>();
+    	
+    	serviceNameToServiceConfigurations =
+    			new HashMap<String, List<ServiceConfiguration>>();
+    	
+    }
+
+
+    /**
+     * Duplications can only be seen, when you traverse down the configuration file.
+     * 
+     */
+    public boolean isDuplicatedHost(String name, ServiceConfiguration serviceConfig) {
+
+        /**
+         * This will be populated with host names of all other services other than the
+         * service subjected to the test.
+         */
+        List<String> hostsOtherThanMine = new ArrayList<String>(hostNamesTracker.values().size());
+
+        for (Map.Entry<String, Set<String>> entry : hostNamesTracker.entrySet()) {
+            if (!entry.getKey().equals(name)) {
+                hostsOtherThanMine.addAll(entry.getValue());
+            }
+        }
+
+        for (String host : serviceConfig.getHosts()) {
+            if (!hostsOtherThanMine.isEmpty() && hostsOtherThanMine.contains(host)) {
+                return true;
+            }
+        }
+
+        addToHostNameTrackerMap(name, serviceConfig.getHosts());
+
+        return false;
+    }
+
+
+    public void addToHostNameTrackerMap(String name, List<String> hosts) {
+
+        Set<String> allHosts;
+
+        if (hostNamesTracker.containsKey(name)) {
+            allHosts = hostNamesTracker.get(name);
+            allHosts.addAll(hosts);
+        } else {
+            allHosts = new HashSet<String>(hosts);
+        }
+        hostNamesTracker.put(name, allHosts);
+    }
+    
+    public void addToHostContextMap(String hostName, HostContext ctxt) {
+
+        if (hostName != null && ctxt != null) {
+            hostCtxt.put(hostName, ctxt);
+        }
+    }
+    
+    /**
+     * Return a map of {@link org.apache.stratos.load.balancer.conf.util.HostContext}.
+     * @return
+     */
+    public Map<String, HostContext> getHostContextMap() {
+
+        List<Integer> tenantIds;
+        Map<String, String> URLSuffixes;
+
+        // FIXME if possible! I couldn't think of any other way to do this, at this moment.
+        // Note: some of these for-loops are pretty small, thus no considerable performance overhead.
+        // iterate through each service
+        for (Iterator<Set<String>> it = hostNamesTracker.values().iterator(); it.hasNext();) {
+
+            // iterate through host names of this service
+            for (String hostName : ((Set<String>) it.next())) {
+                                                                  
+                // building HostContext
+                HostContext ctxt = new HostContext(hostName);
+
+                // iterate through domains of this host
+                for (Map.Entry<String, Map<String, ServiceConfiguration>> parentMap : serviceConfigurations.entrySet()) {
+
+                    // iterate through sub domain of this domain
+                    for (Map.Entry<String, ServiceConfiguration> childMap : parentMap.getValue()
+                            .entrySet()) {
+                        // iterate through hosts of this
+                        for (String host : childMap.getValue().getHosts()) {
+                            // if a matching Service configuration is found.
+                            if (host.equals(hostName)) {
+                                
+                                String tenantRange = childMap.getValue().getTenantRange();
+                                String domain = parentMap.getKey();
+                                String subDomain = childMap.getKey();
+                                          
+                                ctxt.addTenantDomainContexts(LoadBalancerConfigUtil.getTenantDomainContexts(tenantRange, domain, subDomain));
+
+                                break;
+                            }
+                        }
+                        
+                        //iterate through URL suffixes
+                        for(Map.Entry<String, String> entry : childMap.getValue().getUrl_suffix().entrySet()) {
+                            if(entry.getKey().equals(hostName)) {
+                                
+                                ctxt.setUrlSuffix(entry.getValue());
+                                
+                                break;
+                            }
+
+                        }
+                    }
+                }
+
+                // add this hostCtxt
+                hostCtxt.put(hostName, ctxt);
+            }
+
+        }
+
+        return hostCtxt;
+
+    }
+
+    protected void createConfiguration(Configuration config, Node node) {
+
+        if (node == null) {
+            String msg = "The configuration element for " +
+                    config.getClass().getName() + " is null.";
+            throw new RuntimeException(msg);
+        }
+
+        try {
+            // load properties
+            for (Map.Entry<String, String> entry : node.getProperties().entrySet()) {
+                String key = entry.getKey();
+                String value = entry.getValue();
+
+                PropertyHelper.setInstanceProperty(key, value, config);
+            }
+
+        } catch (Exception e) {
+            String msg = "Error setting values to " + config.getClass().getName();
+            log.error(msg, e);
+            throw new RuntimeException(msg, e);
+        }
+    }
+
+    public LBConfiguration getLoadBalancerConfig() {
+        return lbConfig;
+    }
+
+    public String[] getServiceDomains() {
+
+        Object[] objs = serviceConfigurations.keySet().toArray();
+
+        return Arrays.copyOf(objs, objs.length, String[].class);
+
+    }
+
+    public String[] getServiceSubDomains(String domain) {
+
+        if (serviceConfigurations.get(domain) != null) {
+            Object[] objs = serviceConfigurations.get(domain).keySet().toArray();
+            return Arrays.copyOf(objs, objs.length, String[].class);
+        }
+
+        return new String[0];
+    }
+
+    public ServiceConfiguration getServiceConfig(String domain, String subDomain) {
+        if (serviceConfigurations.get(domain) != null) {
+            return serviceConfigurations.get(domain).get(subDomain);
+        }
+        return null;
+    }
+    
+    
+    public List<ServiceConfiguration> getServiceConfigs(String serviceName) {
+        return serviceNameToServiceConfigurations.get(serviceName);
+    }
+
+    /**
+     * Convert given configuration file to a single String
+     *
+     * @param configFileName - file name to convert
+     * @return String with complete lb configuration
+     * @throws java.io.FileNotFoundException
+     */
+    public String createLBConfigString(String configFileName) throws FileNotFoundException {
+        StringBuilder lbConfigString = new StringBuilder("");
+
+        File configFile = new File(configFileName);
+        Scanner scanner;
+
+        scanner = new Scanner(configFile);
+
+        while (scanner.hasNextLine()) {
+            lbConfigString.append(scanner.nextLine().trim() + "\n");
+        }
+
+        return lbConfigString.toString().trim();
+    }
+
+    public String createLBConfigString(InputStream configFileName) throws IOException {
+
+        // read the stream with BufferedReader
+        BufferedReader br = new BufferedReader(new InputStreamReader(configFileName));
+
+        StringBuilder sb = new StringBuilder();
+
+        String line;
+        while ((line = br.readLine()) != null) {
+            sb.append(line.trim() + "\n");
+        }
+
+        return sb.toString().trim();
+    }
+
+    public abstract class Configuration implements Serializable {
+
+        private static final long serialVersionUID = -5433889427746551250L;
+        protected String imageId = System.getenv("ami_id");
+        protected String payload;
+        protected boolean payloadSet;
+
+        protected String availability_zone = "us-east-1c";
+        protected boolean availabilityZoneSet;
+
+        protected String[] security_groups = new String[]{"default"};
+        protected boolean securityGroupsSet;
+
+        protected String instance_type = "m1.large";
+        protected boolean instanceTypeSet;
+
+        protected String additional_info;
+
+        public String getImageId() {
+            return imageId;
+        }
+
+        public String getAdditionalInfo() {
+            return additional_info;
+        }
+
+        public String getAvailability_zone() {
+            if (this instanceof LBConfiguration) {
+                return availability_zone;
+            }
+            if (availabilityZoneSet) {
+                return availability_zone;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.availabilityZoneSet) {
+                return defaultServiceConfig.availability_zone;
+            }
+            return availability_zone;
+        }
+
+        public String[] getSecurityGroups() {
+            if (this instanceof LBConfiguration) {
+                return security_groups;
+            }
+            if (securityGroupsSet) {
+                return security_groups;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.securityGroupsSet) {
+                return defaultServiceConfig.security_groups;
+            }
+            return security_groups;
+        }
+
+        public String getInstanceType() {
+            if (this instanceof LBConfiguration) {
+                return instance_type;
+            }
+            if (instanceTypeSet) {
+                return instance_type;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.instanceTypeSet) {
+                return defaultServiceConfig.instance_type;
+            }
+            return instance_type;
+        }
+
+
+        public String getUserData() {
+            if (payload == null) {
+                payload = LoadBalancerConfigUtil.getUserData("resources/cluster_node.zip");
+            }
+            if (this instanceof LBConfiguration) {
+                return payload;
+            }
+            if (payloadSet) {
+                return payload;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.payloadSet) {
+                return defaultServiceConfig.payload;
+            }
+            return payload;
+        }
+
+        public void setPayload(String payload) {
+            this.payload = LoadBalancerConfigUtil.getUserData(LoadBalancerConfigUtil.replaceVariables(payload));
+            this.payloadSet = true;
+        }
+
+        public void setAvailability_zone(String availabilityZone) {
+            this.availability_zone = LoadBalancerConfigUtil.replaceVariables(availabilityZone);
+            this.availabilityZoneSet = true;
+        }
+
+        public void setSecurity_groups(String securityGroups) {
+            this.security_groups = LoadBalancerConfigUtil.replaceVariables(securityGroups).split(",");
+            this.securityGroupsSet = true;
+        }
+
+        public void setInstance_type(String instanceType) {
+            this.instance_type = LoadBalancerConfigUtil.replaceVariables(instanceType);
+            this.instanceTypeSet = true;
+        }
+
+    }
+
+    public class LBConfiguration extends Configuration implements Serializable {
+
+        private static final long serialVersionUID = 1357143883932816418L;
+        private String elasticIP;//= LoadBalancerConfigUtil.replaceVariables("${ELASTIC_IP}");
+        private int instances = 1;
+        private boolean isAutoscaleEnabled;
+        private int autoscalerTaskInterval = 30000;
+        private String autoscalerServiceEpr;
+        private int serverStartupDelay = 60000;
+        private int sizeOfCache = 0 ;
+        private boolean failOver;
+        private int sessionTimeOut = -1;
+        private String groupManagementAgentClass;
+        private String autoscalerTaskClass;
+        private String mbServerUrl;
+        private boolean useEmbeddedAutoscaler = true;
+        private String algorithm = "org.apache.synapse.endpoints.algorithms.RoundRobin";
+
+        public String getElasticIP() {
+            return elasticIP;
+        }
+
+        public int getInstances() {
+            return instances;
+        }
+
+        public boolean isAutoscaleEnabled() {
+            return isAutoscaleEnabled;
+        }
+        
+        public boolean useEmbeddedAutoscaler() {
+            return useEmbeddedAutoscaler;
+        }
+        
+        public boolean getFailOver() {
+            return failOver;
+        }
+
+        public String getAutoscalerServiceEpr() {
+            return autoscalerServiceEpr;
+        }
+
+        public int getAutoscalerTaskInterval() {
+            return autoscalerTaskInterval;
+        }
+
+        public int getServerStartupDelay() {
+            return serverStartupDelay;
+        }
+        
+        public int getSessionTimeOut() {
+            return sessionTimeOut;
+        }
+
+        public void setElasticIP(String elasticIP) {
+            this.elasticIP = LoadBalancerConfigUtil.replaceVariables(elasticIP);
+        }
+
+        public void setInstances(int instances) {
+            this.instances = instances;
+        }
+
+        public void setEnable_autoscaler(String isEnabled) {
+            this.isAutoscaleEnabled = Boolean.parseBoolean(isEnabled);
+        }
+        
+        public void setUse_embedded_autoscaler(String use) {
+            this.useEmbeddedAutoscaler = Boolean.parseBoolean(use);
+        }
+        
+        public void setFail_over(String isEnabled) {
+            this.failOver = Boolean.parseBoolean(isEnabled);
+        }
+
+        public void setAutoscaler_service_epr(String epr) {
+            this.autoscalerServiceEpr = epr;
+        }
+
+        public void setMb_server_url(String url) {
+            this.mbServerUrl = url;
+        }
+        
+        public String getMbServerUrl() {
+        	return mbServerUrl;
+        }
+
+		public void setAutoscaler_task_interval(String interval) {
+            this.autoscalerTaskInterval = Integer.parseInt(interval);
+        }
+
+        public void setServer_startup_delay(String delay) {
+            this.serverStartupDelay = Integer.parseInt(delay);
+        }
+        
+        public void setSession_timeout(String timeout) {
+            this.sessionTimeOut = Integer.parseInt(timeout);
+        }
+
+        public String getAlgorithm() {
+            return algorithm;
+        }
+
+        public void setAlgorithm(String algorithm) {
+            if (algorithm != null) {
+                this.algorithm = algorithm;
+            }
+        }
+
+        public int getSizeOfCache() {
+            return sizeOfCache;
+        }
+
+        public void setSize_of_cache(int sizeOfCache) {
+            this.sizeOfCache = sizeOfCache;
+        }
+
+        public String getGroupManagementAgentClass() {
+            return groupManagementAgentClass;
+        }
+        
+        public String getAutoscalerTaskClass() {
+            return autoscalerTaskClass;
+        }
+
+        public void setGroup_mgt_agent(String groupManagementAgentClass){
+            this.groupManagementAgentClass = groupManagementAgentClass;
+        }
+        
+        public void setAutoscaler_task(String autoscalerTaskClass){
+            this.autoscalerTaskClass = autoscalerTaskClass;
+        }
+    }
+
+    public class ServiceConfiguration extends Configuration implements Serializable {
+
+    	private String serviceName;
+    	
+        public String getServiceName() {
+        	return serviceName;
+        }
+
+		public void setServiceName(String name) {
+        	this.serviceName = name;
+        }
+		
+		public String getPublicIp() {
+        	return publicIp;
+        }
+
+		public void setPublic_ip(String publicIp) {
+        	this.publicIp = publicIp;
+        }
+
+		private String publicIp;
+
+		private static final long serialVersionUID = 8707314702788040116L;
+        private int minAppInstances = 1;
+        private boolean minAppInstancesSet;
+
+        private int maxAppInstances = 3;
+        private boolean maxAppInstancesSet;
+
+        private int maxRequestsPerSecond = 100;
+        private boolean maxRequestsPerSecondSet;
+        
+        private double alarmingUpperRate = 0.7;
+        private boolean alarmingUpperRateSet;
+
+        private double alarmingLowerRate = 0.2;
+        private boolean alarmingLowerRateSet;
+        
+        private double scaleDownFactor = 0.25;
+        private boolean scaleDownFactorSet;
+        
+        private int roundsToAverage = 10;
+        private boolean roundsToAverageSet;
+
+        private int instancesPerScaleUp = 1;
+        private boolean instancesPerScaleUpSet;
+
+        private int messageExpiryTime = 60000; // milliseconds
+        private boolean messageExpiryTimeSet;
+
+        private List<String> hosts = new ArrayList<String>();
+        private Map<String, String> urlSuffixes = new HashMap<String, String>();
+        private boolean hostsSet;
+
+        private String domain;
+
+        private String tenantRange;
+        private boolean tenantRangeSet;
+
+        private String subDomain = Constants.DEFAULT_SUB_DOMAIN;
+        private boolean subDomainSet;
+
+        public String getTenantRange() {
+            if (tenantRangeSet) {
+                return tenantRange;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.tenantRangeSet) {
+                return defaultServiceConfig.tenantRange;
+            }
+            return tenantRange;
+        }
+
+        public String getDomain() {
+            return domain;
+        }
+
+        public List<String> getHosts() {
+            if (hostsSet) {
+                return hosts;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.hostsSet) {
+                return defaultServiceConfig.hosts;
+            }
+            return hosts;
+        }
+
+        public int getMinAppInstances() {
+            if (minAppInstancesSet) {
+                return minAppInstances;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.minAppInstancesSet) {
+                return defaultServiceConfig.minAppInstances;
+            }
+            return minAppInstances;
+        }
+
+        public int getMaxAppInstances() {
+            if (maxAppInstancesSet) {
+                return maxAppInstances;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.maxAppInstancesSet) {
+                return defaultServiceConfig.maxAppInstances;
+            }
+            return maxAppInstances;
+        }
+
+        public int getMaxRequestsPerSecond() {
+            if (maxRequestsPerSecondSet) {
+                return maxRequestsPerSecond;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.maxRequestsPerSecondSet) {
+                return defaultServiceConfig.maxRequestsPerSecond;
+            }
+            return maxRequestsPerSecond;
+        }
+
+        public int getRoundsToAverage() {
+            if (roundsToAverageSet) {
+                return roundsToAverage;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.roundsToAverageSet) {
+                return defaultServiceConfig.roundsToAverage;
+            }
+            return roundsToAverage;
+        }
+
+        public int getInstancesPerScaleUp() {
+            if (instancesPerScaleUpSet) {
+                return instancesPerScaleUp;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.instancesPerScaleUpSet) {
+                return defaultServiceConfig.instancesPerScaleUp;
+            }
+            return instancesPerScaleUp;
+        }
+
+        public int getMessageExpiryTime() {
+            if (messageExpiryTimeSet) {
+                return messageExpiryTime;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.messageExpiryTimeSet) {
+                return defaultServiceConfig.messageExpiryTime;
+            }
+            return messageExpiryTime;
+        }
+
+        public String getSubDomain() {
+            if (subDomainSet) {
+                return subDomain;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.subDomainSet) {
+                return defaultServiceConfig.subDomain;
+            }
+            return subDomain;
+        }
+
+        public void setMin_app_instances(int minAppInstances) {
+            this.minAppInstances = minAppInstances;
+            this.minAppInstancesSet = true;
+        }
+
+        public void setMax_app_instances(int maxAppInstances) {
+            if (maxAppInstances < 1) {
+                LoadBalancerConfigUtil.handleException("maxAppInstances in the autoscaler task configuration " +
+                        "should be at least 1");
+            }
+            this.maxAppInstances = maxAppInstances;
+            this.maxAppInstancesSet = true;
+        }
+        
+		public void setAlarming_upper_rate(double rate) {
+			if (rate > 0 && rate <= 1) {
+				this.alarmingUpperRate = rate;
+				this.alarmingUpperRateSet = true;
+			}
+		}
+
+        public void setAlarming_lower_rate(double rate) {
+			if (rate > 0 && rate <= 1) {
+				this.alarmingLowerRate = rate;
+				this.alarmingLowerRateSet = true;
+			}
+        }
+        
+		public void setScale_down_factor(double factor) {
+			if (factor > 0 && factor <= 1) {
+				this.scaleDownFactor = factor;
+				this.scaleDownFactorSet = true;
+			}
+		}
+        
+        public void setMax_requests_per_second(int rps) {
+            this.maxRequestsPerSecond = rps;
+            this.maxRequestsPerSecondSet = true;
+        }
+
+        public void setRounds_to_average(int roundsToAverage) {
+            this.roundsToAverage = roundsToAverage;
+            this.roundsToAverageSet = true;
+        }
+
+        public void setInstances_per_scale_up(int instancesPerScaleUp) {
+            if (instancesPerScaleUp < 1) {
+                LoadBalancerConfigUtil.handleException("instancesPerScaleUp in the autoscaler task configuration " +
+                        "should be at least 1");
+            }
+            this.instancesPerScaleUp = instancesPerScaleUp;
+            this.instancesPerScaleUpSet = true;
+        }
+
+        public void setMessage_expiry_time(int messageExpiryTime) {
+            if (messageExpiryTime < 1) {
+                LoadBalancerConfigUtil.handleException("messageExpiryTime in the autoscaler task configuration " +
+                        "should be at least 1");
+            }
+            this.messageExpiryTime = messageExpiryTime;
+            this.messageExpiryTimeSet = true;
+        }
+
+        public void setHosts(String hostsStr) {
+            // clear all unnecessary values --> property will get overwritten
+            hosts = new ArrayList<String>();
+            // there can be multiple hosts, let's find out.
+            String[] host = hostsStr.split(Constants.HOSTS_DELIMITER);
+
+            for (String string : host) {
+                if (!string.isEmpty()) {
+                    this.hosts.add(string);
+                }
+            }
+
+        }
+
+        public void setUrl_suffix(String suffix) {
+            // clear all unnecessary values --> property will get overwritten
+            //hosts = new ArrayList<String>();
+            // there can be multiple hosts, let's find out.
+            String[] suffixes = suffix.split(Constants.HOSTS_DELIMITER);
+            int count = 0;
+            if(suffixes.length == this.hosts.size()) {
+                for (String string : suffixes) {
+                    if (!string.isEmpty()) {
+                        this.urlSuffixes.put(this.hosts.get(count), string);
+                        count++;
+                    }
+                }
+            
+            } else {
+                //Error
+            }
+        }
+
+        public Map<String, String> getUrl_suffix() {
+            return this.urlSuffixes;
+        }
+
+        public void setTenant_range(String range) {
+            this.tenantRange = range;
+        }
+
+        public void setSub_domain(String subDomain) {
+            this.subDomain = subDomain;
+            this.subDomainSet = true;
+        }
+
+        public void setDomain(String domain) {
+            this.domain = domain;
+        }
+        
+        public boolean equals(ServiceConfiguration config) {
+            return this.domain.equals(config.getDomain()) &&
+                    this.subDomain.equals(config.getSubDomain());
+        }
+        
+        public int hashCode() {
+            return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
+                    append(domain).
+                    append(subDomain).
+                    toHashCode();
+        }
+
+        public double getAlarmingUpperRate() {
+            if (alarmingUpperRateSet) {
+                return alarmingUpperRate;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.alarmingUpperRateSet) {
+                return defaultServiceConfig.alarmingUpperRate;
+            }
+            return alarmingUpperRate;
+        }
+
+        public double getAlarmingLowerRate() {
+            if (alarmingLowerRateSet) {
+                return alarmingLowerRate;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.alarmingLowerRateSet) {
+                return defaultServiceConfig.alarmingLowerRate;
+            }
+            return alarmingLowerRate;
+        }
+
+        public double getScaleDownFactor() {
+            if (scaleDownFactorSet) {
+                return scaleDownFactor;
+            } else if (defaultServiceConfig != null && defaultServiceConfig.scaleDownFactorSet) {
+                return defaultServiceConfig.scaleDownFactor;
+            }
+            return scaleDownFactor;
+        }
+    }
+
+    public Map<String, Set<String>> getHostNamesTracker() {
+        return hostNamesTracker;
+    }
+
+
+    public Map<String, Map<String, ServiceConfiguration>> getServiceConfigurations() {
+        return serviceConfigurations;
+    }
+
+
+    public Node getRootNode() {
+        return rootNode;
+    }
+
+
+    public void setRootNode(Node rootNode) {
+        this.rootNode = rootNode;
+    }
+
+    public static void setInstance(LoadBalancerConfiguration instance) {
+        LoadBalancerConfiguration.instance = instance;
+    }
+
+	public Map<String, List<ServiceConfiguration>> getServiceNameToServiceConfigurations() {
+    	return serviceNameToServiceConfigurations;
+    }
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
new file mode 100755
index 0000000..c4820a7
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/Node.java
@@ -0,0 +1,356 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.conf.structure;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+/**
+ * This is the basic data structure which holds a <i>Nginx</i> formatted configuration file.
+ * 
+ */
+public class Node implements Serializable{
+
+    private static final long serialVersionUID = 4071569903421115370L;
+
+    /**
+     * Name of this Node element
+     */
+    private String name;
+
+    /**
+     * Every node can have 0..n child nodes. 
+     * They are kept in a List.
+     */
+    private List<Node> childNodes = new ArrayList<Node>();
+
+    /**
+     * Every node can have 0..n properties. 
+     * They are kept in a Map, in the order they appear.
+     * Key: property name
+     * Value: property value
+     */
+    private Map<String, String> properties = new LinkedHashMap<String, String>();
+
+    public void setChildNodes(List<Node> childNodes) {
+        this.childNodes = childNodes;
+    }
+
+    public void setProperties(Map<String, String> properties) {
+        this.properties = properties;
+    }
+
+    /**
+     * This will convert each child Node of this Node to a String.
+     * @return a string which represents child nodes of this node.
+     */
+    public String childNodesToString(int indentation) {
+        StringBuilder childNodesString = new StringBuilder();
+        indentation++;
+        
+        for (Node node : childNodes) {
+            childNodesString.append(node.toString(indentation)+"\n");
+        }
+        
+        return childNodesString.toString();
+    }
+
+    /**
+     * This will try to find a child Node of this Node, which has the given name.
+     * @param name name of the child node to find.
+     * @return child Node object if found or else <code>null</code>.
+     */
+    public Node findChildNodeByName(String name) {
+        for (Node aNode : childNodes) {
+            if (aNode.getName().equals(name)) {
+                return aNode;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the name of this Node. 
+     * @return name of the node.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns child nodes List of this Node.
+     * @return List of Node
+     */
+    public List<Node> getChildNodes() {
+        return childNodes;
+    }
+
+    /**
+     * Returns properties Map of this Node.
+     * @return Map whose keys and values are String.  
+     */
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Returns the value of a given property.
+     * @param key name of a property.
+     * @return trimmed value if the property is found in this Node, or else <code>null</code>. 
+     */
+    public String getProperty(String key) {
+        if (properties.get(key) == null) {
+            return null;
+        }
+        return properties.get(key).trim();
+    }
+
+    /**
+     * Returns all the properties of this Node as a String.
+     * Key and value of the property is separated by a tab (\t) character and
+     * each property is separated by a new line character.
+     * @param indentation relative number of tabs 
+     * @return properties of this node as a String.
+     */
+    public String propertiesToString(int indentation) {
+        
+        String indent = getIndentation(indentation);
+        
+        StringBuilder sb = new StringBuilder();
+        for (Entry<String, String> entry : properties.entrySet()) {
+            // hack to get a quick fix in.
+            if (!"tenant_id".equals(entry.getKey()) && !"alias".equals(entry.getKey())) {
+                sb.append(indent + entry.getKey() + "\t" + entry.getValue() + ";\n");
+            }
+        }
+        return sb.toString();
+    }
+    
+    /**
+     * Removes the first occurrence of a node having the given name
+     * and returns the removed {@link org.apache.stratos.load.balancer.conf.structure.Node}.
+     * @param name name of the child node to be removed.
+     * @return removed {@link org.apache.stratos.load.balancer.conf.structure.Node} or else <code>null</code>.
+     */
+    public Node removeChildNode(String name) {
+        Node aNode = findChildNodeByName(name);
+        
+        if(aNode != null){
+            if(childNodes.remove(aNode)){
+                return aNode;
+            }
+        }
+        
+        return null;
+    }
+
+    /**
+     * Removes the first occurrence of a node equals to the given node.
+     * @param node {@link org.apache.stratos.load.balancer.conf.structure.Node} to be removed.
+     * @return whether the removal is successful or not.
+     */
+    public boolean removeChildNode(Node node){
+
+        return childNodes.remove(node);
+    }
+    
+    /**
+     * Sets the name of this Node.
+     * @param name String to be set as the name.
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Appends a child node at the end of the List of child nodes of this Node, if 
+     * a similar node is not already present as a child node.
+     * @param aNode child Node to be appended.
+     */
+    public void appendChild(Node aNode) {
+        if (aNode != null && !nodeAlreadyPresent(aNode)) {
+            childNodes.add(aNode);
+        }
+    }
+    
+    /**
+     * Adds a new property to properties Map of this Node if and only if 
+     * key is not <code>null</code>.
+     * @param key name of the property to be added.
+     * @param value value of the property to be added.
+     */
+    public void addProperty(String key, String value) {
+        if (key != null) {
+            properties.put(key, value);
+        }
+    }
+    
+    /**
+     * Convert this Node to a String which is in <i>Nginx</i> format.
+     * <br/>
+     * Sample:
+     * <br></br>
+     * <code>
+     * ij {
+     * <br/>
+     * klm n;
+     * <br/>
+     * pq {
+     * <br/>
+     * rst u;
+     * <br/>
+     * }
+     * <br/>
+     * }
+     * <br/>
+     * </code>
+     */
+    public String toString() {
+        
+        String nodeString = 
+                getName()+" {\n" +
+                (propertiesToString(1)) +
+                (childNodesToString(1)) +
+                "}";
+        
+        return nodeString;
+    }
+    
+    public boolean equals(Object node) {
+        
+        if(node instanceof Node){
+            return this.getName().equals(((Node) node).getName()) &&
+                    isIdenticalProperties(this.getProperties(), ((Node) node).getProperties()) &&
+                    isIdenticalChildren(this.getChildNodes(), ((Node) node).getChildNodes());
+        }
+        
+        return false;
+        
+    }
+    
+    public int hashCode() {
+        return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
+            append(name).
+            append(properties).
+            append(childNodes).
+            toHashCode();
+    }
+    
+    private boolean isIdenticalChildren(List<Node> childNodes1, List<Node> childNodes2) {
+        
+        if(childNodes1.size() != childNodes2.size()){
+            return false;
+        }
+        
+        for (Node node1 : childNodes1) {
+            int i=0;
+            for (Node node2 : childNodes2) {
+                
+                i++;
+                if(node1.equals(node2)){
+                    break;
+                }
+                
+                if(i == childNodes1.size()){
+                    return false;
+                }
+                
+            }
+        }
+        
+        return true;
+    }
+    
+    private boolean nodeAlreadyPresent(Node aNode){
+        
+        for(Node node : this.childNodes){
+            if(node.equals(aNode)){
+                return true;
+            }
+        }
+        
+        return false;
+    }
+
+    private boolean isIdenticalProperties(Map<String, String> map1,
+        Map<String, String> map2) {
+        
+        if(map1.size() != map2.size()){
+            return false;
+        }
+        
+        for (Iterator<Entry<String, String>> iterator1 = map1.entrySet().iterator(); iterator1.hasNext();) {
+            Entry<String, String> entry1 = (Entry<String, String>) iterator1.next();
+            
+            int i=0;
+            
+            for(Iterator<Entry<String, String>> iterator2 = map2.entrySet().iterator(); iterator2.hasNext();) {
+                Entry<String, String> entry2 = (Entry<String, String>) iterator2.next();
+                
+                i++;
+                
+                if((entry1.getKey().equals(entry2.getKey()) &&
+                        entry1.getValue().equals(entry2.getValue()))){
+                    
+                    break;
+                }
+                
+                if(i == map1.size()){
+                    return false;
+                }
+                
+            }
+        }
+        
+        return true;
+    }
+
+    private String toString(int indentation){
+        
+        String indent = getIndentation(indentation-1);
+        
+        String nodeString = 
+                indent + getName()+" {\n" +
+                (propertiesToString(indentation)) +
+                (childNodesToString(indentation)) +
+                indent + "}";
+        
+        return nodeString;
+    }
+    
+    private String getIndentation(int tabs){
+        
+        StringBuilder indent = new StringBuilder("");
+        
+        for (int i = 0; i < tabs; i++) {
+            indent.append("\t");
+        }
+                
+        return indent.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
new file mode 100755
index 0000000..168492d
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/structure/NodeBuilder.java
@@ -0,0 +1,140 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.conf.structure;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.load.balancer.conf.util.Constants;
+
+/**
+ * This responsible for build up a Node object from a given content.
+ * Every closing brace should be in a new line.
+ */
+public class NodeBuilder {
+    
+    private static final Log log = LogFactory.getLog(NodeBuilder.class);
+
+    /**
+     * This method is useful when you do not have a root node in your content.
+     * @param aNode
+     *            Node object whose name set.
+     * @param content
+     *            should be something similar to following.
+     * 
+     *            abc d;
+     *            efg h;
+     *            # comment 
+     *            ij { # comment
+     *              klm n;
+     * 
+     *              pq {
+     *                  rst u;
+     *              }
+     *            }
+     * 
+     * @return fully constructed Node
+     */
+    public static Node buildNode(Node aNode, String content) {
+
+    	if(content == null || content.isEmpty()){
+    		return aNode;
+    	}
+    	
+        String[] lines = content.split("\n");
+
+        for (int i = 0; i < lines.length; i++) {
+            String line = lines[i].trim();
+
+            // avoid line comments
+            if (!line.startsWith(Constants.NGINX_COMMENT)) {
+                
+                // skip comments in-line 
+                if(line.contains(Constants.NGINX_COMMENT)){
+                    line = line.substring(0, line.indexOf(Constants.NGINX_COMMENT));
+                }
+                
+                // another node is detected and it is not a variable starting from $
+                if (line.contains(Constants.NGINX_NODE_START_BRACE) && 
+                        !line.contains(Constants.NGINX_VARIABLE)) {
+                    
+                    try {
+                        Node childNode = new Node();
+                        childNode.setName(line.substring(0, line.indexOf(Constants.NGINX_NODE_START_BRACE)).trim());
+
+                        StringBuilder sb = new StringBuilder();
+
+                        int matchingBraceTracker = 1;
+
+                        while (!line.contains(Constants.NGINX_NODE_END_BRACE) || matchingBraceTracker != 0) {
+                            i++;
+                            if (i == lines.length) {
+                                break;
+                            }
+                            line = lines[i];
+                            if (line.contains(Constants.NGINX_NODE_START_BRACE)) {
+                                matchingBraceTracker++;
+                            }
+                            if (line.contains(Constants.NGINX_NODE_END_BRACE)) {
+                                matchingBraceTracker--;
+                            }
+                            sb.append(line + "\n");
+                        }
+
+                        childNode = buildNode(childNode, sb.toString());
+						if (aNode == null) {
+							aNode = childNode;
+						} else {
+							aNode.appendChild(childNode);
+						}
+
+                    } catch (Exception e) {
+                        String msg = "Malformatted element is defined in the configuration file. [" +
+                                i + "] \n";
+                        log.error(msg , e);
+                        throw new RuntimeException(msg + line, e);
+                    }
+
+                }
+                // this is a property
+                else {
+                    if (!line.isEmpty() && !Constants.NGINX_NODE_END_BRACE.equals(line)) {
+                        String[] prop = line.split(Constants.NGINX_SPACE_REGEX);
+                        String value = line.substring(prop[0].length(), line.indexOf(Constants.NGINX_LINE_DELIMITER)).trim();
+                        try {
+                            aNode.addProperty(prop[0], value);
+                        } catch (Exception e) {
+                            String msg = "Malformatted property is defined in the configuration file. [" +
+                                    i + "] \n";
+                            log.error(msg, e);
+                            throw new RuntimeException(msg + line, e);
+                        }
+                    }
+                }
+            
+            }
+        }
+
+        return aNode;
+
+    }
+    
+    public static Node buildNode(String content) {
+	    return buildNode(null, content);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
new file mode 100755
index 0000000..31e172d
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/Constants.java
@@ -0,0 +1,50 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.conf.util;
+
+/**
+ * This keeps the element names used in loadbalancer.conf file
+ */
+public class Constants {
+    
+    public static final String LOAD_BALANCER_ELEMENT = "loadbalancer";
+    public static final String SERVICES_ELEMENT = "services";
+    public static final String DEFAULTS_ELEMENT = "defaults";
+    public static final String HOSTS_ELEMENT = "hosts";
+    public static final String HOSTS_DELIMITER = ",";
+    public static final String DOMAIN_ELEMENT = "domains";
+    public static final String TENANT_RANGE_ELEMENT = "tenant_range";
+    public static final String SUB_DOMAIN_ELEMENT = "sub_domain";
+    public static final String TENANT_RANGE_DELIMITER = "-";
+    public static final String UNLIMITED_TENANT_RANGE = "*";
+    public static final String AUTOSCALER_ENABLE_ELEMENT = "enable_autoscaler";
+    public static final String SUB_DOMAIN_DELIMITER = "#";
+    public static final String DEFAULT_SUB_DOMAIN = "__$default";
+    
+    /* Nginx format related constants */
+    
+    public static final String NGINX_COMMENT = "#";
+    public static final String NGINX_NODE_START_BRACE = "{";
+    public static final String NGINX_NODE_END_BRACE = "}";
+    public static final String NGINX_VARIABLE = "${";
+    public static final String NGINX_LINE_DELIMITER = ";";
+    public static final String NGINX_SPACE_REGEX = "[\\s]+";
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
new file mode 100755
index 0000000..ecd952a
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/HostContext.java
@@ -0,0 +1,161 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.conf.util;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.synapse.endpoints.algorithms.AlgorithmContext;
+import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
+
+/**
+ * For each unique host name defined in loadbalancer configuration, we'll generate
+ * this object. 
+ */
+public class HostContext {
+    
+    /**
+     * A unique identifier to identify this {@link #HostContext()}
+     */
+    private String hostName;
+    
+    /**
+     * Key - tenant id
+     * Value - <code>TenantDomainContext</code> of the corresponding tenant
+     */
+    private Map<Integer, TenantDomainContext> tenantIdToTenantDomainContextMap = new HashMap<Integer, TenantDomainContext>();
+    
+    /**
+     * AlgorithmContext of this host
+     */
+    private AlgorithmContext algorithmContext;
+    
+    /**
+     * Load balance algorithm of this host
+     */
+    private LoadbalanceAlgorithm algorithm;
+    
+    private String urlSuffix;
+    
+    public HostContext(String hostName) {
+        this.hostName = hostName;
+    }
+    
+    public void addTenantDomainContexts(List<TenantDomainContext> ctxts) {
+        
+        for (TenantDomainContext tenantDomainContext : ctxts) {
+            tenantIdToTenantDomainContextMap.put(tenantDomainContext.getTenantId(), tenantDomainContext);
+        }
+    }
+    
+    @Deprecated
+    public void addTenantDomainContext(TenantDomainContext ctxt) {
+        tenantIdToTenantDomainContextMap.put(ctxt.getTenantId(), ctxt);
+    }
+    
+    public TenantDomainContext getTenantDomainContext(int tenantId) {
+        return tenantIdToTenantDomainContextMap.get(tenantId);
+    }
+    
+    /**
+     * Returns all the {@link org.apache.stratos.load.balancer.conf.util.TenantDomainContext} entries.
+     */
+    public Collection<TenantDomainContext> getTenantDomainContexts() {
+        return tenantIdToTenantDomainContextMap.values();
+    }
+    
+    /**
+     * Given a tenant id, this will return its domain.
+     * @param tenantId 
+     * @return domain if this tenant has a dedicated one, it will be returned.
+     * If not, and there's a default (*) domain, it will be returned.
+     * If neither of the above is defined, null will be returned.
+     */
+    public String getDomainFromTenantId(int tenantId) {
+        if (tenantIdToTenantDomainContextMap.get(tenantId) == null) {
+            // if there's no specific domain for this tenant, we will redirect it to the default
+            // cluster
+            
+            if(tenantIdToTenantDomainContextMap.get(0) == null){
+                return null;
+            }
+            
+            return tenantIdToTenantDomainContextMap.get(0).getDomain();
+        }
+
+        return tenantIdToTenantDomainContextMap.get(tenantId).getDomain();
+    }
+    
+    /**
+     * Given a tenant id, this will return its sub domain.
+     * @param tenantId 
+     * @return sub_domain if this tenant has a dedicated one, it will be returned.
+     * If not, and there's a default (*) sub domain, it will be returned.
+     * If neither of the above is defined, null will be returned.
+     */
+    public String getSubDomainFromTenantId(int tenantId) {
+        if (tenantIdToTenantDomainContextMap.get(tenantId) == null) {
+            // if there's no specific domain for this tenant, we will redirect it to the default
+            // cluster
+            
+            if(tenantIdToTenantDomainContextMap.get(0) == null){
+                return null;
+            }
+            
+            return tenantIdToTenantDomainContextMap.get(0).getSubDomain();
+        }
+
+        return tenantIdToTenantDomainContextMap.get(tenantId).getSubDomain();
+    }
+
+    public String getHostName() {
+        return hostName;
+    }
+    
+    public LoadbalanceAlgorithm getAlgorithm() {
+        return algorithm;
+    }
+
+    public AlgorithmContext getAlgorithmContext() {
+        return algorithmContext;
+    }
+
+    public void setAlgorithmContext(AlgorithmContext algorithmContext) {
+        this.algorithmContext = algorithmContext;
+    }
+
+    public void setAlgorithm(LoadbalanceAlgorithm algorithm) {
+        this.algorithm = algorithm;
+    }
+
+    public Map<Integer, TenantDomainContext> getTenantIdToTenantDomainContextMap() {
+        return tenantIdToTenantDomainContextMap;
+    }
+    
+    public void setUrlSuffix(String suffix)  {
+        this.urlSuffix = suffix;
+    }
+
+    public String getUrlSuffix() {
+        return this.urlSuffix;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
new file mode 100755
index 0000000..fe432c9
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/LoadBalancerConfigUtil.java
@@ -0,0 +1,305 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.conf.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.synapse.SynapseException;
+import sun.misc.BASE64Encoder;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility methods for Autoscale mediator
+ */
+public final class LoadBalancerConfigUtil {
+
+    private static final Log log = LogFactory.getLog(LoadBalancerConfigUtil.class);
+
+    private LoadBalancerConfigUtil() {
+    }
+
+    /**
+     * handles the exception
+     * 
+     * @param msg
+     *            exception message
+     */
+    public static void handleException(String msg) {
+        log.error(msg);
+        throw new RuntimeException(msg);
+    }
+
+    /**
+     * handles the exception
+     * 
+     * @param msg
+     *            exception message
+     * @param e
+     *            exception
+     */
+    public static void handleException(String msg, Exception e) {
+        log.error(msg, e);
+        throw new SynapseException(msg, e);
+    }
+
+    /**
+     * Replaces the variables
+     * 
+     * @param text
+     *            input string
+     * @return output String
+     */
+    public static String replaceVariables(String text) {
+        int indexOfStartingChars;
+        int indexOfClosingBrace;
+
+        // The following condition deals with properties.
+        // Properties are specified as ${system.property},
+        // and are assumed to be System properties
+        if ((indexOfStartingChars = text.indexOf("${")) != -1 &&
+            (indexOfClosingBrace = text.indexOf("}")) != -1) { // Is a property used?
+            String var = text.substring(indexOfStartingChars + 2, indexOfClosingBrace);
+
+            String propValue = System.getProperty(var);
+            if (propValue == null) {
+                propValue = System.getenv(var);
+            }
+            if (propValue != null) {
+                text =
+                       text.substring(0, indexOfStartingChars) + propValue +
+                               text.substring(indexOfClosingBrace + 1);
+            }
+        }
+        return text;
+    }
+
+    public static String getUserData(String payloadFileName) {
+        String userData = null;
+        try {
+            File file = new File(payloadFileName);
+            if (!file.exists()) {
+                handleException("Payload file " + payloadFileName + " does not exist");
+            }
+            if (!file.canRead()) {
+                handleException("Payload file " + payloadFileName + " does cannot be read");
+            }
+            byte[] bytes = LoadBalancerConfigUtil.getBytesFromFile(file);
+            if (bytes != null) {
+                BASE64Encoder encoder = new BASE64Encoder();
+                userData = encoder.encode(bytes);
+            }
+        } catch (Exception e) {
+            LoadBalancerConfigUtil.handleException("Cannot read data from payload file " +
+                                                   payloadFileName, e);
+
+        }
+        return userData;
+    }
+
+    /**
+     * Returns the contents of the file in a byte array
+     * 
+     * @param file
+     *            - Input File
+     * @return Bytes from the file
+     * @throws java.io.IOException
+     *             , if retrieving the file contents failed.
+     */
+    public static byte[] getBytesFromFile(File file) throws IOException {
+        if (!file.exists()) {
+            log.error("Payload file " + file.getAbsolutePath() + " does not exist");
+            return null;
+        }
+        InputStream is = new FileInputStream(file);
+        byte[] bytes;
+
+        try {
+            // Get the size of the file
+            long length = file.length();
+
+            // You cannot create an array using a long type.
+            // It needs to be an int type.
+            // Before converting to an int type, check
+            // to ensure that file is not larger than Integer.MAX_VALUE.
+            if (length > Integer.MAX_VALUE) {
+                if (log.isDebugEnabled()) {
+                    log.debug("File is too large");
+                }
+            }
+
+            // Create the byte array to hold the data
+            bytes = new byte[(int) length];
+
+            // Read in the bytes
+            int offset = 0;
+            int numRead;
+            while (offset < bytes.length &&
+                   (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
+                offset += numRead;
+            }
+
+            // Ensure all the bytes have been read in
+            if (offset < bytes.length) {
+                throw new IOException("Could not completely read file " + file.getName());
+            }
+        } finally {
+            // Close the input stream and return bytes
+            is.close();
+        }
+
+        return bytes;
+    }
+
+    /**
+     * @deprecated
+     *             Extract the domain part given a string which is in
+     *             &lt;sub_domain&gt;#&lt;domain&gt; format.
+     * @param str
+     *            in &lt;sub_domain&gt;#&lt;domain&gt; format.
+     * @return the domain part. If # is not present this will return the trimmed
+     *         input string.
+     */
+    public static String getDomain(String str) {
+        str = str.trim();
+        if (!str.contains(Constants.SUB_DOMAIN_DELIMITER)) {
+            return str;
+        }
+        return str.substring(str.indexOf(Constants.SUB_DOMAIN_DELIMITER) + 1);
+    }
+
+    /**
+     * @deprecated
+     *             Extract the sub_domain part given a string which is in
+     *             &lt;sub_domain&gt;#&lt;domain&gt; format.
+     * @param str
+     *            in &lt;sub_domain&gt;#&lt;domain&gt; format.
+     * @return the sub_domain part. If # is not present this will return <code>null</code>.
+     */
+    public static String getSubDomain(String str) {
+        str = str.trim();
+        if (!str.contains(Constants.SUB_DOMAIN_DELIMITER)) {
+            return null;
+        }
+        return str.substring(0, str.indexOf(Constants.SUB_DOMAIN_DELIMITER));
+    }
+
+    // public static EC2InstanceManager createEC2InstanceManager(String accessKey,
+    // String secretKey,
+    // String instanceMgtEPR) {
+    // AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
+    // AmazonEC2Client ec2Client = new AmazonEC2Client(awsCredentials);
+    // ec2Client.setEndpoint(instanceMgtEPR);
+    // return new EC2InstanceManager(ec2Client);
+    // }
+
+    public static List<TenantDomainContext> getTenantDomainContexts(String tenantRange, String domain, String subDomain) {
+        
+        List<TenantDomainContext> ctxts = new ArrayList<TenantDomainContext>();
+        List<Integer> tenantIds = getTenantIds(tenantRange);
+        
+        // iterate through all tenant ids under this host
+        for (Integer tId : tenantIds) {
+
+            // create a new TenantDomainContext
+            TenantDomainContext tenantCtxt =
+                                             new TenantDomainContext(
+                                                                     tId,
+                                                                     domain,
+                                                                     subDomain);
+            // add it to the list
+            ctxts.add(tenantCtxt);
+        }
+        
+        return ctxts;
+        
+    }
+    
+    /**
+     * This method will read the tenant range string and return a list of tenant ids
+     * which is derived from tenant range string.
+     * 
+     * @param tenantRange
+     * @return list of tenant ids.
+     */
+    public static List<Integer> getTenantIds(String tenantRange) {
+
+        List<Integer> tenantIds = new ArrayList<Integer>();
+
+        String[] parsedLine = tenantRange.trim().split("-");
+
+        if (parsedLine[0].equalsIgnoreCase("*")) {
+            tenantIds.add(0);
+
+		} else if (parsedLine.length == 1) {
+			// if there aren't any hyphens in the string, try to see whether
+			// this is a list of ids
+			parsedLine = tenantRange.trim().split(",");
+			
+			// if there aren't any commas in the string, we assume this to be a
+			// one single integer.
+			if (parsedLine.length == 1) {
+				try {
+					int tenantId = Integer.parseInt(tenantRange);
+					tenantIds.add(tenantId);
+
+				} catch (NumberFormatException e) {
+					String msg = "Invalid tenant range is specified : "
+							+ tenantRange;
+					log.error(msg, e);
+					throw new RuntimeException(msg, e);
+				}
+			} else {
+				for (int i = 0; i < parsedLine.length; i++) {
+					int tenantId = Integer.parseInt(parsedLine[i]);
+					tenantIds.add(tenantId);
+				}
+			}
+		} else if (parsedLine.length == 2) {
+            try {
+
+                int startIndex = Integer.parseInt(parsedLine[0]);
+                int endIndex = Integer.parseInt(parsedLine[1]);
+
+                for (int tenantId = startIndex; tenantId <= endIndex; tenantId++) {
+
+                    tenantIds.add(tenantId);
+                }
+
+            } catch (NumberFormatException e) {
+                String msg = "Invalid tenant range is specified : " + tenantRange;
+                log.error(msg, e);
+                throw new RuntimeException(msg, e);
+            }
+
+        } else {
+            String msg = "Invalid tenant range is specified : " + tenantRange;
+            log.error(msg);
+            throw new RuntimeException(msg);
+        }
+
+        return tenantIds;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
new file mode 100755
index 0000000..33162c5
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/util/TenantDomainContext.java
@@ -0,0 +1,80 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.conf.util;
+
+/**
+ * This object will hold all the data related to a tenant.
+ */
+public class TenantDomainContext {
+    
+    /**
+     * this is the unique identifier for this object
+     */
+    private int tenantId;
+    
+    /**
+     * Domain, which this tenant belongs to.
+     */
+    private String domain;
+    
+    /**
+     * Sub domain, which this tenant belongs to.
+     */
+    private String subDomain;
+    
+    public TenantDomainContext(int tenantId, String domain, String subDomain) {
+        this.tenantId = tenantId;
+        this.domain = domain;
+        this.subDomain = subDomain;
+    }
+    
+    
+    /** Getters and Setters **/
+
+    public int getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(int tenantId) {
+        this.tenantId = tenantId;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    public String getSubDomain() {
+        return subDomain;
+    }
+
+    public void setSubDomain(String subDomain) {
+        this.subDomain = subDomain;
+    }
+    
+    
+    /** End of Getters and Setters **/
+    
+    
+    
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/32565547/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
new file mode 100755
index 0000000..c94b54c
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigUtilTest.java
@@ -0,0 +1,48 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF 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
+
+ *  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 org.apache.stratos.load.balancer.test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.stratos.load.balancer.conf.util.LoadBalancerConfigUtil;
+
+import junit.framework.TestCase;
+
+public class LoadBalancerConfigUtilTest extends TestCase {
+
+    private List<Integer> tenantList1 = Arrays.asList(1,2,3);
+    private List<Integer> tenantList2 = Arrays.asList(1,6,3,4);
+    private List<Integer> tenantList3 = Arrays.asList(43);
+    private List<Integer> tenantList4 = Arrays.asList(0);
+    
+    @Override
+    protected void setUp() throws Exception {
+
+    }
+    
+    public final void testGetTenantIds() {
+        
+        assertEquals(tenantList1, LoadBalancerConfigUtil.getTenantIds("1-3"));
+        assertEquals(tenantList2, LoadBalancerConfigUtil.getTenantIds("1,6,3,4"));
+        assertEquals(tenantList3, LoadBalancerConfigUtil.getTenantIds("43"));
+        assertEquals(tenantList4, LoadBalancerConfigUtil.getTenantIds("*"));
+    }
+
+}


[3/3] git commit: Merge remote-tracking branch 'origin/master'

Posted by im...@apache.org.
Merge remote-tracking branch 'origin/master'


Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/1041b1ba
Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/1041b1ba
Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/1041b1ba

Branch: refs/heads/master
Commit: 1041b1bae894ac54e1604611d0e56adf49c6f3b5
Parents: 3256554 14d59ad
Author: Imesh Gunaratne <im...@apache.org>
Authored: Sun Nov 10 22:39:31 2013 +0530
Committer: Imesh Gunaratne <im...@apache.org>
Committed: Sun Nov 10 22:39:31 2013 +0530

----------------------------------------------------------------------
 pom.xml | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)
----------------------------------------------------------------------