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 56128)
+++ components/core/src/test/java/org/hippoecm/hst/configuration/ContainerComponentConfigurationsIT.java	(revision )
@@ -368,53 +368,47 @@
     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();
+        assertInheritanceAndModelReloadWorks(getLocalhostRootMountId());
     }
 
     @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();
+        assertInheritanceAndModelReloadWorks(getLocalhostRootMountId());
     }
 
     @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();
+        assertInheritanceAndModelReloadWorks(getLocalhostRootMountId());
     }
 
     @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();
+        assertInheritanceAndModelReloadWorks(getLocalhostRootMountId());
     }
 
     @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");
+    public void cascading_non_workspace_inheritance() throws Exception {
 
-        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);
-        }
+    }
+
+    @Test
+    public void cascading_workspace_inheritance() throws Exception {
+
     }
 
-    private void assertInheritanceAndModelReloadWorks() throws Exception {
+    @Test
+    public void cascading_workspace_children_inheritance() throws Exception {
 
+    }
+
+    private void assertInheritanceAndModelReloadWorks(final String mountId) throws Exception {
+
         createHstWorkspaceAndReferenceableContainer("myReferenceableContainer",
                 "/hst:hst/hst:configurations/unittestcommon");
 
@@ -422,7 +416,7 @@
         addComponentReference(testComponent, inheritedContainerName, "myReferenceableContainer");
         {
             final VirtualHosts vhosts = hstSitesManager.getVirtualHosts();
-            final Mount mount = vhosts.getMountByIdentifier(getLocalhostRootMountId());
+            final Mount mount = vhosts.getMountByIdentifier(mountId);
             final HstComponentConfiguration pageComponent = mount.getHstSite().getComponentsConfiguration().getComponentConfiguration("hst:pages/homepage");
             final HstComponentConfiguration testComponent = pageComponent.getChildByName(TEST_COMPONENT_NODE_NAME);
             assertNotNull(testComponent);
@@ -457,6 +451,27 @@
             assertTrue(item.isInherited());
         }
 
+    }
+
+    @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);
+        }
     }
 
     /**
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 56128)
+++ components/core/src/main/java/org/hippoecm/hst/configuration/cache/CompositeConfigurationNodes.java	(revision )
@@ -1,12 +1,12 @@
 /*
  *  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.
  *  You may obtain a copy of the License at
- * 
+ *
  *       http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,8 +18,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 
 import org.apache.commons.lang.StringUtils;
@@ -61,40 +63,94 @@
 
         // Add all the explicitly inherited hst:configuration nodes.
         if (configurationRootNode.getValueProvider().hasProperty(HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM)) {
-
+            final Set<String> alreadyInherited = new HashSet<>();
             String[] inherits = configurationRootNode.getValueProvider().getStrings(HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM);
             for (String inheritPath : inherits) {
-                if (!inheritPath.startsWith("../")) {
-                    log.warn("hst:inheritsfrom property must start with ../ but this is not the case for '{}'. We skip this inherit", configurationRootNode.getValueProvider().getPath());
-                    continue;
+                addInherited(configurationRootNode, configurationsNode, inheritPath, relPaths, alreadyInherited);
-                }
+            }
-                String hstConfigsInheritedRelPath = inheritPath.substring(3);
+        }
 
+        // add the hst:default node as last one
+        HstNode defaultConfigurationRootHstNode = configurationsNode.getNode(HstNodeTypes.NODENAME_HST_HSTDEFAULT);
+        if (defaultConfigurationRootHstNode != null) {
+            orderedRootConfigurationNodeInheritanceList.add(defaultConfigurationRootHstNode);
+        }
+    }
+
+    private void addInherited(final HstNode configurationRootNode, final HstNode configurationsNode,
+                              final String inheritPath, final String[] relPaths, final Set<String> alreadyInherited) {
+
+
+        String hstConfigsInheritedRelPath = inheritPath.substring(3);
-                String absHstConfigsInheritedPath = configurationsNode.getValueProvider().getPath() + "/" + hstConfigsInheritedRelPath;
+        String absHstConfigsInheritedPath = configurationsNode.getValueProvider().getPath() + "/" + hstConfigsInheritedRelPath;
+        HstNode inheritConfig = configurationsNode.getNode(hstConfigsInheritedRelPath);
-                // 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));
+        // 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) {
+            log.debug("inherited configuration for '{}' is null", hstConfigsInheritedRelPath);
+            return;
+        }
+        if (alreadyInherited.contains(inheritConfig.getValueProvider().getIdentifier())) {
+            log.debug("Already inherited configuration '{}' for '{}'", configurationRootNode.getValueProvider().getPath(), inheritPath);
+            return;
+        }
+        alreadyInherited.add(inheritConfig.getValueProvider().getIdentifier() + "-" + inheritPath);
+
-                if (inheritConfig != null && isValidInheritedNode(inheritConfig)) {
-                    orderedRootConfigurationNodeInheritanceList.add(inheritConfig);
+        if (inheritConfig != null && isValidInheritedNode(inheritConfig)) {
+            orderedRootConfigurationNodeInheritanceList.add(inheritConfig);
-                    if (inheritConfig.getValueProvider().hasProperty(HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM)) {
-                        log.warn("Skipping inheritfrom property for configuration node '{}' because this node is already inherit. Not allowed to inherit again", inheritConfig.getValueProvider().getPath());
+
+            HstNode rootInheritedConfiguration = getHstConfiguration(inheritConfig);
+            if (rootInheritedConfiguration.getValueProvider().hasProperty(HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM)) {
+                String[] cascadingInheritedPaths = rootInheritedConfiguration.getValueProvider().getStrings(HstNodeTypes.GENERAL_PROPERTY_INHERITS_FROM);
+                for (String cascadingInheritedPath : cascadingInheritedPaths) {
+                    if (hstConfigsInheritedRelPath.contains("/")) {
+                        // inheritance is something like ../common/hst:workspace or ../common/hst:workspace/hst:pages
+                        // only inherit via cascading the same relative path
+                        final String relPath = StringUtils.substringAfter(hstConfigsInheritedRelPath, "/");
+                        if (cascadingInheritedPath.endsWith(hstConfigsInheritedRelPath)) {
+                            // if inherited config exists, inherit, otherwise skip
+                            final HstNode cascading = configurationsNode.getNode(StringUtils.substringBefore(hstConfigsInheritedRelPath, "/"));
+                            if (cascading == null) {
+                                log.debug("No cascading config present at '{}' for '{}'. Skip it.", relPath, configurationRootNode.getValueProvider().getPath());
+                            } else {
+                                addInherited(cascading, configurationsNode, cascadingInheritedPath, relPaths, alreadyInherited);
-                    }
-                } else {
+                            }
+                        } else {
+                            log.debug("Do not cascade inheritance for '{}' for '{}'", cascadingInheritedPath, configurationRootNode.getValueProvider().getPath());
+                        }
+                    } else {
+                        // cascading inheritance
+                        final HstNode cascading = configurationsNode.getNode(hstConfigsInheritedRelPath);
+                        if (cascading == null) {
+                            log.debug("No cascading config present at '{}' for '{}'. Skip it.", hstConfigsInheritedRelPath, configurationRootNode.getValueProvider().getPath());
+                        } else {
+                            addInherited(cascading, configurationsNode, cascadingInheritedPath, relPaths, alreadyInherited);
+                        }
+                    }
+                }
+            }
+        } else {
-                    log.error("Relative inherit path '{}' for node '{}' does not point to a node of type " +
-                                    "'{}' or '{}', or it does not point to a child node of '{}', or it does not exist. Fix this path.",
-                            new String[]{inheritPath, configurationRootNode.getValueProvider().getPath(),
-                                    NODETYPE_HST_CONFIGURATION, NODETYPE_HST_WORKSPACE, NODENAME_HST_WORKSPACE});
-                }
-            }
+            log.error("Relative inherit path '{}' for node '{}' does not point to a node of type " +
+                            "'{}' or '{}', or it does not point to a child node of '{}', or it does not exist. Fix this path.",
+                    new String[]{inheritPath, configurationRootNode.getValueProvider().getPath(),
+                            NODETYPE_HST_CONFIGURATION, NODETYPE_HST_WORKSPACE, NODENAME_HST_WORKSPACE});
+        }
+    }
-        }
 
-        // add the hst:default node as last one
-        HstNode defaultConfigurationRootHstNode = configurationsNode.getNode(HstNodeTypes.NODENAME_HST_HSTDEFAULT);
-        if (defaultConfigurationRootHstNode != null) {
-            orderedRootConfigurationNodeInheritanceList.add(defaultConfigurationRootHstNode);
+    private HstNode getHstConfiguration(final HstNode inheritConfig) {
+        if  (NODETYPE_HST_CONFIGURATION.equals(inheritConfig.getNodeTypeName())) {
+            return inheritConfig;
         }
+        if (NODETYPE_HST_WORKSPACE.equals(inheritConfig.getNodeTypeName())) {
+            return inheritConfig.getParent();
+        }
+        if (NODETYPE_HST_WORKSPACE.equals(inheritConfig.getParent().getNodeTypeName())) {
+            return inheritConfig.getParent().getParent();
+        }
+        throw new IllegalArgumentException(String.format("Illegal Inherited configuration '%s' should not be possible at this point.",
+                inheritConfig.getValueProvider().getPath()));
     }
 
     /**
@@ -151,11 +207,11 @@
                         // 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) ) {
+                            && 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
+                        log.debug("Merging explicitly inherited workspace configuration for '{}'",
+                                inherited.getValueProvider().getPath());
+                        // hst:inheritsfrom is something like ../common/hst:workspace/hst:pages
                         workspaceAccountedRelativeInheritPath = "";
 
                     } else {
