Index: components/core/src/test/java/org/hippoecm/hst/configuration/pages/PagesModelsIT.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- components/core/src/test/java/org/hippoecm/hst/configuration/pages/PagesModelsIT.java	(revision 55877)
+++ components/core/src/test/java/org/hippoecm/hst/configuration/pages/PagesModelsIT.java	(revision )
@@ -15,6 +15,9 @@
  */
 package org.hippoecm.hst.configuration.pages;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.jcr.Node;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
@@ -22,18 +25,27 @@
 
 import org.hippoecm.hst.configuration.HstNodeTypes;
 import org.hippoecm.hst.configuration.components.HstComponentConfiguration;
+import org.hippoecm.hst.configuration.hosting.Mount;
+import org.hippoecm.hst.configuration.hosting.VirtualHosts;
+import org.hippoecm.hst.configuration.model.EventPathsInvalidator;
 import org.hippoecm.hst.configuration.model.HstManager;
 import org.hippoecm.hst.configuration.site.HstSite;
 import org.hippoecm.hst.core.request.ResolvedMount;
 import org.hippoecm.hst.site.HstServices;
 import org.hippoecm.hst.test.AbstractTestConfigurations;
+import org.hippoecm.hst.util.JcrSessionUtils;
 import org.hippoecm.repository.api.HippoSession;
 import org.hippoecm.repository.util.JcrUtils;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
 import static junit.framework.Assert.assertNull;
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM;
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_PARAMETER_NAMES;
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_PARAMETER_VALUES;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -181,7 +193,7 @@
     }
 
     @Test
-    public void test_workspace_in_inherited_pages_is_ignored() throws Exception {
+    public void workspace_pages_from_inherited_configuration_are_by_default_ignored() throws Exception {
         session.getNode("/hst:hst/hst:configurations/unittestcommon").addNode("hst:workspace");
         session.move("/hst:hst/hst:configurations/unittestcommon/hst:pages",
                 "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages");
@@ -194,6 +206,156 @@
         }
         assertNull(hstSite.getComponentsConfiguration().getComponentConfigurations().get("standarddetail"));
     }
+
+    // test inheritance from hst:workspace via inheritsfrom = ../xyz/hst:workspace
+    @Test
+    public void hst_components_from_workspace_by_default_not_inherited_unless_explicitly_inherited() throws Exception {
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+            assertNotNull(pageComponent);
+            assertTrue(pageComponent.isInherited());
+        }
+        // now move the [/hst:hst/hst:configurations/unittestcommon/hst:pages] to
+        // [/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages] and show the 'homepage' is not there any more
+
+        if (!session.nodeExists("/hst:hst/hst:configurations/unittestcommon/hst:workspace")) {
+            session.getNode("/hst:hst/hst:configurations/unittestcommon").addNode(HstNodeTypes.NODENAME_HST_WORKSPACE);
+        }
+        session.move("/hst:hst/hst:configurations/unittestcommon/hst:pages",
+                "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages");
+
+        EventPathsInvalidator invalidator = HstServices.getComponentManager().getComponent(EventPathsInvalidator.class.getName());
+        String[] pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+        session.save();
+
+        invalidator.eventPaths(pathsToBeChanged);
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+            Assert.assertNull(pageComponent);
+        }
+
+        // for all kind of inheritance variants below, the 'homepage' should be inherited
+        List<String[]> inheritanceVariants = new ArrayList<>();
+        inheritanceVariants.add(new String[]{"../unittestcommon", "../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon", "../unittestcommon/hst:workspace/hst:pages"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace", "../unittestcommon"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:pages", "../unittestcommon"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:pages"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:pages", "../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace", "../unittestcommon/hst:workspace/hst:pages"});
+
+        for (String[] inheritanceVariant : inheritanceVariants) {
+
+            setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                    inheritanceVariant);
+
+            pathsToBeChanged = new String[]{"/hst:hst/hst:configurations/unittestproject"};
+            invalidator.eventPaths(pathsToBeChanged);
+            {
+                VirtualHosts vhosts = hstManager.getVirtualHosts();
+                final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+                final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+                assertNotNull(pageComponent);
+                assertTrue(pageComponent.isInherited());
+                Assert.assertNull(pageComponent.getParameter("foo"));
+            }
+            // make sure a change triggers a reload!
+            final Node homePageNode = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages/homepage");
+            homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_NAMES, new String[]{"foo"});
+            homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"bar"});
+            pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+            session.save();
+            invalidator.eventPaths(pathsToBeChanged);
+            {
+                VirtualHosts vhosts = hstManager.getVirtualHosts();
+                final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+                final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+                // assert that the change is reloaded
+                assertEquals("bar", pageComponent.getParameter("foo"));
+            }
+
+            homePageNode.getProperty(GENERAL_PROPERTY_PARAMETER_NAMES).remove();
+            homePageNode.getProperty(GENERAL_PROPERTY_PARAMETER_VALUES).remove();
+            pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+            session.save();
+            invalidator.eventPaths(pathsToBeChanged);
+        }
+    }
+
+    @Test
+    public void test_inheritance_precedence() throws Exception {
+        if (!session.nodeExists("/hst:hst/hst:configurations/unittestcommon/hst:workspace")) {
+            session.getNode("/hst:hst/hst:configurations/unittestcommon").addNode(HstNodeTypes.NODENAME_HST_WORKSPACE);
+        }
+
+        // hst:pages both below unittestcommon AND below unittestcommon/hst:workspace
+        JcrUtils.copy(session, "/hst:hst/hst:configurations/unittestcommon/hst:pages", "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages");
+
+        // both have hst:pages/homepage : Depending on precedence of the hst:inheritsfrom, one of them is merged into the 'unittestproject' model
+        final Node homePageNode = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:pages/homepage");
+        homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_NAMES, new String[]{"location"});
+        homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"non-workspace"});
+        final Node workspaceHomePageNode = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages/homepage");
+        workspaceHomePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_NAMES, new String[]{"location"});
+        workspaceHomePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"workspace"});
+
+        // add an extra component to workspace
+        JcrUtils.copy(session, "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages/homepage",
+                "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages/homepageAgain");
+
+
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon", "../unittestcommon/hst:workspace"});
+        session.save();
+
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+            assertNotNull(pageComponent);
+            // since we first inherit ../unittestcommon and *then* ../unittestcommon/hst:workspace, we expect the homepage from
+            // unittestcommon/hst:pages and not from unittestcommon/hst:workspace/hst:pages
+            assertEquals("non-workspace", pageComponent.getParameter("location"));
+
+            // assert that 'homepageAgain' which is only present below 'unittestcommon/hst:workspace/hst:pages' is inherited still
+            final HstComponentConfiguration pageAgainComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepageAgain");
+            assertNotNull(pageAgainComponent);
+        }
+
+        // switch the inheritance
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon/hst:workspace", "../unittestcommon"});
+
+        EventPathsInvalidator invalidator = HstServices.getComponentManager().getComponent(EventPathsInvalidator.class.getName());
+        session.save();
+        invalidator.eventPaths(new String[] {"/hst:hst/hst:configurations/unittestproject"});
+
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+            assertNotNull(pageComponent);
+            // since we first inherit ../unittestcommon and *then* ../unittestcommon/hst:workspace, we expect the homepage from
+            // unittestcommon/hst:pages and not from unittestcommon/hst:workspace/hst:pages
+            assertEquals("workspace", pageComponent.getParameter("location"));
+        }
+    }
+
+    private void setWorkspaceInheritance(final String hstConfigurationPath, final String[] inheritsFrom) throws RepositoryException {
+        final Node hstConfigNode = session.getNode(hstConfigurationPath);
+        hstConfigNode.setProperty(GENERAL_PROPERTY_INHERITS_FROM, inheritsFrom);
+        session.save();
+    }
+
+    private String getLocalhostRootMountId() throws RepositoryException {
+        return session.getNode("/hst:hst/hst:hosts/dev-localhost/localhost/hst:root").getIdentifier();
+    }
+
 
     @Test
     public void test_marked_deleted_hstconfiguration_nodes_are_present_in_model()  throws Exception {
Index: components/core/src/test/java/org/hippoecm/hst/configuration/ContainerComponentConfigurationsIT.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- components/core/src/test/java/org/hippoecm/hst/configuration/ContainerComponentConfigurationsIT.java	(revision 55877)
+++ components/core/src/test/java/org/hippoecm/hst/configuration/ContainerComponentConfigurationsIT.java	(revision )
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Hippo B.V. (http://www.onehippo.com)
+ * Copyright 2013-2015 Hippo B.V. (http://www.onehippo.com)
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,17 +23,21 @@
 import javax.jcr.SimpleCredentials;
 import javax.jcr.nodetype.ConstraintViolationException;
 
+import org.apache.commons.lang.ArrayUtils;
 import org.hippoecm.hst.configuration.components.HstComponentConfiguration;
 import org.hippoecm.hst.configuration.hosting.Mount;
 import org.hippoecm.hst.configuration.hosting.VirtualHosts;
 import org.hippoecm.hst.configuration.model.EventPathsInvalidator;
 import org.hippoecm.hst.configuration.model.HstManager;
+import org.hippoecm.hst.core.container.ContainerException;
 import org.hippoecm.hst.site.HstServices;
 import org.hippoecm.hst.test.AbstractTestConfigurations;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM;
+import static org.hippoecm.repository.util.JcrUtils.getMultipleStringProperty;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -119,7 +123,7 @@
     }
 
 
-    private void addIllegalHomePageContainer(final Node parent,final String containerName) throws Exception {
+    private void addIllegalHomePageContainer(final Node parent, final String containerName) throws Exception {
         /*
            try to add to test component a not allowed container:
              + containerName [hst:containercomponent]
@@ -155,7 +159,7 @@
 
     private void addComponentReference(final Node parent, final String containerReferenceNodeName, String reference) throws RepositoryException {
         /*
-         try to add to test component a non existing cnntainerComponentReference:
+         try to add to test component a non existing containerComponentReference:
            + containerName [hst:containercomponent]
                - hst:xtype =  HST.vBox
                - hst:referencecomponent = reference
@@ -315,18 +319,20 @@
     @Test
     public void referenceable_containers_from_inherited_configuration_not_included() throws Exception {
         // below add a container to hst:workspace in 'unittestcommon' : this workspace is invisible for
-        // 'unittestproject' as workspace nodes are not inherited
+        // 'unittestproject' as workspace nodes are not IMPLICITLY inherited UNLESS hst:inheritsfrom EXPLICITLY
+        // includes ../xyz/hst:workspace
         createHstWorkspaceAndReferenceableContainer("myReferenceableContainer",
                 "/hst:hst/hst:configurations/unittestcommon");
-        addComponentReference(testComponent, "inheritedcontainer", "myReferenceableContainer");
+        final String inheritedContainerName = "inheritedcontainer";
+        addComponentReference(testComponent, inheritedContainerName, "myReferenceableContainer");
         {
             final VirtualHosts vhosts = hstSitesManager.getVirtualHosts();
             final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
             final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
             final HstComponentConfiguration testComponent = pageComponent.getChildByName(TEST_COMPONENT_NODE_NAME);
             assertNotNull(testComponent);
-            // container available since part of inherited
-            final HstComponentConfiguration component = testComponent.getChildByName("container");
+            // container NOT available since part of inherited
+            final HstComponentConfiguration component = testComponent.getChildByName(inheritedContainerName);
             assertNull(component);
         }
 
@@ -344,15 +350,118 @@
             final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
             final HstComponentConfiguration testComponent = pageComponent.getChildByName(TEST_COMPONENT_NODE_NAME);
             assertNotNull(testComponent);
-            // container available since part of inherited
+            // container available since part of inherited workspace (which by default is not inherited)
             final HstComponentConfiguration component = testComponent.getChildByName("localcontainer");
             assertNotNull(component);
         }
 
     }
 
+
+    private void setWorkspaceInheritance(final String hstConfigurationPath, final String[] inheritsFrom) throws RepositoryException {
+        final Node hstConfigNode = session.getNode(hstConfigurationPath);
+        hstConfigNode.setProperty(GENERAL_PROPERTY_INHERITS_FROM, inheritsFrom);
+        session.save();
+    }
+
+    @Test
+    public void referenceable_containers_from_inherited_configuration_included_when_workspace_explicitly_inherited_and_invalidation_works() throws Exception {
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon", "../unittestcommon/hst:workspace"});
+        assertInheritanceAndModelReloadWorks();
+    }
+
+    @Test
+    public void referenceable_containers_from_inherited_configuration_included_when_only_workspace_inherited_and_invalidation_works() throws Exception {
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon/hst:workspace"});
+        assertInheritanceAndModelReloadWorks();
+    }
+
+    @Test
+    public void referenceable_containers_from_containers_inherited_configuration_included_when_workspace_explicitly_inherited_and_invalidation_works() throws Exception {
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon", "../unittestcommon/hst:workspace/hst:containers"});
+        assertInheritanceAndModelReloadWorks();
+    }
+
+    @Test
+    public void referenceable_containers_from_containers_inherited_configuration_included_when_only_workspace_inherited_and_invalidation_works() throws Exception {
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon/hst:workspace/hst:containers"});
+        assertInheritanceAndModelReloadWorks();
+    }
+
+    @Test
+    public void test_illegal_reference_of_to_deeply_nested_container() throws Exception {
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon/hst:workspace/hst:containers/myReferenceableContainer"});
+        createHstWorkspaceAndReferenceableContainer("myReferenceableContainer",
+                "/hst:hst/hst:configurations/unittestcommon");
+
+        final String inheritedContainerName = "inheritedcontainer";
+        addComponentReference(testComponent, inheritedContainerName, "myReferenceableContainer");
+        {
+            final VirtualHosts vhosts = hstSitesManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+            final HstComponentConfiguration testComponent = pageComponent.getChildByName(TEST_COMPONENT_NODE_NAME);
+            assertNotNull(testComponent);
+            // container available since part of inherited BUT inherited workspace IS now inherited because explicitly inherited
+            final HstComponentConfiguration component = testComponent.getChildByName(inheritedContainerName);
+            assertNull(component);
+        }
+    }
+
+    private void assertInheritanceAndModelReloadWorks() throws Exception {
+
+        createHstWorkspaceAndReferenceableContainer("myReferenceableContainer",
+                "/hst:hst/hst:configurations/unittestcommon");
+
+        final String inheritedContainerName = "inheritedcontainer";
+        addComponentReference(testComponent, inheritedContainerName, "myReferenceableContainer");
+        {
+            final VirtualHosts vhosts = hstSitesManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+            final HstComponentConfiguration testComponent = pageComponent.getChildByName(TEST_COMPONENT_NODE_NAME);
+            assertNotNull(testComponent);
+            // container available since part of inherited BUT inherited workspace IS now inherited because explicitly inherited
+            final HstComponentConfiguration component = testComponent.getChildByName(inheritedContainerName);
+            assertNotNull(component);
+            final HstComponentConfiguration item = component.getChildByName("item");
+            assertNotNull(item);
+            assertEquals("value1", item.getParameter("name1"));
+            assertTrue(item.isInherited());
+        }
+
+        // now trigger a change in the inherited component from workspace. This should trigger a reload
+        final Node componentItem = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:containers/myReferenceableContainer/item");
+        componentItem.setProperty(HstNodeTypes.GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"valueNew"});
+        session.save();
+        // trigger events as during tests the jcr event listeners are not enabled
+        EventPathsInvalidator invalidator = HstServices.getComponentManager().getComponent(EventPathsInvalidator.class.getName());
+        invalidator.eventPaths(componentItem.getPath());
+        {
+            final VirtualHosts vhosts = hstSitesManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
+            final HstComponentConfiguration testComponent = pageComponent.getChildByName(TEST_COMPONENT_NODE_NAME);
+            assertNotNull(testComponent);
+            final HstComponentConfiguration component = testComponent.getChildByName(inheritedContainerName);
+            assertNotNull(component);
+            final HstComponentConfiguration item = component.getChildByName("item");
+            assertNotNull(item);
+            // a change in inherited workspace node should trigger a reload of the model
+            assertEquals("valueNew", item.getParameter("name1"));
+            assertTrue(item.isInherited());
+        }
+
+    }
+
     /**
-     * @return the highest ancestor path of newly created nodes: This is the node that needs to be cleanup at the end again
+     * @return the highest ancestor path of newly created nodes: This is the node that needs to be cleanup at the end
+     * again
      */
     private String createHstWorkspaceAndReferenceableContainer(final String containerRelPath,
                                                                final String projectPath) throws RepositoryException {
@@ -378,7 +487,7 @@
         final String[] elems = containerRelPath.split("/");
         if (elems.length > 1) {
             // first create folders
-            for (int i = 0; i < (elems.length -1); i++) {
+            for (int i = 0; i < (elems.length - 1); i++) {
                 if (folder.hasNode(elems[i])) {
                     folder = folder.getNode(elems[i]);
                 } else {
@@ -389,8 +498,8 @@
                 }
             }
         }
-        final Node container = folder.addNode(elems[elems.length -1], HstNodeTypes.NODETYPE_HST_CONTAINERCOMPONENT);
+        final Node container = folder.addNode(elems[elems.length - 1], HstNodeTypes.NODETYPE_HST_CONTAINERCOMPONENT);
-        if (highestAncestorPath  == null) {
+        if (highestAncestorPath == null) {
             highestAncestorPath = container.getPath();
         }
         container.setProperty(HstNodeTypes.COMPONENT_PROPERTY_XTYPE, "HST.vBox");
Index: components/core/src/main/java/org/hippoecm/hst/configuration/cache/CompositeConfigurationNodes.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- components/core/src/main/java/org/hippoecm/hst/configuration/cache/CompositeConfigurationNodes.java	(revision 55877)
+++ components/core/src/main/java/org/hippoecm/hst/configuration/cache/CompositeConfigurationNodes.java	(revision )
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2010-2013 Hippo B.V. (http://www.onehippo.com)
+ *  Copyright 2010-2015 Hippo B.V. (http://www.onehippo.com)
  * 
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -22,10 +22,15 @@
 import java.util.Map;
 import java.util.UUID;
 
+import org.apache.commons.lang.StringUtils;
 import org.hippoecm.hst.configuration.HstNodeTypes;
 import org.hippoecm.hst.configuration.model.HstNode;
 import org.slf4j.LoggerFactory;
 
+import static org.hippoecm.hst.configuration.HstNodeTypes.NODENAME_HST_WORKSPACE;
+import static org.hippoecm.hst.configuration.HstNodeTypes.NODETYPE_HST_CONFIGURATION;
+import static org.hippoecm.hst.configuration.HstNodeTypes.NODETYPE_HST_WORKSPACE;
+
 public class CompositeConfigurationNodes {
 
     private static final org.slf4j.Logger log = LoggerFactory.getLogger(HstNodeImpl.class);
@@ -48,7 +53,7 @@
         compositeConfigurationDependenyPaths.addAll(createDependencyPaths(configurationRootNode.getValueProvider().getPath(), relPaths, true));
 
         final HstNode configurationsNode = configurationRootNode.getParent();
-        final String defaultConfigurationRootPath = configurationsNode.getValueProvider().getPath() + "/"+HstNodeTypes.NODENAME_HST_HSTDEFAULT;
+        final String defaultConfigurationRootPath = configurationsNode.getValueProvider().getPath() + "/" + HstNodeTypes.NODENAME_HST_HSTDEFAULT;
         // hst:default is the implicit inherited configuration
 
         compositeConfigurationDependenyPaths.add(defaultConfigurationRootPath);
@@ -66,19 +71,19 @@
                 String hstConfigsInheritedRelPath = inheritPath.substring(3);
 
                 String absHstConfigsInheritedPath = configurationsNode.getValueProvider().getPath() + "/" + hstConfigsInheritedRelPath;
-                // regardless whether absHstConfigsInheritedPath exists or not, add it to the compositeConfigurationDependenyPaths : If it gets
+                // regardless whether absHstConfigsInheritedPath exists or not, add it to the compositeConfigurationDependencyPaths : If it gets
                 // added later on, it does impact this CompositeConfigurationNodes
                 compositeConfigurationDependenyPaths.add(absHstConfigsInheritedPath);
                 compositeConfigurationDependenyPaths.addAll(createDependencyPaths(absHstConfigsInheritedPath, relPaths, false));
                 HstNode inheritConfig = configurationsNode.getNode(hstConfigsInheritedRelPath);
-                if (inheritConfig != null && HstNodeTypes.NODETYPE_HST_CONFIGURATION.equals(inheritConfig.getNodeTypeName())) {
+                if (inheritConfig != null && isValidInheritedNode(inheritConfig)) {
                     orderedRootConfigurationNodeInheritanceList.add(inheritConfig);
                     if (inheritConfig.getValueProvider().hasProperty(HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM)) {
                         log.error("Skipping inheritfrom property for configuration node '{}' because this node is already inherit. Not allowed to inherit again", inheritConfig.getValueProvider().getPath());
                     }
                 } else {
                     log.error("Relative inherit path '{}' for node '{}' does not point to a node of type '{}' or does not exist. Fix this path.",
-                            new String[]{inheritPath, configurationRootNode.getValueProvider().getPath(), HstNodeTypes.NODETYPE_HST_CONFIGURATION});
+                            new String[]{inheritPath, configurationRootNode.getValueProvider().getPath(), NODETYPE_HST_CONFIGURATION});
                 }
             }
         }
@@ -90,6 +95,24 @@
         }
     }
 
+    /**
+     * Valid inherited configuration node is one that meets one of the following criteria
+     * <lu>
+     * <li>points to a node of type hst:configuration node, for example hst:inheritsfrom = ../common</li>
+     * <li>points to a node of type hst:workspace node, for example hst:inheritsfrom = ../common/hst:workspace</li>
+     * <li>points to a child node of a node of type hst:workspace, for example hst:inheritsfrom =
+     * ../common/hst:workspace/hst:pages</li>
+     * </lu>
+     *
+     * @param inheritConfig
+     * @return
+     */
+    private boolean isValidInheritedNode(final HstNode inheritConfig) {
+        return (NODETYPE_HST_CONFIGURATION.equals(inheritConfig.getNodeTypeName())
+                || NODETYPE_HST_WORKSPACE.equals(inheritConfig.getNodeTypeName())
+                || NODETYPE_HST_WORKSPACE.equals(inheritConfig.getParent().getNodeTypeName()));
+    }
+
     public HstNode getConfigurationRootNode() {
         return configurationRootNode;
     }
@@ -103,28 +126,71 @@
         for (String compositeConfigurationNodeRelPath : compositeConfigurationNodeRelPaths) {
 
             // a mainConfigNode is a node like hst:sitemap or hst:pages for example
-            HstNode mainConfigNode =  configurationRootNode.getNode(compositeConfigurationNodeRelPath);
+            HstNode mainConfigNode = configurationRootNode.getNode(compositeConfigurationNodeRelPath);
 
             if (mainConfigNode == null) {
                 // check whether there is a mainConfigNode in the workspace. Take that one if present
-                mainConfigNode = configurationRootNode.getNode(HstNodeTypes.NODENAME_HST_WORKSPACE + "/" + compositeConfigurationNodeRelPath);
+                mainConfigNode = configurationRootNode.getNode(NODENAME_HST_WORKSPACE + "/" + compositeConfigurationNodeRelPath);
             }
 
             List<HstNode> fallbackMainConfigNodes = new ArrayList<>();
-            // see if there is an inherited main config node that is *not* below workspace since workspace nodes are NOT
-            // inherited
-            if (!compositeConfigurationNodeRelPath.startsWith(HstNodeTypes.NODENAME_HST_WORKSPACE)) {
+
+            final String relativeInheritPath = compositeConfigurationNodeRelPath;
+
-                for (HstNode inherited : orderedRootConfigurationNodeInheritanceList) {
+            for (HstNode inherited : orderedRootConfigurationNodeInheritanceList) {
+                // for hst:containers the relativeInheritPath starts with hst:workspace
+                String workspaceAccountedRelativeInheritPath = relativeInheritPath;
+                if (relativeInheritPath.startsWith(NODENAME_HST_WORKSPACE)) {
+                    if (inherited.getNodeTypeName().equals(NODETYPE_HST_WORKSPACE)) {
+                        log.debug("Merging explicitly inherited workspace configuration for '{}'",
+                                inherited.getValueProvider().getPath());
+                        // hst:inheritsfrom is something like ../common/hst:workspace
+
+                        // remove the hst:workspace part : in inherited HstNode already
+                        workspaceAccountedRelativeInheritPath = relativeInheritPath.substring(NODENAME_HST_WORKSPACE.length() + 1);
+                    } else if (inherited.getParent().getNodeTypeName().equals(NODETYPE_HST_WORKSPACE)
+                            && inherited.getValueProvider().getPath().endsWith(relativeInheritPath) ) {
+
+                            log.debug("Merging explicitly inherited workspace configuration for '{}'",
+                                    inherited.getValueProvider().getPath());
+                            // hst:inheritsfrom is something like ../common/hst:workspace/hst:pages
+                        workspaceAccountedRelativeInheritPath = "";
+
+                    } else {
+                        log.debug("Do not merge workspace nodes since not explicitly inherited");
+                        continue;
+                    }
+                } else if (inherited.getParent().getNodeTypeName().equals(NODETYPE_HST_WORKSPACE)) {
+                    if (inherited.getValueProvider().getPath().endsWith(relativeInheritPath)) {
+                        log.debug("Merging explicitly inherited workspace child configuration for '{}'",
+                                inherited.getValueProvider().getPath());
+                        // hst:inheritsfrom is something like ../common/hst:workspace/hst:pages
+                        workspaceAccountedRelativeInheritPath = "";
+                    } else {
+                        log.debug("Do not merge workspace nodes '{}' since '{}' is explicitly inherited",
+                                relativeInheritPath, inherited.getValueProvider().getPath());
+                        continue;
+                    }
+                }
-                    if (mainConfigNode == null) {
+                if (mainConfigNode == null) {
-                        mainConfigNode =  inherited.getNode(compositeConfigurationNodeRelPath);
+                    if (workspaceAccountedRelativeInheritPath.isEmpty()) {
+                        mainConfigNode = inherited;
                     } else {
-                        HstNode inheritedMainConfigNode = inherited.getNode(compositeConfigurationNodeRelPath);
+                        mainConfigNode = inherited.getNode(workspaceAccountedRelativeInheritPath);
+                    }
+                } else {
+                    HstNode inheritedMainConfigNode;
+                    if (workspaceAccountedRelativeInheritPath.isEmpty()) {
+                        inheritedMainConfigNode = inherited;
+                    } else {
+                        inheritedMainConfigNode = inherited.getNode(workspaceAccountedRelativeInheritPath);
+                    }
-                        if (inheritedMainConfigNode != null) {
-                            fallbackMainConfigNodes.add(inheritedMainConfigNode);
-                        }
-                    }
-                }
+                    if (inheritedMainConfigNode != null) {
+                        fallbackMainConfigNodes.add(inheritedMainConfigNode);
+                    }
+                }
+            }
-            }
+
             if (mainConfigNode == null) {
                 continue;
             }
@@ -154,7 +220,7 @@
             }
         }
         if (log.isDebugEnabled()) {
-            log.debug("Creating cachekey took {} ms.", System.currentTimeMillis() -start);
+            log.debug("Creating cachekey took {} ms.", System.currentTimeMillis() - start);
         }
         cacheKey = uuids;
         return cacheKey;
@@ -162,14 +228,35 @@
 
     private List<String> createDependencyPaths(final String rootPath, final String[] relPaths, boolean includeWorkspacePath) {
         List<String> paths = new ArrayList<>();
+        boolean isInheritedWorkspace = false;
+        if (rootPath.contains("/" + NODENAME_HST_WORKSPACE)) {
+            // explicitly inherited workspace (eg hst:inheritsfrom = ../common/hst:workspace)
+            isInheritedWorkspace = true;
+            final String mainConfigNodeName = StringUtils.substringAfter(rootPath, "/" + NODENAME_HST_WORKSPACE + "/");
+            if (!mainConfigNodeName.isEmpty()) {
+                // explicitly inherited workspace main config node (eg hst:inheritsfrom = ../common/hst:workspace/hst:pages))
+                // just return this explicit dependency path
+                paths.add(rootPath);
+                return paths;
+            }
+        }
         for (String relPath : relPaths) {
+            if (isInheritedWorkspace) {
+                if (relPath.startsWith(NODENAME_HST_WORKSPACE + "/")) {
+                    // hst:workspace/hst:containers
+                    paths.add(rootPath + relPath.substring(NODENAME_HST_WORKSPACE.length()));
+                } else {
-            paths.add(rootPath + "/" + relPath);
+                    paths.add(rootPath + "/" + relPath);
-            if (includeWorkspacePath && !relPath.startsWith(HstNodeTypes.NODENAME_HST_WORKSPACE)) {
+                }
+            } else {
+                paths.add(rootPath + "/" + relPath);
+                if (includeWorkspacePath && !relPath.startsWith(NODENAME_HST_WORKSPACE)) {
-                // also include the workspace variant as below workspace nodes like hst:sitemenus or hst:sitemap can also be found
-                // if relPath already starts with hst:workspace it doesn't really matter. No bother to check
+                    // also include the workspace variant as below workspace nodes like hst:sitemenus or hst:sitemap can also be found
+                    // if relPath already starts with hst:workspace it doesn't really matter. No bother to check
-                paths.add(rootPath + "/" + HstNodeTypes.NODENAME_HST_WORKSPACE + "/" + relPath);
+                    paths.add(rootPath + "/" + NODENAME_HST_WORKSPACE + "/" + relPath);
-            }
-        }
+                }
+            }
+        }
         return paths;
     }
 
@@ -187,9 +274,9 @@
 
             HstNode mainConfigNodeInWorkspace = null;
             final HstNode parent = mainConfigNode.getParent();
-            if (!parent.getName().equals(HstNodeTypes.NODENAME_HST_WORKSPACE)) {
+            if (!parent.getName().equals(NODENAME_HST_WORKSPACE)) {
-                 // mainConfigNode is not already a node in workspace
+                // mainConfigNode is not already a node in workspace
-                mainConfigNodeInWorkspace = parent.getNode(HstNodeTypes.NODENAME_HST_WORKSPACE + "/" + mainConfigNode.getName());
+                mainConfigNodeInWorkspace = parent.getNode(NODENAME_HST_WORKSPACE + "/" + mainConfigNode.getName());
             }
 
             for (HstNode child : mainConfigNode.getNodes()) {
Index: components/core/src/test/java/org/hippoecm/hst/configuration/menu/HstMenuModelsIT.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- components/core/src/test/java/org/hippoecm/hst/configuration/menu/HstMenuModelsIT.java	(revision 55877)
+++ components/core/src/test/java/org/hippoecm/hst/configuration/menu/HstMenuModelsIT.java	(revision )
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2014 Hippo B.V. (http://www.onehippo.com)
+ *  Copyright 2014-2015 Hippo B.V. (http://www.onehippo.com)
  * 
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
  */
 package org.hippoecm.hst.configuration.menu;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import javax.jcr.Node;
@@ -22,10 +24,14 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.SimpleCredentials;
 
+import org.hippoecm.hst.configuration.HstNodeTypes;
+import org.hippoecm.hst.configuration.hosting.Mount;
+import org.hippoecm.hst.configuration.hosting.VirtualHosts;
 import org.hippoecm.hst.configuration.internal.CanonicalInfo;
 import org.hippoecm.hst.configuration.model.EventPathsInvalidator;
 import org.hippoecm.hst.configuration.model.HstManager;
 import org.hippoecm.hst.configuration.site.HstSite;
+import org.hippoecm.hst.configuration.sitemap.HstSiteMapItem;
 import org.hippoecm.hst.configuration.sitemenu.HstSiteMenuConfiguration;
 import org.hippoecm.hst.configuration.sitemenu.HstSiteMenuItemConfiguration;
 import org.hippoecm.hst.core.request.ResolvedMount;
@@ -38,8 +44,15 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM;
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_PARAMETER_NAMES;
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_PARAMETER_VALUES;
+import static org.hippoecm.hst.configuration.HstNodeTypes.NODENAME_HST_WORKSPACE;
+import static org.hippoecm.hst.configuration.HstNodeTypes.NODETYPE_HST_SITEMENUITEM;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 public class HstMenuModelsIT extends AbstractTestConfigurations {
@@ -368,4 +381,170 @@
 
     }
 
+    // test inheritance from hst:workspace via inheritsfrom = ../xyz/hst:workspace
+    @Test
+    public void menu_from_workspace_by_default_not_inherited_unless_explicitly_inherited() throws Exception {
+        JcrUtils.copy(session, "/hst:hst/hst:configurations/unittestcommon/hst:sitemenus/main",
+                "/hst:hst/hst:configurations/unittestcommon/hst:sitemenus/footer");
+        session.save();
+
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final Map<String, HstSiteMenuConfiguration> siteMenuConfigurations = mount.getHstSite().getSiteMenusConfiguration().getSiteMenuConfigurations();
+            assertNotNull(siteMenuConfigurations.get("main"));
+            assertNotNull(siteMenuConfigurations.get("footer"));
+            assertFalse(((CanonicalInfo)siteMenuConfigurations.get("main")).isWorkspaceConfiguration());
+        }
+
+        // now move the [/hst:hst/hst:configurations/unittestcommon/hst:sitemenus/footer] to
+        // [/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemenus/footer] and show the 'footer' is not
+        // there any more in the model
+
+        if (!session.nodeExists("/hst:hst/hst:configurations/unittestcommon/hst:workspace")) {
+            session.getNode("/hst:hst/hst:configurations/unittestcommon").addNode(NODENAME_HST_WORKSPACE);
+        }
+        if (!session.nodeExists("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemenus")) {
+            session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:workspace").addNode(HstNodeTypes.NODENAME_HST_SITEMENUS);
+        }
+
+        session.move("/hst:hst/hst:configurations/unittestcommon/hst:sitemenus/footer",
+                "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemenus/footer");
+
+        EventPathsInvalidator invalidator = HstServices.getComponentManager().getComponent(EventPathsInvalidator.class.getName());
+        String[] pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+        session.save();
+        invalidator.eventPaths(pathsToBeChanged);
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final Map<String, HstSiteMenuConfiguration> siteMenuConfigurations = mount.getHstSite().getSiteMenusConfiguration().getSiteMenuConfigurations();
+            assertNotNull(siteMenuConfigurations.get("main"));
+            assertNull(siteMenuConfigurations.get("footer"));
+        }
+
+        // for all kind of inheritance variants below, the 'footer' menu should be inherited now
+        List<String[]> inheritanceVariants = new ArrayList<>();
+        inheritanceVariants.add(new String[]{"../unittestcommon", "../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon", "../unittestcommon/hst:workspace/hst:sitemenus"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace", "../unittestcommon"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:sitemenus", "../unittestcommon"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:sitemenus"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:sitemenus", "../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace", "../unittestcommon/hst:workspace/hst:sitemenus"});
+
+        for (String[] inheritanceVariant : inheritanceVariants) {
+
+            setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                    inheritanceVariant);
+
+            pathsToBeChanged = new String[]{"/hst:hst/hst:configurations/unittestproject"};
+            invalidator.eventPaths(pathsToBeChanged);
+            {
+                VirtualHosts vhosts = hstManager.getVirtualHosts();
+                final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+                final Map<String, HstSiteMenuConfiguration> siteMenuConfigurations = mount.getHstSite().getSiteMenusConfiguration().getSiteMenuConfigurations();
+                assertNotNull(siteMenuConfigurations.get("main"));
+                assertNotNull(siteMenuConfigurations.get("footer"));
+                assertFalse(((CanonicalInfo)siteMenuConfigurations.get("main")).isWorkspaceConfiguration());
+                assertTrue(((CanonicalInfo)siteMenuConfigurations.get("footer")).isWorkspaceConfiguration());
+            }
+            // make sure a change triggers a reload!
+            session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemenus/footer").addNode("newItem", NODETYPE_HST_SITEMENUITEM);
+            pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+            session.save();
+            invalidator.eventPaths(pathsToBeChanged);
+            {
+                VirtualHosts vhosts = hstManager.getVirtualHosts();
+                final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+                final Map<String, HstSiteMenuConfiguration> siteMenuConfigurations = mount.getHstSite().getSiteMenusConfiguration().getSiteMenuConfigurations();
+                boolean expectedItemFound = false;
+                for (HstSiteMenuItemConfiguration itemConfiguration : siteMenuConfigurations.get("footer").getSiteMenuConfigurationItems()) {
+                    if ("newItem".equals(itemConfiguration.getName())) {
+                        expectedItemFound = true;
+                    }
+                }
+                assertTrue(expectedItemFound);
+            }
+
+            session.removeItem("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemenus/footer/newItem");
+            pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+            session.save();
+            invalidator.eventPaths(pathsToBeChanged);
+        }
+    }
+
+
+    @Test
+    public void test_inheritance_precedence() throws Exception {
+        if (!session.nodeExists("/hst:hst/hst:configurations/unittestcommon/hst:workspace")) {
+            session.getNode("/hst:hst/hst:configurations/unittestcommon").addNode(NODENAME_HST_WORKSPACE);
+        }
+
+        session.move("/hst:hst/hst:configurations/unittestproject/hst:sitemap",
+                "/hst:hst/hst:configurations/unittestcommon/hst:sitemap");
+        // hst:pages both below unittestcommon AND below unittestcommon/hst:workspace
+        JcrUtils.copy(session, "/hst:hst/hst:configurations/unittestcommon/hst:sitemap",
+                "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap");
+
+        // both have hst:sitemap/home : Depending on precedence of the hst:inheritsfrom, one of them is merged into the 'unittestproject' model
+        final Node homePageNode = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:sitemap/home");
+        homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_NAMES, new String[]{"location"});
+        homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"non-workspace"});
+        final Node workspaceHomePageNode = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap/home");
+        workspaceHomePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_NAMES, new String[]{"location"});
+        workspaceHomePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"workspace"});
+
+        // add an extra sitemap to workspace
+        JcrUtils.copy(session, "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap/home",
+                "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap/homeAgain");
+
+
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon", "../unittestcommon/hst:workspace"});
+        session.save();
+
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstSiteMapItem item = mount.getHstSite().getSiteMap().getSiteMapItem("home");
+            assertNotNull(item);
+            // since we first inherit ../unittestcommon and *then* ../unittestcommon/hst:workspace, we expect the 'home' from
+            // unittestcommon/hst:sitemap and not from unittestcommon/hst:workspace/hst:sitemap
+            assertEquals("non-workspace", item.getParameter("location"));
+
+            // assert that 'homeAgain' which is only present below 'unittestcommon/hst:workspace/hst:sitemap' is inherited still
+            final HstSiteMapItem itemAgain = mount.getHstSite().getSiteMap().getSiteMapItem("homeAgain");
+            assertNotNull(itemAgain);
+        }
+
+        // switch the inheritance
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon/hst:workspace", "../unittestcommon"});
+
+        EventPathsInvalidator invalidator = HstServices.getComponentManager().getComponent(EventPathsInvalidator.class.getName());
+        session.save();
+        invalidator.eventPaths(new String[]{"/hst:hst/hst:configurations/unittestproject"});
+
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstSiteMapItem item = mount.getHstSite().getSiteMap().getSiteMapItem("home");
+            assertNotNull(item);
+            // since we first inherit ../unittestcommon and *then* ../unittestcommon/hst:workspace, we expect the homepage from
+            // unittestcommon/hst:pages and not from unittestcommon/hst:workspace/hst:pages
+            assertEquals("workspace", item.getParameter("location"));
+        }
+    }
+
+    private void setWorkspaceInheritance(final String hstConfigurationPath, final String[] inheritsFrom) throws RepositoryException {
+        final Node hstConfigNode = session.getNode(hstConfigurationPath);
+        hstConfigNode.setProperty(GENERAL_PROPERTY_INHERITS_FROM, inheritsFrom);
+        session.save();
+    }
+
+    private String getLocalhostRootMountId() throws RepositoryException {
+        return session.getNode("/hst:hst/hst:hosts/dev-localhost/localhost/hst:root").getIdentifier();
+    }
 }
Index: components/core/src/test/java/org/hippoecm/hst/configuration/cache/HstConfigurationLoadingCacheIT.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- components/core/src/test/java/org/hippoecm/hst/configuration/cache/HstConfigurationLoadingCacheIT.java	(revision 55877)
+++ components/core/src/test/java/org/hippoecm/hst/configuration/cache/HstConfigurationLoadingCacheIT.java	(revision )
@@ -62,4 +62,25 @@
         rootConfigEventPath = hstConfigurationLoadingCache.getMainConfigOrRootConfigNodePath(new HstEvent("/hst:hst/hst:configurations/foo[1]/bar/lux/", false));
         assertEquals("/hst:hst/hst:configurations/foo[1]/bar", rootConfigEventPath);
     }
+
+
+    @Test
+    public void testGetRootConfigPathFromWorkspaceEvents() {
+        String rootConfigEventPath = hstConfigurationLoadingCache.getMainConfigOrRootConfigNodePath(new HstEvent("/hst:hst/hst:configurations/foo/hst:workspace", false));
+        assertEquals("/hst:hst/hst:configurations/foo/hst:workspace", rootConfigEventPath);
+
+        rootConfigEventPath = hstConfigurationLoadingCache.getMainConfigOrRootConfigNodePath(
+                new HstEvent("/hst:hst/hst:configurations/foo/hst:workspace/hst:sitemap", false));
+        assertEquals("/hst:hst/hst:configurations/foo/hst:workspace/hst:sitemap", rootConfigEventPath);
+
+
+        rootConfigEventPath = hstConfigurationLoadingCache.getMainConfigOrRootConfigNodePath(
+                new HstEvent("/hst:hst/hst:configurations/foo/hst:workspace/hst:sitemap/test", false));
+        assertEquals("/hst:hst/hst:configurations/foo/hst:workspace/hst:sitemap", rootConfigEventPath);
+        rootConfigEventPath = hstConfigurationLoadingCache.getMainConfigOrRootConfigNodePath(
+
+                new HstEvent("/hst:hst/hst:configurations/foo/hst:workspace/hst:sitemap/test/", false));
+        assertEquals("/hst:hst/hst:configurations/foo/hst:workspace/hst:sitemap", rootConfigEventPath);
+
+    }
 }
Index: components/core/src/test/java/org/hippoecm/hst/configuration/sitemap/SiteMapModelsIT.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- components/core/src/test/java/org/hippoecm/hst/configuration/sitemap/SiteMapModelsIT.java	(revision 55877)
+++ components/core/src/test/java/org/hippoecm/hst/configuration/sitemap/SiteMapModelsIT.java	(revision )
@@ -15,12 +15,18 @@
  */
 package org.hippoecm.hst.configuration.sitemap;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.jcr.Node;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.SimpleCredentials;
 
 import org.hippoecm.hst.configuration.HstNodeTypes;
+import org.hippoecm.hst.configuration.components.HstComponentConfiguration;
+import org.hippoecm.hst.configuration.hosting.Mount;
+import org.hippoecm.hst.configuration.hosting.VirtualHosts;
 import org.hippoecm.hst.configuration.internal.CanonicalInfo;
 import org.hippoecm.hst.configuration.model.EventPathsInvalidator;
 import org.hippoecm.hst.configuration.model.HstManager;
@@ -36,11 +42,13 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import junit.framework.Assert;
-import static junit.framework.Assert.assertNull;
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM;
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_PARAMETER_NAMES;
+import static org.hippoecm.hst.configuration.HstNodeTypes.GENERAL_PROPERTY_PARAMETER_VALUES;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 public class SiteMapModelsIT extends AbstractTestConfigurations {
@@ -81,7 +89,7 @@
         CanonicalInfo siteMapCanonicalInfo = (CanonicalInfo)siteMap;
         assertFalse(siteMapCanonicalInfo.isWorkspaceConfiguration());
         final Node siteMapNode = session.getNodeByIdentifier(siteMapCanonicalInfo.getCanonicalIdentifier());
-        assertTrue(siteMapNode.getPath().equals(hstSite.getConfigurationPath()+"/hst:sitemap"));
+        assertTrue(siteMapNode.getPath().equals(hstSite.getConfigurationPath() + "/hst:sitemap"));
 
         for (HstSiteMapItem hstSiteMapItem : siteMap.getSiteMapItems()) {
             if (hstSiteMapItem.getQualifiedId().contains("hst:default")) {
@@ -109,7 +117,7 @@
         CanonicalInfo siteMapCanonicalInfo = (CanonicalInfo)siteMap;
         assertTrue(siteMapCanonicalInfo.isWorkspaceConfiguration());
         final Node siteMapNode = session.getNodeByIdentifier(siteMapCanonicalInfo.getCanonicalIdentifier());
-        assertTrue(siteMapNode.getPath().equals(hstSite.getConfigurationPath()+"/hst:workspace/hst:sitemap"));
+        assertTrue(siteMapNode.getPath().equals(hstSite.getConfigurationPath() + "/hst:workspace/hst:sitemap"));
 
         for (HstSiteMapItem hstSiteMapItem : siteMap.getSiteMapItems()) {
             if (hstSiteMapItem.getQualifiedId().contains("hst:default")) {
@@ -119,7 +127,7 @@
             CanonicalInfo siteMapItemCanonicalInfo = (CanonicalInfo)hstSiteMapItem;
             assertTrue(siteMapItemCanonicalInfo.isWorkspaceConfiguration());
             final Node siteMapItemNode = session.getNodeByIdentifier(siteMapItemCanonicalInfo.getCanonicalIdentifier());
-            assertTrue(siteMapItemNode.getPath().startsWith(hstSite.getConfigurationPath()+"/hst:workspace/hst:sitemap"));
+            assertTrue(siteMapItemNode.getPath().startsWith(hstSite.getConfigurationPath() + "/hst:workspace/hst:sitemap"));
         }
     }
 
@@ -139,20 +147,20 @@
         assertFalse(siteMapCanonicalInfo.isWorkspaceConfiguration());
 
         final Node siteMapNode = session.getNodeByIdentifier(siteMapCanonicalInfo.getCanonicalIdentifier());
-        assertTrue(siteMapNode.getPath().equals(hstSite.getConfigurationPath()+"/hst:sitemap"));
+        assertTrue(siteMapNode.getPath().equals(hstSite.getConfigurationPath() + "/hst:sitemap"));
 
         HstSiteMapItem home = siteMap.getSiteMapItem("home");
         CanonicalInfo homeCanonicalInfo = (CanonicalInfo)home;
         assertTrue(homeCanonicalInfo.isWorkspaceConfiguration());
         final Node homeNode = session.getNodeByIdentifier(homeCanonicalInfo.getCanonicalIdentifier());
-        assertTrue(homeNode.getPath().startsWith(hstSite.getConfigurationPath()+"/hst:workspace/hst:sitemap"));
+        assertTrue(homeNode.getPath().startsWith(hstSite.getConfigurationPath() + "/hst:workspace/hst:sitemap"));
 
         for (HstSiteMapItem hstSiteMapItem : siteMap.getSiteMapItems()) {
             CanonicalInfo siteMapItemCanonicalInfo = (CanonicalInfo)hstSiteMapItem;
             if (hstSiteMapItem.getValue().equals("home")) {
                 assertTrue(siteMapItemCanonicalInfo.isWorkspaceConfiguration());
                 final Node siteMapItemNode = session.getNodeByIdentifier(siteMapItemCanonicalInfo.getCanonicalIdentifier());
-                assertTrue(siteMapItemNode.getPath().startsWith(hstSite.getConfigurationPath()+"/hst:workspace/hst:sitemap"));
+                assertTrue(siteMapItemNode.getPath().startsWith(hstSite.getConfigurationPath() + "/hst:workspace/hst:sitemap"));
             } else {
                 assertFalse(siteMapItemCanonicalInfo.isWorkspaceConfiguration());
                 final Node siteMapItemNode = session.getNodeByIdentifier(siteMapItemCanonicalInfo.getCanonicalIdentifier());
@@ -177,7 +185,7 @@
         assertFalse(siteMapCanonicalInfo.isWorkspaceConfiguration());
 
         final Node siteMapNode = session.getNodeByIdentifier(siteMapCanonicalInfo.getCanonicalIdentifier());
-        assertTrue(siteMapNode.getPath().equals(hstSite.getConfigurationPath()+"/hst:sitemap"));
+        assertTrue(siteMapNode.getPath().equals(hstSite.getConfigurationPath() + "/hst:sitemap"));
 
         HstSiteMapItem home = siteMap.getSiteMapItem("home");
         CanonicalInfo homeCanonicalInfo = (CanonicalInfo)home;
@@ -208,7 +216,7 @@
             CanonicalInfo homeCanonicalInfo = (CanonicalInfo)home;
             assertTrue(homeCanonicalInfo.isWorkspaceConfiguration());
             final Node homeNode = session.getNodeByIdentifier(homeCanonicalInfo.getCanonicalIdentifier());
-            assertTrue(homeNode.getPath().startsWith(hstSite.getConfigurationPath()+"/hst:workspace/hst:sitemap"));
+            assertTrue(homeNode.getPath().startsWith(hstSite.getConfigurationPath() + "/hst:workspace/hst:sitemap"));
         }
 
         {
@@ -240,11 +248,11 @@
         CanonicalInfo homeCanonicalInfo = (CanonicalInfo)home;
         assertTrue(homeCanonicalInfo.isWorkspaceConfiguration());
         final Node homeNode = session.getNodeByIdentifier(homeCanonicalInfo.getCanonicalIdentifier());
-        assertTrue(homeNode.getPath().startsWith(hstSite.getConfigurationPath()+"/hst:workspace/hst:sitemap"));
+        assertTrue(homeNode.getPath().startsWith(hstSite.getConfigurationPath() + "/hst:workspace/hst:sitemap"));
     }
 
     @Test
-    public void test_workspace_in_inherited_sitemap_is_ignored() throws Exception {
+    public void workspace_sitemap_from_inherited_configuration_is_by_default_ignored() throws Exception {
         session.getNode("/hst:hst/hst:configurations/unittestcommon").addNode("hst:workspace").addNode("hst:sitemap");
         session.move("/hst:hst/hst:configurations/unittestproject/hst:sitemap/home",
                 "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap/home");
@@ -254,15 +262,169 @@
         final HstSiteMap siteMap = hstSite.getSiteMap();
         assertNull(siteMap.getSiteMapItem("home"));
     }
+
+    // test inheritance from hst:workspace via inheritsfrom = ../xyz/hst:workspace
+    @Test
+    public void hst_sitemap_from_workspace_by_default_not_inherited_unless_explicitly_inherited() throws Exception {
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstSiteMapItem item = mount.getHstSite().getSiteMap().getSiteMapItem("home");
+            assertNotNull(item);
+            assertFalse(((CanonicalInfo)item).isWorkspaceConfiguration());
+        }
+        // now move the [/hst:hst/hst:configurations/unittestcommon/hst:pages] to
+        // [/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:pages] and show the 'homepage' is not there
+        // any more in the model
+
+        if (!session.nodeExists("/hst:hst/hst:configurations/unittestcommon/hst:workspace")) {
+            session.getNode("/hst:hst/hst:configurations/unittestcommon").addNode(HstNodeTypes.NODENAME_HST_WORKSPACE);
+        }
+        session.move("/hst:hst/hst:configurations/unittestproject/hst:sitemap",
+                "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap");
+
+        EventPathsInvalidator invalidator = HstServices.getComponentManager().getComponent(EventPathsInvalidator.class.getName());
+        String[] pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+        session.save();
+        invalidator.eventPaths(pathsToBeChanged);
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstSiteMapItem item = mount.getHstSite().getSiteMap().getSiteMapItem("home");
+            assertNull(item);
+        }
+
+        // for all kind of inheritance variants below, the 'home' sitemap item should be inherited
+        List<String[]> inheritanceVariants = new ArrayList<>();
+        inheritanceVariants.add(new String[]{"../unittestcommon", "../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon", "../unittestcommon/hst:workspace/hst:sitemap"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace", "../unittestcommon"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:sitemap", "../unittestcommon"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:sitemap"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace/hst:sitemap", "../unittestcommon/hst:workspace"});
+        inheritanceVariants.add(new String[]{"../unittestcommon/hst:workspace", "../unittestcommon/hst:workspace/hst:sitemap"});
+
+        for (String[] inheritanceVariant : inheritanceVariants) {
+
+            setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                    inheritanceVariant);
+
+            pathsToBeChanged = new String[]{"/hst:hst/hst:configurations/unittestproject"};
+            invalidator.eventPaths(pathsToBeChanged);
+            {
+                VirtualHosts vhosts = hstManager.getVirtualHosts();
+                final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+                final HstSiteMapItem item = mount.getHstSite().getSiteMap().getSiteMapItem("home");
+                assertNotNull(item);
+                assertTrue(((CanonicalInfo)item).isWorkspaceConfiguration());
+                assertNull(item.getParameter("foo"));
+            }
+            // make sure a change triggers a reload!
+            final Node homePageNode = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap/home");
+            homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_NAMES, new String[]{"foo"});
+            homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"bar"});
+            pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+            session.save();
+            invalidator.eventPaths(pathsToBeChanged);
+            {
+                VirtualHosts vhosts = hstManager.getVirtualHosts();
+                final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+                final HstSiteMapItem item = mount.getHstSite().getSiteMap().getSiteMapItem("home");
+                // assert that the change is reloaded
+                assertEquals("bar", item.getParameter("foo"));
+            }
+
+            homePageNode.getProperty(GENERAL_PROPERTY_PARAMETER_NAMES).remove();
+            homePageNode.getProperty(GENERAL_PROPERTY_PARAMETER_VALUES).remove();
+            pathsToBeChanged = JcrSessionUtils.getPendingChangePaths(session, session.getNode("/hst:hst"), false);
+            session.save();
+            invalidator.eventPaths(pathsToBeChanged);
+        }
+    }
+
+
+    @Test
+    public void test_inheritance_precedence() throws Exception {
+        if (!session.nodeExists("/hst:hst/hst:configurations/unittestcommon/hst:workspace")) {
+            session.getNode("/hst:hst/hst:configurations/unittestcommon").addNode(HstNodeTypes.NODENAME_HST_WORKSPACE);
+        }
+
+        session.move("/hst:hst/hst:configurations/unittestproject/hst:sitemap",
+                "/hst:hst/hst:configurations/unittestcommon/hst:sitemap");
+        // hst:pages both below unittestcommon AND below unittestcommon/hst:workspace
+        JcrUtils.copy(session, "/hst:hst/hst:configurations/unittestcommon/hst:sitemap",
+                "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap");
+
+        // both have hst:sitemap/home : Depending on precedence of the hst:inheritsfrom, one of them is merged into the 'unittestproject' model
+        final Node homePageNode = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:sitemap/home");
+        homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_NAMES, new String[]{"location"});
+        homePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"non-workspace"});
+        final Node workspaceHomePageNode = session.getNode("/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap/home");
+        workspaceHomePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_NAMES, new String[]{"location"});
+        workspaceHomePageNode.setProperty(GENERAL_PROPERTY_PARAMETER_VALUES, new String[]{"workspace"});
+
+        // add an extra sitemap to workspace
+        JcrUtils.copy(session, "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap/home",
+                "/hst:hst/hst:configurations/unittestcommon/hst:workspace/hst:sitemap/homeAgain");
+
+
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon", "../unittestcommon/hst:workspace"});
+        session.save();
+
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstSiteMapItem item = mount.getHstSite().getSiteMap().getSiteMapItem("home");
+            assertNotNull(item);
+            // since we first inherit ../unittestcommon and *then* ../unittestcommon/hst:workspace, we expect the 'home' from
+            // unittestcommon/hst:sitemap and not from unittestcommon/hst:workspace/hst:sitemap
+            assertEquals("non-workspace", item.getParameter("location"));
+
+            // assert that 'homeAgain' which is only present below 'unittestcommon/hst:workspace/hst:sitemap' is inherited still
+            final HstSiteMapItem itemAgain = mount.getHstSite().getSiteMap().getSiteMapItem("homeAgain");
+            assertNotNull(itemAgain);
+        }
+
+        // switch the inheritance
+        setWorkspaceInheritance("/hst:hst/hst:configurations/unittestproject",
+                new String[]{"../unittestcommon/hst:workspace", "../unittestcommon"});
+
+        EventPathsInvalidator invalidator = HstServices.getComponentManager().getComponent(EventPathsInvalidator.class.getName());
+        session.save();
+        invalidator.eventPaths(new String[]{"/hst:hst/hst:configurations/unittestproject"});
+
+        {
+            VirtualHosts vhosts = hstManager.getVirtualHosts();
+            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final HstSiteMapItem item = mount.getHstSite().getSiteMap().getSiteMapItem("home");
+            assertNotNull(item);
+            // since we first inherit ../unittestcommon and *then* ../unittestcommon/hst:workspace, we expect the homepage from
+            // unittestcommon/hst:pages and not from unittestcommon/hst:workspace/hst:pages
+            assertEquals("workspace", item.getParameter("location"));
+        }
+    }
+
+    private void setWorkspaceInheritance(final String hstConfigurationPath, final String[] inheritsFrom) throws RepositoryException {
+        final Node hstConfigNode = session.getNode(hstConfigurationPath);
+        hstConfigNode.setProperty(GENERAL_PROPERTY_INHERITS_FROM, inheritsFrom);
+        session.save();
+    }
+
+    private String getLocalhostRootMountId() throws RepositoryException {
+        return session.getNode("/hst:hst/hst:hosts/dev-localhost/localhost/hst:root").getIdentifier();
+    }
+
 
     @Test
-    public void marked_deleted_nodes_are_part_of_hst_model_but_ignored_while_matching()  throws Exception {
+    public void marked_deleted_nodes_are_part_of_hst_model_but_ignored_while_matching() throws Exception {
 
         ResolvedMount mount = hstManager.getVirtualHosts().matchMount("localhost", "/site", "/");
         ResolvedSiteMapItem matchedItemForHomePage = mount.matchSiteMapItem("/");
         ResolvedSiteMapItem matchedItemForNewsFoo = mount.matchSiteMapItem("/news/foo");
-        assertEquals("home",matchedItemForHomePage.getHstSiteMapItem().getId());
+        assertEquals("home", matchedItemForHomePage.getHstSiteMapItem().getId());
-        assertEquals("news/_default_",matchedItemForNewsFoo.getHstSiteMapItem().getId());
+        assertEquals("news/_default_", matchedItemForNewsFoo.getHstSiteMapItem().getId());
 
         final Node home = session.getNode("/hst:hst/hst:configurations/unittestproject/hst:sitemap/home");
         home.addMixin(HstNodeTypes.MIXINTYPE_HST_EDITABLE);
@@ -292,7 +454,7 @@
     }
 
     @Test
-    public void marked_deleted_nodes_their_children_are_marked_deleted_as_well()  throws Exception {
+    public void marked_deleted_nodes_their_children_are_marked_deleted_as_well() throws Exception {
         final Node news = session.getNode("/hst:hst/hst:configurations/unittestproject/hst:sitemap/news");
         news.addMixin(HstNodeTypes.MIXINTYPE_HST_EDITABLE);
         news.setProperty(HstNodeTypes.EDITABLE_PROPERTY_STATE, "deleted");
Index: components/core/src/test/resources/log4j-filters.txt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- components/core/src/test/resources/log4j-filters.txt	(revision 55877)
+++ components/core/src/test/resources/log4j-filters.txt	(revision )
@@ -1,5 +1,5 @@
 #
-#  Copyright 2013 Hippo B.V. (http://www.onehippo.com)
+#  Copyright 2013-2015 Hippo B.V. (http://www.onehippo.com)
 #
 #  Licensed under the Apache License, Version 2.0 (the  "License");
 #  you may not use this file except in compliance with the License.
@@ -20,4 +20,7 @@
 Cannot load channels because node '/hst:hst/hst:channels' does not exist
 Unknown channel /hst:hst/hst:channels/testchannel, ignoring mount hst:root
 Please correct the configuration because duplicate configuration nodes found
-Cannot add cms location
\ No newline at end of file
+Cannot add cms location
+Cannot lookup referenced component
+Cannot find hst:template
+Relative inherit path '../unittestcommon/hst:workspace/hst:containers/myReferenceableContainer'
\ No newline at end of file
Index: components/core/src/test/java/org/hippoecm/hst/configuration/HstComponentsConfigurationModelsIT.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- components/core/src/test/java/org/hippoecm/hst/configuration/HstComponentsConfigurationModelsIT.java	(revision 55877)
+++ components/core/src/test/java/org/hippoecm/hst/configuration/HstComponentsConfigurationModelsIT.java	(revision )
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2011-2013 Hippo B.V. (http://www.onehippo.com)
+ *  Copyright 2011-2015 Hippo B.V. (http://www.onehippo.com)
  * 
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@
 import org.hippoecm.hst.site.HstServices;
 import org.hippoecm.hst.test.AbstractTestConfigurations;
 import org.hippoecm.hst.util.JcrSessionUtils;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -47,44 +48,59 @@
 public class HstComponentsConfigurationModelsIT extends AbstractTestConfigurations {
 
     private HstManager hstManager;
+    private Session session;
 
     @Override
     @Before
     public void setUp() throws Exception {
         super.setUp();
         hstManager = getComponent(HstManager.class.getName());
+        this.session = createSession();
+        createHstConfigBackup(session);
     }
 
+    @Override
+    @After
+    public void tearDown() throws Exception {
+        restoreHstConfigBackup(session);
+        session.logout();
+        super.tearDown();
+    }
+
+
     /**
      * All the mounts that share the same items for:
      * <ol>
-     *  <li>hst:pages</li>
+     * <li>hst:pages</li>
-     *  <li>hst:components</li>
+     * <li>hst:components</li>
-     *  <li>hst:templates</li>
+     * <li>hst:templates</li>
-     *  <li>hst:catalog</li>
+     * <li>hst:catalog</li>
-     *  <li>hst:workspace</li>
+     * <li>hst:workspace</li>
      * </ol>
-     * 
+     * <p/>
-     * MUST also share the same {@link HstComponentsConfigurationService}. This also 
+     * MUST also share the same {@link HstComponentsConfigurationService}. This also
-     * holds of course of the items above are coming from inherited configuration. If the {@link HstComponentConfigurationService}
+     * holds of course of the items above are coming from inherited configuration. If the {@link
+     * HstComponentConfigurationService}
-     * is not shared, memory footprint of the HST model will become very large and loading of the model 
+     * is not shared, memory footprint of the HST model will become very large and loading of the model
      * becomes slow. The model MUST always be shared. This unit test verifies that
-     * 
-     * For the unittest content we have all the available hst:configuration inherit from the hst:configuration 'unittestcommon' :
-     * This is the configuration that contains the pages, components and templates for all the {@link Mount}s. Thus, all 
+     * <p/>
+     * For the unittest content we have all the available hst:configuration inherit from the hst:configuration
+     * 'unittestcommon' :
+     * This is the configuration that contains the pages, components and templates for all the {@link Mount}s. Thus,
+     * all
-     * {@link HstComponentsConfigurationService}s for the unittest model should be the same, EXCEPT for 
-     * the Mounts that point to '/hst:hst/hst:sites/unittestsubproject' which in turn refers to   
+     * {@link HstComponentsConfigurationService}s for the unittest model should be the same, EXCEPT for
+     * the Mounts that point to '/hst:hst/hst:sites/unittestsubproject' which in turn refers to
-     * '/hst:hst/hst:configurations/unittestsubproject' : This unittestsubproject has its own hst:pages/homepage (which is only meant for this unit test to validate the 
+     * '/hst:hst/hst:configurations/unittestsubproject' : This unittestsubproject has its own hst:pages/homepage (which
+     * is only meant for this unit test to validate the
      * correct working of inheriting {@link HstComponentsConfigurationService}s only
      * when all pages, components, templates and catalogs are the same)
-     * 
+     *
      * @throws Exception
      */
     @Test
     public void testSharedHstComponentsConfigurations() throws Exception {
         // since unittestproject contains its own 'hst:prototypepages' node, we first move this node away (otherwise
         // instance won't be shared)
-        Session session = createSession();
         removePagePrototypeFromConfig(session);
 
         ResolvedMount mount1 = hstManager.getVirtualHosts().matchMount("www.unit.test", "/site", "/");
@@ -128,35 +144,33 @@
         HstComponentsConfiguration service9 = mount9.getMount().getHstSite().getComponentsConfiguration();
         HstComponentsConfiguration service10 = mount10.getMount().getHstSite().getComponentsConfiguration();
         HstComponentsConfiguration service11 = mount11.getMount().getHstSite().getComponentsConfiguration();
-        
+
         HstComponentsConfiguration WithDiffHstCompServ1 = mountWithDiffHstCompServ1.getMount().getHstSite().getComponentsConfiguration();
         HstComponentsConfiguration WithDiffHstCompServ2 = mountWithDiffHstCompServ2.getMount().getHstSite().getComponentsConfiguration();
 
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service2);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service2);
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service4);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service4);
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service5);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service5);
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service6);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service6);
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service7);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service7);
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service8);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service8);
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service9);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service9);
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service10);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service10);
-        assertSame("Expected shared HstComponentsConfiguration objects failed", service1 , service11);
+        assertSame("Expected shared HstComponentsConfiguration objects failed", service1, service11);
 
-        assertNotSame("Expected non shared HstComponentsConfiguration objects failed", service1 , WithDiffHstCompServ1);
+        assertNotSame("Expected non shared HstComponentsConfiguration objects failed", service1, WithDiffHstCompServ1);
-        assertNotSame("Expected non shared HstComponentsConfiguration objects failed", service1 , WithDiffHstCompServ2);
+        assertNotSame("Expected non shared HstComponentsConfiguration objects failed", service1, WithDiffHstCompServ2);
 
-        restorePagePrototypesFromConfig(session);
-        session.logout();
     }
 
     /**
      * HstComponentsConfigurationService instance are reused between models after changes if the changes
      * could never have effect on them.
+     *
      * @throws Exception
      */
     @Test
     public void testReloadOnlyChangedHstComponentsConfigurations() throws Exception {
-        final Session session = createSession();
         removePagePrototypeFromConfig(session);
 
         final ResolvedMount mountBefore1 = hstManager.getVirtualHosts().matchMount("www.unit.test", "/site", "/");
@@ -254,10 +268,6 @@
         assertSame(componenentConfigsThirdAfter1, componenentConfigsThirdAfter2);
         assertSame(componenentConfigsThirdAfter1, componenentConfigsBefore1);
 
-        session.getNode("/hst:hst/hst:configurations/global").getNode("hst:sitemenus").remove();
-        session.save();
-        restorePagePrototypesFromConfig(session);
-        session.logout();
     }
 
 
@@ -277,7 +287,6 @@
         HstComponentsConfiguration service6 = mount6.getMount().getHstSite().getComponentsConfiguration();
         HstComponentsConfiguration service7 = mount7.getMount().getHstSite().getComponentsConfiguration();
 
-        final Session session = createSession();
         Node defaultComponents = session.getNode("/hst:hst/hst:configurations/hst:default/hst:components");
         defaultComponents.addNode("testNewUniqueNamedNodeInHstDefaultConfigurationTriggersReloadAll", "hst:component");
 
@@ -337,10 +346,6 @@
         assertSame(serviceAgain6, serviceAfter6);
         assertSame(serviceAgain7, serviceAfter7);
 
-        session.getNode("/hst:hst/hst:configurations/hst:default/hst:sitemap").getNode("testNewUniqueNamedNodeInHstDefaultConfigurationTriggersReloadAll").remove();
-        session.getNode("/hst:hst/hst:configurations/hst:default/hst:components").getNode("testNewUniqueNamedNodeInHstDefaultConfigurationTriggersReloadAll").remove();
-        session.save();
-        session.logout();
     }
 
     @Test
@@ -359,9 +364,8 @@
         HstComponentsConfiguration service6 = mount6.getMount().getHstSite().getComponentsConfiguration();
         HstComponentsConfiguration service7 = mount7.getMount().getHstSite().getComponentsConfiguration();
 
-        final Session session = createSession();
         Node configurationsNode = session.getNode("/hst:hst/hst:configurations");
-        Node commonCatalog = configurationsNode.addNode("hst:catalog","hst:catalog");
+        Node commonCatalog = configurationsNode.addNode("hst:catalog", "hst:catalog");
         commonCatalog.addNode("testNewUniqueNamedNodeInCommonCatalogTriggersReloadAll", "hst:containeritempackage");
 
         EventPathsInvalidator invalidator = HstServices.getComponentManager().getComponent(EventPathsInvalidator.class.getName());
@@ -389,9 +393,7 @@
         assertNotSame(service5, serviceAfter5);
         assertNotSame(service6, serviceAfter6);
         assertNotSame(service7, serviceAfter7);
-        session.getNode("/hst:hst/hst:configurations/hst:catalog").remove();
-        session.save();
-        session.logout();
+
     }
 
     @Test
@@ -401,7 +403,6 @@
         // there is one explicit non inherited component, and that is
         // hst:hst/hst:configurations/unittestsubproject/hst:pages/homepage
 
-
         final String explicitNonInheritedComponent = "/hst:hst/hst:configurations/unittestsubproject/hst:pages/homepage";
         final VirtualHosts virtualHosts = hstManager.getVirtualHosts();
         final List<String> hostGroupNames = virtualHosts.getHostGroupNames();
@@ -437,17 +438,10 @@
         }
     }
 
-
-    private void restorePagePrototypesFromConfig(final Session session) throws RepositoryException {
-        session.move("/hst:prototypepages", "/hst:hst/hst:configurations/unittestproject/hst:prototypepages");
-        session.save();
-    }
-
     private void removePagePrototypeFromConfig(final Session session) throws RepositoryException {
         session.move("/hst:hst/hst:configurations/unittestproject/hst:prototypepages", "/hst:prototypepages");
         session.save();
     }
-
 
     protected Session createSession() throws RepositoryException {
         Repository repository = HstServices.getComponentManager().getComponent(Repository.class.getName() + ".delegating");
