SLING-4124 : Bootstrap command file can't be appended

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1684195 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java b/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java
index cfeea1f..4946cbf 100644
--- a/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java
+++ b/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java
@@ -154,48 +154,63 @@
             if ( mode != null ) {
                 baseConfig.getProperties().put(ModelConstants.CFG_UNPROCESSED_MODE, mode);
             }
-        }
-        final boolean baseIsRaw = baseConfig.getProperties().get(ModelConstants.CFG_UNPROCESSED) != null;
-        final boolean mergeIsRaw = mergeConfig.getProperties().get(ModelConstants.CFG_UNPROCESSED) != null;
-        // simplest case, both are raw
-        if ( baseIsRaw && mergeIsRaw ) {
-            final String cfgMode = (String)mergeConfig.getProperties().get(ModelConstants.CFG_UNPROCESSED_MODE);
-            if ( cfgMode == null || ModelConstants.CFG_MODE_OVERWRITE.equals(cfgMode) ) {
-                copyConfigurationProperties(baseConfig, mergeConfig);
-            } else {
-                final Configuration newConfig = new Configuration(baseConfig.getPid(), baseConfig.getFactoryPid());
-                getProcessedConfiguration(newConfig, baseConfig);
-                clearConfiguration(baseConfig);
-                copyConfigurationProperties(baseConfig, newConfig);
-
-                clearConfiguration(newConfig);
-                getProcessedConfiguration(newConfig, mergeConfig);
-                copyConfigurationProperties(baseConfig, newConfig);
-            }
-
-        // another simple case, both are not raw
-        } else if ( !baseIsRaw && !mergeIsRaw ) {
-            // merge mode is always overwrite
-            clearConfiguration(baseConfig);
-            copyConfigurationProperties(baseConfig, mergeConfig);
-
-        // base is not raw but merge is
-        } else if ( !baseIsRaw && mergeIsRaw ) {
-            final String cfgMode = (String)mergeConfig.getProperties().get(ModelConstants.CFG_UNPROCESSED_MODE);
-            if ( cfgMode == null || ModelConstants.CFG_MODE_OVERWRITE.equals(cfgMode) ) {
-                clearConfiguration(baseConfig);
-                copyConfigurationProperties(baseConfig, mergeConfig);
-            } else {
-                final Configuration newMergeConfig = new Configuration(mergeConfig.getPid(), mergeConfig.getFactoryPid());
-                getProcessedConfiguration(newMergeConfig, mergeConfig);
-                copyConfigurationProperties(baseConfig, newMergeConfig);
-            }
-
-            // base is raw, but merge is not raw
         } else {
-            // merge mode is always overwrite
-            clearConfiguration(baseConfig);
-            copyConfigurationProperties(baseConfig, mergeConfig);
+            final boolean baseIsRaw = baseConfig.getProperties().get(ModelConstants.CFG_UNPROCESSED) != null;
+            final boolean mergeIsRaw = mergeConfig.getProperties().get(ModelConstants.CFG_UNPROCESSED) != null;
+            // simplest case, both are raw
+            if ( baseIsRaw && mergeIsRaw ) {
+                final String cfgMode = (String)mergeConfig.getProperties().get(ModelConstants.CFG_UNPROCESSED_MODE);
+                if ( cfgMode == null || ModelConstants.CFG_MODE_OVERWRITE.equals(cfgMode) ) {
+                    copyConfigurationProperties(baseConfig, mergeConfig);
+                } else {
+                    final Configuration newConfig = new Configuration(baseConfig.getPid(), baseConfig.getFactoryPid());
+                    getProcessedConfiguration(newConfig, baseConfig);
+                    clearConfiguration(baseConfig);
+                    copyConfigurationProperties(baseConfig, newConfig);
+
+                    clearConfiguration(newConfig);
+                    getProcessedConfiguration(newConfig, mergeConfig);
+
+                    if ( baseConfig.isSpecial() ) {
+                        final String baseValue = baseConfig.getProperties().get(baseConfig.getPid()).toString();
+                        final String mergeValue = newConfig.getProperties().get(baseConfig.getPid()).toString();
+                        baseConfig.getProperties().put(baseConfig.getPid(), baseValue + "\n" + mergeValue);
+                    } else {
+                        copyConfigurationProperties(baseConfig, newConfig);
+                    }
+                }
+
+            // another simple case, both are not raw
+            } else if ( !baseIsRaw && !mergeIsRaw ) {
+                // merge mode is always overwrite
+                clearConfiguration(baseConfig);
+                copyConfigurationProperties(baseConfig, mergeConfig);
+
+            // base is not raw but merge is
+            } else if ( !baseIsRaw && mergeIsRaw ) {
+                final String cfgMode = (String)mergeConfig.getProperties().get(ModelConstants.CFG_UNPROCESSED_MODE);
+                if ( cfgMode == null || ModelConstants.CFG_MODE_OVERWRITE.equals(cfgMode) ) {
+                    clearConfiguration(baseConfig);
+                    copyConfigurationProperties(baseConfig, mergeConfig);
+                } else {
+                    final Configuration newMergeConfig = new Configuration(mergeConfig.getPid(), mergeConfig.getFactoryPid());
+                    getProcessedConfiguration(newMergeConfig, mergeConfig);
+
+                    if ( baseConfig.isSpecial() ) {
+                        final String baseValue = baseConfig.getProperties().get(baseConfig.getPid()).toString();
+                        final String mergeValue = newMergeConfig.getProperties().get(baseConfig.getPid()).toString();
+                        baseConfig.getProperties().put(baseConfig.getPid(), baseValue + "\n" + mergeValue);
+                    } else {
+                        copyConfigurationProperties(baseConfig, newMergeConfig);
+                    }
+                }
+
+                // base is raw, but merge is not raw
+            } else {
+                // merge mode is always overwrite
+                clearConfiguration(baseConfig);
+                copyConfigurationProperties(baseConfig, mergeConfig);
+            }
         }
     }
 
diff --git a/src/test/java/org/apache/sling/provisioning/model/ModelUtilityTest.java b/src/test/java/org/apache/sling/provisioning/model/ModelUtilityTest.java
index bfa682f..d5d18ef 100644
--- a/src/test/java/org/apache/sling/provisioning/model/ModelUtilityTest.java
+++ b/src/test/java/org/apache/sling/provisioning/model/ModelUtilityTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import java.util.List;
 
@@ -77,15 +78,21 @@
 
         ModelUtility.merge(baseRaw, mergeRaw);
 
-        final List<Configuration> cfgs = U.assertConfigurationsInRunMode(baseRaw.getFeature("configadmin").getRunMode(), 3);
+        final List<Configuration> cfgs = U.assertConfigurationsInRunMode(baseRaw.getFeature("configadmin").getRunMode(), 4);
 
-        final Configuration cfgA = cfgs.get(0);
+        final Configuration cfgBoot = cfgs.get(0);
+        assertEquals(1, cfgBoot.getProperties().size());
+        assertTrue(cfgBoot.getProperties().get(":bootstrap").toString().contains("uninstall bundle.a"));
+        assertTrue(cfgBoot.getProperties().get(":bootstrap").toString().contains("uninstall bundle.b"));
+        assertTrue(cfgBoot.getProperties().get(":bootstrap").toString().contains("uninstall bundle.c"));
+
+        final Configuration cfgA = cfgs.get(1);
         assertEquals("org.apache.test.A", cfgA.getPid());
         assertNull(cfgA.getFactoryPid());
         assertEquals(1, cfgA.getProperties().size());
         assertEquals("AA", cfgA.getProperties().get("name"));
 
-        final Configuration cfgB = cfgs.get(1);
+        final Configuration cfgB = cfgs.get(2);
         assertEquals("org.apache.test.B", cfgB.getPid());
         assertNull(cfgB.getFactoryPid());
         assertEquals(3, cfgB.getProperties().size());
@@ -93,7 +100,7 @@
         assertEquals("bar", cfgB.getProperties().get("foo"));
         assertArrayEquals(new String[] {"one", "two", "three"}, (String[])cfgB.getProperties().get("array"));
 
-        final Configuration cfgC = cfgs.get(2);
+        final Configuration cfgC = cfgs.get(3);
         assertEquals("org.apache.test.C", cfgC.getPid());
         assertNull(cfgC.getFactoryPid());
         assertEquals(3, cfgC.getProperties().size());
@@ -111,22 +118,26 @@
 
         ModelUtility.merge(baseEffective, mergeEffective);
 
-        final List<Configuration> cfgs = U.assertConfigurationsInRunMode(baseEffective.getFeature("configadmin").getRunMode(), 3);
+        final List<Configuration> cfgs = U.assertConfigurationsInRunMode(baseEffective.getFeature("configadmin").getRunMode(), 4);
 
-        final Configuration cfgA = cfgs.get(0);
+        final Configuration cfgBoot = cfgs.get(0);
+        assertEquals(1, cfgBoot.getProperties().size());
+        assertTrue(cfgBoot.getProperties().get(":bootstrap").toString().contains("uninstall bundle.c"));
+
+        final Configuration cfgA = cfgs.get(1);
         assertEquals("org.apache.test.A", cfgA.getPid());
         assertNull(cfgA.getFactoryPid());
         assertEquals(1, cfgA.getProperties().size());
         assertEquals("AA", cfgA.getProperties().get("name"));
 
-        final Configuration cfgB = cfgs.get(1);
+        final Configuration cfgB = cfgs.get(2);
         assertEquals("org.apache.test.B", cfgB.getPid());
         assertNull(cfgB.getFactoryPid());
         assertEquals(2, cfgB.getProperties().size());
         assertEquals("BB", cfgB.getProperties().get("name"));
         assertEquals("bar", cfgB.getProperties().get("foo"));
 
-        final Configuration cfgC = cfgs.get(2);
+        final Configuration cfgC = cfgs.get(3);
         assertEquals("org.apache.test.C", cfgC.getPid());
         assertNull(cfgC.getFactoryPid());
         assertEquals(1, cfgC.getProperties().size());
@@ -140,22 +151,26 @@
 
         ModelUtility.merge(baseRaw, mergeEffective);
 
-        final List<Configuration> cfgs = U.assertConfigurationsInRunMode(baseRaw.getFeature("configadmin").getRunMode(), 3);
+        final List<Configuration> cfgs = U.assertConfigurationsInRunMode(baseRaw.getFeature("configadmin").getRunMode(), 4);
 
-        final Configuration cfgA = cfgs.get(0);
+        final Configuration cfgBoot = cfgs.get(0);
+        assertEquals(1, cfgBoot.getProperties().size());
+        assertTrue(cfgBoot.getProperties().get(":bootstrap").toString().contains("uninstall bundle.c"));
+
+        final Configuration cfgA = cfgs.get(1);
         assertEquals("org.apache.test.A", cfgA.getPid());
         assertNull(cfgA.getFactoryPid());
         assertEquals(1, cfgA.getProperties().size());
         assertEquals("AA", cfgA.getProperties().get("name"));
 
-        final Configuration cfgB = cfgs.get(1);
+        final Configuration cfgB = cfgs.get(2);
         assertEquals("org.apache.test.B", cfgB.getPid());
         assertNull(cfgB.getFactoryPid());
         assertEquals(2, cfgB.getProperties().size());
         assertEquals("BB", cfgB.getProperties().get("name"));
         assertEquals("bar", cfgB.getProperties().get("foo"));
 
-        final Configuration cfgC = cfgs.get(2);
+        final Configuration cfgC = cfgs.get(3);
         assertEquals("org.apache.test.C", cfgC.getPid());
         assertNull(cfgC.getFactoryPid());
         assertEquals(1, cfgC.getProperties().size());
@@ -169,15 +184,21 @@
 
         ModelUtility.merge(baseEffective, mergeRaw);
 
-        final List<Configuration> cfgs = U.assertConfigurationsInRunMode(baseEffective.getFeature("configadmin").getRunMode(), 3);
+        final List<Configuration> cfgs = U.assertConfigurationsInRunMode(baseEffective.getFeature("configadmin").getRunMode(), 4);
 
-        final Configuration cfgA = cfgs.get(0);
+        final Configuration cfgBoot = cfgs.get(0);
+        assertEquals(1, cfgBoot.getProperties().size());
+        assertTrue(cfgBoot.getProperties().get(":bootstrap").toString().contains("uninstall bundle.a"));
+        assertTrue(cfgBoot.getProperties().get(":bootstrap").toString().contains("uninstall bundle.b"));
+        assertTrue(cfgBoot.getProperties().get(":bootstrap").toString().contains("uninstall bundle.c"));
+
+        final Configuration cfgA = cfgs.get(1);
         assertEquals("org.apache.test.A", cfgA.getPid());
         assertNull(cfgA.getFactoryPid());
         assertEquals(1, cfgA.getProperties().size());
         assertEquals("AA", cfgA.getProperties().get("name"));
 
-        final Configuration cfgB = cfgs.get(1);
+        final Configuration cfgB = cfgs.get(2);
         assertEquals("org.apache.test.B", cfgB.getPid());
         assertNull(cfgB.getFactoryPid());
         assertEquals(3, cfgB.getProperties().size());
@@ -185,7 +206,7 @@
         assertEquals("bar", cfgB.getProperties().get("foo"));
         assertArrayEquals(new String[] {"one", "two", "three"}, (String[])cfgB.getProperties().get("array"));
 
-        final Configuration cfgC = cfgs.get(2);
+        final Configuration cfgC = cfgs.get(3);
         assertEquals("org.apache.test.C", cfgC.getPid());
         assertNull(cfgC.getFactoryPid());
         assertEquals(3, cfgC.getProperties().size());
diff --git a/src/test/resources/merge/config-base.txt b/src/test/resources/merge/config-base.txt
index e5c0451..ce37955 100644
--- a/src/test/resources/merge/config-base.txt
+++ b/src/test/resources/merge/config-base.txt
@@ -41,4 +41,8 @@
       "3"
     ]
     name="C"    
+
+:bootstrap
+    uninstall bundle.a
+    uninstall bundle.b
     
\ No newline at end of file
diff --git a/src/test/resources/merge/config-merge.txt b/src/test/resources/merge/config-merge.txt
index b640577..ec5c6be 100644
--- a/src/test/resources/merge/config-merge.txt
+++ b/src/test/resources/merge/config-merge.txt
@@ -32,4 +32,6 @@
 
 org.apache.test.C [mode=merge]
     foo="bar"    
-    
\ No newline at end of file
+
+:bootstrap [mode=merge]
+    uninstall bundle.c