Commit d64308f0 authored by Bert Leunis's avatar Bert Leunis

HSTTWO-4242 Merge master changes in feature/HSTTWO-4242

parents c9320918 3c418fab
......@@ -15,19 +15,12 @@
*/
package org.hippoecm.hst.configuration.site;
import org.onehippo.cms7.services.hst.Channel;
import org.hippoecm.hst.configuration.hosting.Mount;
import org.hippoecm.hst.core.request.HstRequestContext;
import org.onehippo.cms7.services.hst.Channel;
@FunctionalInterface
public interface HstSiteProvider {
/**
* This key is used to store the map on the http session of the webmaster in the channel mngr. The map will contain
* which branch should be used for a mount. The mapping will be {@link Mount#getIdentifier()} to {@link Channel#getBranchId()}
*/
String HST_SITE_PROVIDER_HTTP_SESSION_KEY = HstSiteProvider.class.getName() + ".key";
HstSite getHstSite(CompositeHstSite compositeHstSite, HstRequestContext requestContext);
}
/*
* Copyright 2017 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hippoecm.hst.cmsrest.services;
import org.hippoecm.hst.core.request.HstRequestContext;
/**
* For every invocation of {@link org.hippoecm.hst.rest.DocumentService#getChannels(String)} and
* {@link org.hippoecm.hst.rest.DocumentService#getUrl(String, String)} this {@link #apply(HstRequestContext, String)}
* will be invoked for every {@link DocumentContextAugmenter} that is added via
* {@link DocumentsResource#addDocumentContextAugmenter(DocumentContextAugmenter)}
*/
@FunctionalInterface
public interface DocumentContextAugmenter {
void apply(HstRequestContext requestContext, String uuid);
}
......@@ -16,7 +16,6 @@
package org.hippoecm.hst.cmsrest.services;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.jcr.Node;
......@@ -42,17 +41,25 @@ public class DocumentsResource extends BaseResource implements DocumentService {
private static final Logger log = LoggerFactory.getLogger(DocumentsResource.class);
private HstLinkCreator hstLinkCreator;
// default no context augmenters
private List<DocumentContextAugmenter> documentContextAugmenters = new ArrayList<>();
public void setHstLinkCreator(HstLinkCreator hstLinkCreator) {
this.hstLinkCreator = hstLinkCreator;
}
public void addDocumentContextAugmenter(final DocumentContextAugmenter documentContextAugmenter) {
documentContextAugmenters.add(documentContextAugmenter);
}
public ChannelDocumentDataset getChannels(String uuid) {
final ChannelDocumentDataset dataset = new ChannelDocumentDataset();
HstRequestContext requestContext = RequestContextProvider.get();
documentContextAugmenters.stream().forEach(dca -> dca.apply(requestContext, uuid));
Node handle = ResourceUtil.getNode(requestContext, uuid);
if (handle == null) {
return dataset;
......@@ -78,6 +85,8 @@ public class DocumentsResource extends BaseResource implements DocumentService {
ChannelDocument document = new ChannelDocument();
document.setChannelId(channel.getId());
document.setChannelName(channel.getName());
document.setBranchId(channel.getBranchId());
document.setBranchOf(channel.getBranchOf());
if (StringUtils.isNotEmpty(link.getPath())) {
document.setPathInfo("/" + link.getPath());
} else {
......@@ -155,7 +164,6 @@ public class DocumentsResource extends BaseResource implements DocumentService {
if (handle == null) {
return null;
}
final String hostGroupNameForCmsHost = getHostGroupNameForCmsHost();
List<HstLink> canonicalLinks = hstLinkCreator.createAllAvailableCanonicals(handle, requestContext, type, hostGroupNameForCmsHost);
......
......@@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
/**
* Utility methods for resource classes.
*/
class ResourceUtil {
public class ResourceUtil {
private static final Logger log = LoggerFactory.getLogger(ResourceUtil.class);
......@@ -46,7 +46,7 @@ class ResourceUtil {
*
* @return the node with the given UUID, or null if no such node could be found.
*/
static Node getNode(final HstRequestContext requestContext, final String uuidParam) {
public static Node getNode(final HstRequestContext requestContext, final String uuidParam) {
if (uuidParam == null) {
log.info("UUID is null, returning null", uuidParam);
return null;
......
......@@ -118,6 +118,10 @@
<property name="channelFilter" ref="channelFilter"/>
</bean>
<bean id="org.hippoecm.hst.rest.DocumentService" class="org.hippoecm.hst.cmsrest.services.DocumentsResource" parent="baseResource">
<property name="hstLinkCreator" ref="org.hippoecm.hst.core.linking.HstLinkCreator"/>
</bean>
<bean id="jaxrsCmsRestCxfServerFactoryBean" class="org.apache.cxf.jaxrs.JAXRSServerFactoryBean">
<property name="address" value="/" />
<property name="providers">
......@@ -130,9 +134,7 @@
<list>
<bean class="org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider">
<constructor-arg>
<bean class="org.hippoecm.hst.cmsrest.services.DocumentsResource" parent="baseResource">
<property name="hstLinkCreator" ref="org.hippoecm.hst.core.linking.HstLinkCreator"/>
</bean>
<ref bean="org.hippoecm.hst.rest.DocumentService"/>
</constructor-arg>
</bean>
<bean class="org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider">
......
/*
* Copyright 2017 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hippoecm.hst.cmsrest.services;
import java.util.UUID;
import org.hippoecm.hst.cmsrest.AbstractCmsRestTest;
import org.hippoecm.hst.rest.DocumentService;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class DocumentContextAugmenterTest extends AbstractCmsRestTest {
private DocumentService documentService;
@Override
public void setUp() throws Exception {
super.setUp();
documentService = getComponentManager().getComponent(DocumentService.class, "org.hippoecm.hst.cmsrest");
((DocumentsResource)documentService).addDocumentContextAugmenter(new ShortCircuitingDocumentContextAugmenter());
}
@Test
public void assert_documentContextAugmenter_is_invoked() throws Exception {
try {
documentService.getChannels(UUID.randomUUID().toString());
fail("Expected the #getChannels to be short-circuited by ShortCircuitingDocumentContextAugmenter");
} catch (IllegalStateException e) {
assertEquals(ShortCircuitingDocumentContextAugmenter.SHORT_CIRCUITING_DOCUMENT_CONTEXT_AUGMENTER_IS_WORKING, e.getMessage());
}
}
}
/*
* Copyright 2017 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hippoecm.hst.cmsrest.services;
import org.hippoecm.hst.core.request.HstRequestContext;
public class ShortCircuitingDocumentContextAugmenter implements DocumentContextAugmenter {
public static final String SHORT_CIRCUITING_DOCUMENT_CONTEXT_AUGMENTER_IS_WORKING = "ShortCircuitingDocumentContextAugmenter is working";
@Override
public void apply(final HstRequestContext requestContext, final String uuid) {
throw new IllegalStateException(SHORT_CIRCUITING_DOCUMENT_CONTEXT_AUGMENTER_IS_WORKING);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2012-2013 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.
See the License for the specific language governing permissions and
limitations under the License.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<import resource="classpath:/org/hippoecm/hst/cmsrest/AbstractCmsRestTest.xml" />
</beans>
......@@ -289,20 +289,4 @@ public class ConfigurationLockedTest extends MountResourceTest {
forbiddenAssertions(e);
}
}
@Test
@Override
public void select_branch_and_select_master_again() throws Exception {
// regardless the channel being locked, the select branch should STILL work although it is a PUT method. It works
// because of the IgnoreLock annotation, also see org.hippoecm.hst.pagecomposer.jaxrs.cxf.HstConfigLockedCheckInvokerPreprocessor
super.select_branch_and_select_master_again();
}
@Test
@Override
public void select_non_existing_branch_does_not_return_error() throws Exception {
// regardless the channel being locked, the select non existing branch should STILL work although it is a PUT method. It works
// because of the IgnoreLock annotation, also see org.hippoecm.hst.pagecomposer.jaxrs.cxf.HstConfigLockedCheckInvokerPreprocessor
super.select_non_existing_branch_does_not_return_error();
}
}
......@@ -23,12 +23,10 @@ import java.io.Serializable;
*/
public class ChannelDocument implements Serializable {
private static final long serialVersionUID = 1L;
private static final int HASH_SEED = 17;
private static final int ODD_PRIME = 37;
private String channelId;
private String channelName;
private String branchId;
private String branchOf;
private String contextPath;
private String pathInfo;
private String mountPath;
......@@ -53,7 +51,9 @@ public class ChannelDocument implements Serializable {
this.cmsPreviewPrefix = original.cmsPreviewPrefix;
this.pathInfo = original.pathInfo;
this.mountPath = original.mountPath;
this.hostName = original.hostName;
this.hostName = original.hostName;
this.branchId = original.branchId;
this.branchOf = original.branchOf;
}
/**
......@@ -88,6 +88,22 @@ public class ChannelDocument implements Serializable {
this.channelName = channelName;
}
public void setBranchId(final String branchId) {
this.branchId = branchId;
}
public String getBranchId() {
return branchId;
}
public String getBranchOf() {
return branchOf;
}
public void setBranchOf(final String branchOf) {
this.branchOf = branchOf;
}
/**
* @return Returns the contextpath of the URL
*/
......@@ -141,74 +157,46 @@ public class ChannelDocument implements Serializable {
public void setHostName(String hostName) {
this.hostName = hostName;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof ChannelDocument) {
ChannelDocument d = (ChannelDocument)o;
if(!equals(channelId, d.channelId)) {
return false;
}
if(!equals(channelName, d.channelName)) {
return false;
}
if(!equals(contextPath, d.contextPath)) {
return false;
}
if(!equals(pathInfo, d.pathInfo)) {
return false;
}
if(!equals(mountPath, d.mountPath)) {
return false;
}
if(!equals(hostName, d.hostName)) {
return false;
}
// all properties are equal, return true
return true;
}
return false;
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final ChannelDocument that = (ChannelDocument) o;
if (channelId != null ? !channelId.equals(that.channelId) : that.channelId != null) return false;
if (channelName != null ? !channelName.equals(that.channelName) : that.channelName != null) return false;
if (branchId != null ? !branchId.equals(that.branchId) : that.branchId != null) return false;
if (branchOf != null ? !branchOf.equals(that.branchOf) : that.branchOf != null) return false;
if (contextPath != null ? !contextPath.equals(that.contextPath) : that.contextPath != null) return false;
if (pathInfo != null ? !pathInfo.equals(that.pathInfo) : that.pathInfo != null) return false;
if (mountPath != null ? !mountPath.equals(that.mountPath) : that.mountPath != null) return false;
if (hostName != null ? !hostName.equals(that.hostName) : that.hostName != null) return false;
return cmsPreviewPrefix != null ? cmsPreviewPrefix.equals(that.cmsPreviewPrefix) : that.cmsPreviewPrefix == null;
}
@Override
public int hashCode() {
int result = HASH_SEED;
if (channelId != null) {
result = ODD_PRIME * result + channelId.hashCode();
}
if (channelName != null) {
result = ODD_PRIME * result + channelName.hashCode();
}
if (contextPath != null) {
result = ODD_PRIME * result + contextPath.hashCode();
}
if (pathInfo != null) {
result = ODD_PRIME * result + pathInfo.hashCode();
}
if (mountPath != null) {
result = ODD_PRIME * result + mountPath.hashCode();
}
if (channelName != null) {
result = ODD_PRIME * result + channelName.hashCode();
}
if (hostName != null) {
result = ODD_PRIME * result + hostName.hashCode();
}
int result = channelId != null ? channelId.hashCode() : 0;
result = 31 * result + (channelName != null ? channelName.hashCode() : 0);
result = 31 * result + (branchId != null ? branchId.hashCode() : 0);
result = 31 * result + (branchOf != null ? branchId.hashCode() : 0);
result = 31 * result + (contextPath != null ? contextPath.hashCode() : 0);
result = 31 * result + (pathInfo != null ? pathInfo.hashCode() : 0);
result = 31 * result + (mountPath != null ? mountPath.hashCode() : 0);
result = 31 * result + (hostName != null ? hostName.hashCode() : 0);
result = 31 * result + (cmsPreviewPrefix != null ? cmsPreviewPrefix.hashCode() : 0);
return result;
}
public static boolean equals(String str1, String str2) {
return str1 == null ? str2 == null : str1.equals(str2);
}
@Override
public String toString() {
return "ChannelDocument [channelId=" + channelId + ", channelName=" + channelName + ", hostName=" + hostName
return "ChannelDocument [channelId=" + channelId + ", channelName=" + channelName +
", branchId= " + branchId + ", branchOf= " + branchOf +
", hostName=" + hostName
+ ", contextPath=" + contextPath + ", cmsPreviewPrefix=" + cmsPreviewPrefix + ", mountPath="
+ mountPath + ", pathInfo=" + pathInfo + "]";
}
}
......@@ -254,7 +254,6 @@ public class ChannelPropertyMapper {
channelNode.getNode(HstNodeTypes.NODENAME_HST_CHANNELINFO).remove();
}
}
// TODO (meggermont): save channel.branches somewhere
}
static Map<HstPropertyDefinition, Object> loadProperties(HstNode channelInfoNode, List<HstPropertyDefinition> propertyDefinitions) {
......
/*
* Copyright 2017 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hippoecm.hst.configuration.site;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.hippoecm.hst.configuration.hosting.Mount;
import org.hippoecm.hst.core.container.ContainerConstants;
import org.hippoecm.hst.core.request.HstRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.hippoecm.hst.core.container.ContainerConstants.CMS_REQUEST_RENDERING_MOUNT_ID;
public class ChannelManagerHstSiteProvider implements HstSiteProvider {
private static final Logger log = LoggerFactory.getLogger(ChannelManagerHstSiteProvider.class);
@Override
public HstSite getHstSite(final CompositeHstSite compositeHstSite, final HstRequestContext requestContext) {
HttpSession session = requestContext.getServletRequest().getSession();
Map<String, String> mountToBranchIdMapping =
(Map<String, String>)session.getAttribute(HST_SITE_PROVIDER_HTTP_SESSION_KEY);
final String renderingMountId = (String)session.getAttribute(CMS_REQUEST_RENDERING_MOUNT_ID);
Mount mount;
if (renderingMountId == null) {
mount = requestContext.getResolvedMount().getMount();
} else {
mount = requestContext.getVirtualHost().getVirtualHosts().getMountByIdentifier(renderingMountId);
}
if (mountToBranchIdMapping == null) {
log.debug("No branch selected for mount '{}'. Return master", mount);
return compositeHstSite.getMaster();
}
final String branchId = mountToBranchIdMapping.get(mount.getIdentifier());
if (branchId == null) {
log.debug("No branch selected for mount '{}'. Return master", mount);
return compositeHstSite.getMaster();
}
HstSite branch = compositeHstSite.getBranches().get(branchId);
if (branch == null) {
log.info("Unexpected branchId '{}' for mount '{}' found on http session because no such branch present. Removing " +
"branch now and return master.", branchId, mount);
mountToBranchIdMapping.remove(branchId);
return compositeHstSite.getMaster();
}
log.info("Using branch '{}' for mount '{}'", branch.getName(), mount);
return branch;
}
}
......@@ -21,9 +21,12 @@ import org.hippoecm.hst.core.request.HstRequestContext;
public class DelegatingHstSiteProvider {
private HstSiteProvider channelManagerHstSiteProvider;
private HstSiteProvider channelManagerHstSiteProvider = (compositeHstSite, requestContext) -> compositeHstSite.getMaster();
private HstSiteProvider websiteHstSiteProvider = (compositeHstSite, requestContext) -> compositeHstSite.getMaster();
/**
* this setter can be used by enterprise / end project modules to inject a custom HstSiteProvider for the channel mngr
*/
public void setChannelManagerHstSiteProvider(final HstSiteProvider channelManagerHstSiteProvider) {
this.channelManagerHstSiteProvider = channelManagerHstSiteProvider;
}
......
......@@ -68,7 +68,7 @@ public class HstSiteFactory {
if (masterConfiguration.getValueProvider().hasProperty(BRANCH_PROPERTY_BRANCH_OF)) {
throw new ModelLoadingException(String.format("Invalid HST configuration for '%s' : It should be a master " +
"branch because directly referenced by an hst:site but '%s' does have the property '%s' which is " +
"only alowed on branches. Correct the configuration.", masterConfigPath, masterConfigPath, BRANCH_PROPERTY_BRANCH_OF));
"only allowed on branches. Correct the configuration.", masterConfigPath, masterConfigPath, BRANCH_PROPERTY_BRANCH_OF));
}
HstNode configurationsNode = masterConfiguration.getParent();
......
......@@ -39,7 +39,6 @@ import org.onehippo.cms7.services.HippoServiceRegistry;
import org.onehippo.cms7.services.cmscontext.CmsContextService;
import org.onehippo.cms7.services.cmscontext.CmsSessionContext;
import static org.hippoecm.hst.configuration.site.HstSiteProvider.HST_SITE_PROVIDER_HTTP_SESSION_KEY;
import static org.hippoecm.hst.core.container.ContainerConstants.CMS_REQUEST_REPO_CREDS_ATTR;
import static org.hippoecm.hst.core.container.ContainerConstants.CMS_REQUEST_USER_ID_ATTR;
......@@ -64,8 +63,6 @@ public class CmsSecurityValve extends AbstractBaseOrderableValve {
private SessionSecurityDelegation sessionSecurityDelegation;
private final String[] CMS_INTERACTION_ATTRIBUTES = new String[]{HST_SITE_PROVIDER_HTTP_SESSION_KEY};
public void setSessionSecurityDelegation(SessionSecurityDelegation sessionSecurityDelegation) {
this.sessionSecurityDelegation = sessionSecurityDelegation;
}
......@@ -127,9 +124,6 @@ public class CmsSecurityValve extends AbstractBaseOrderableValve {
if (httpSession == null) {
httpSession = servletRequest.getSession(true);
}
// since the HST http session could still exist from a previous login, clean up attributes that might have
// been set during earlier cms interaction
cleanupCmsInteractionAttributes(httpSession);
cmsSessionContext = cmsContextService.attachSessionContext(cmsSessionContextId, httpSession);
if (cmsSessionContext == null) {
......@@ -188,12 +182,6 @@ public class CmsSecurityValve extends AbstractBaseOrderableValve {
}
}
private void cleanupCmsInteractionAttributes(final HttpSession httpSession) {
for (String s : CMS_INTERACTION_ATTRIBUTES) {
httpSession.removeAttribute(s);
}
}
private static void sendError(final HttpServletResponse servletResponse, final int errorCode) throws ContainerException {
try {
servletResponse.sendError(errorCode);
......
/*
* Copyright 2012-2016 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2017 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.
......@@ -62,7 +62,7 @@ public class ModuleDescriptorUtils {
try {
log.info("Loading module descriptor from {}", moduleDescriptorURL);
ModuleDefinition moduleDefinition = loadModuleDefinition(moduleDescriptorURL);
moduleDefinitions.add(moduleDefinition);
addActualModuleDefinitions(moduleDefinition, moduleDefinitions);
} catch (Exception e) {
log.warn("Failed to load module descriptor, " + moduleDescriptorURL + ", which will be just ignored.", e);
}
......@@ -71,7 +71,22 @@ public class ModuleDescriptorUtils {
return moduleDefinitions;
}
private static void addActualModuleDefinitions(final ModuleDefinition moduleDefinition, final List<ModuleDefinition> moduleDefinitions) {
if (moduleDefinition.getName() != null) {
// real module
moduleDefinitions.add(moduleDefinition);
return;
}
if (moduleDefinition.getModuleDefinitions() == null) {
return;
}
// only a container <module> : Pick the actual real modules
for (ModuleDefinition child : moduleDefinition.getModuleDefinitions()) {
addActualModuleDefinitions(child, moduleDefinitions);
}
}
private static ModuleDefinition loadModuleDefinition(URL url) throws JAXBException, IOException {
ModuleDefinition moduleDefinition = null;
......
......@@ -111,10 +111,7 @@
<property name="credentials" ref="javax.jcr.Credentials.hstconfigreader.delegating"/>
</bean>
<bean id="org.hippoecm.hst.configuration.site.DelegatingHstSiteProvider" class="org.hippoecm.hst.configuration.site.DelegatingHstSiteProvider">
<property name="channelManagerHstSiteProvider" ref="org.hippoecm.hst.configuration.site.ChannelManagerHstSiteProvider"/>
</bean>
<bean id="org.hippoecm.hst.configuration.site.DelegatingHstSiteProvider" class="org.hippoecm.hst.configuration.site.DelegatingHstSiteProvider"/>
<bean id="org.hippoecm.hst.configuration.site.ChannelManagerHstSiteProvider" class="org.hippoecm.hst.configuration.site.ChannelManagerHstSiteProvider"/>
</beans>
/*
* Copyright 2008-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2008-2017 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.
......@@ -25,6 +25,7 @@ import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class TestModuleDescriptorUtils {
......@@ -81,6 +82,38 @@ public class TestModuleDescriptorUtils {
assertEquals("org.example.analytics", moduleDef.getParent());
}
@Test
public void test_module_envelope_for_actual_modules() throws Exception {
List<ModuleDefinition> moduleDefs =
ModuleDescriptorUtils.collectAllModuleDefinitions(Thread.currentThread().getContextClassLoader(), "META-INF/hst-assembly/addon/module-envelope-for-actual-modules.xml");
assertEquals("Expected 4 modules since 2 <module> elements are only used as envelope", 4, moduleDefs.size());
{
ModuleDefinition moduleDef = findModuleDefinitionByName(moduleDefs, "org.example.noparent.reports");
assertNull(moduleDef.getParent());
assertNull(moduleDef.getModuleDefinitions());
}
{
ModuleDefinition moduleDef = findModuleDefinitionByName(moduleDefs, "org.example.analytics1.reports");
assertEquals("org.example.analytics1", moduleDef.getParent());
assertNull(moduleDef.getModuleDefinitions());
}
{
ModuleDefinition moduleDef = findModuleDefinitionByName(moduleDefs, "org.example.analytics2.statistics");
assertEquals("org.example.analytics2", moduleDef.getParent());
assertNull(moduleDef.getModuleDefinitions());