org.opencms.ade.containerpage.inherited.TestInheritedContainer Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* File : $Source$
* Date : $Date$
* Version: $Revision$
*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (C) 2002 - 2011 Alkacon Software (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.ade.containerpage.inherited;
import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_HIDDEN;
import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_ORDERKEY;
import static org.opencms.ade.containerpage.inherited.CmsContainerConfiguration.N_VISIBLE;
import org.opencms.ade.containerpage.shared.CmsInheritanceInfo;
import org.opencms.db.CmsResourceState;
import org.opencms.file.CmsFile;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsResource;
import org.opencms.main.CmsException;
import org.opencms.main.I_CmsEventListener;
import org.opencms.main.OpenCms;
import org.opencms.publish.CmsPublishManager;
import org.opencms.test.I_CmsLogHandler;
import org.opencms.test.OpenCmsTestCase;
import org.opencms.test.OpenCmsTestLogAppender;
import org.opencms.test.OpenCmsTestProperties;
import org.opencms.util.CmsCollectionsGenericWrapper;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import org.opencms.xml.containerpage.CmsContainerElementBean;
import org.opencms.xml.content.CmsXmlContent;
import org.opencms.xml.content.CmsXmlContentProperty;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Level;
import org.apache.log4j.spi.LoggingEvent;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import junit.framework.Test;
/**
* Test case for inherited containers.
*
*
*/
public class TestInheritedContainer extends OpenCmsTestCase {
/**
* A special log handler which intercepts log messages from the inherited container configuration
* cache to count how often new configuration files are loaded into the cache.
*/
public static class CacheLoadLogHandler implements I_CmsLogHandler {
/** The number of offline loads. */
private int m_offlineLoads;
/** The number of offline readResource calls. */
private int m_offlineReadResource;
/** The number of online loads. */
private int m_onlineLoads;
/** The number of online readResource calls. */
private int m_onlineReadResource;
/**
* Resets the offline/online load counters to 0.
*/
public void clear() {
m_offlineLoads = 0;
m_onlineLoads = 0;
m_offlineReadResource = 0;
m_onlineReadResource = 0;
}
/**
* Gets the number of offline loads since the last call to clear().
*
* @return the number of offline loads
*/
public int getOfflineLoads() {
return m_offlineLoads;
}
/**
* Gets the number of single readResource calls for offline mode.
*
* @return the number of readResource calls
*/
public int getOfflineReadResource() {
return m_offlineReadResource;
}
/**
* Gets the number of online loads since the last call to clear().
*
* @return the number of online loads
*/
public int getOnlineLoads() {
return m_onlineLoads;
}
/**
* Gets the number of online readResource calls.
*
* @return the number of online readResource calls
*/
public int getOnlineReadResource() {
return m_onlineReadResource;
}
/**
* @see org.opencms.test.I_CmsLogHandler#handleLogEvent(org.apache.log4j.spi.LoggingEvent)
*/
public void handleLogEvent(LoggingEvent event) {
String message = event.getMessage().toString();
if (event.getLevel().equals(Level.TRACE)) {
if (message.startsWith("inherited-container-cache offline load")) {
m_offlineLoads += 1;
}
if (message.startsWith("inherited-container-cache online load")) {
m_onlineLoads += 1;
}
if (message.startsWith("inherited-container-cache offline readSingleResource")) {
m_offlineReadResource += 1;
}
if (message.startsWith("inherited-container-cache online readSingleResource")) {
m_onlineReadResource += 1;
}
}
}
}
/** Constant which represents the offline project. */
public static final boolean OFFLINE = false;
/** Constant which represents the online project. */
public static final boolean ONLINE = true;
/**
* The test case constructor.
*
* @param name the name of the test case
*/
public TestInheritedContainer(String name) {
super(name);
}
/**
* Returns the test suite.
*
*
* @return the test suite
*/
public static Test suite() {
OpenCmsTestProperties.initialize(org.opencms.test.AllTests.TEST_PROPERTIES_PATH);
return generateSetupTestWrapper(TestInheritedContainer.class, "inheritcontainer", "/");
}
/**
* Tests that new elements in parent configurations which are not explicitly referenced by
* a child configuration's ordering are inserted at the end of the element list.
*
* @throws Exception
*/
public void testAppendNew() throws Exception {
CmsInheritedContainerState result = new CmsInheritedContainerState();
result.addConfiguration(buildConfiguration("a b c|||a b c"));
result.addConfiguration(buildConfiguration("d e|||d e"));
result.addConfiguration(buildConfiguration("a c|||"));
List elementBeans = result.getElements(true);
checkConfiguration(
elementBeans,
"key=a new=false visible=true",
"key=c new=false visible=true",
"key=b new=false visible=true",
"key=d new=false visible=true",
"key=e new=false visible=true");
result = new CmsInheritedContainerState();
result.addConfiguration(buildConfiguration("a b c d f e|||f e c d b a"));
result.addConfiguration(buildConfiguration("g|||g"));
result.addConfiguration(buildConfiguration("|||"));
elementBeans = result.getElements(true);
checkConfiguration(
elementBeans,
"key=g new=false",
"key=a new=false",
"key=b new=false",
"key=c new=false",
"key=d new=false",
"key=f new=false",
"key=e new=false");
result = new CmsInheritedContainerState();
result.addConfiguration(buildConfiguration("a b|||b a"));
result.addConfiguration(buildConfiguration("d c|||c d"));
result.addConfiguration(buildConfiguration("e f|||e f"));
elementBeans = result.getElements(true);
checkConfiguration(
elementBeans,
"key=e new=true",
"key=f new=true",
"key=a new=false",
"key=b new=false",
"key=d new=false",
"key=c new=false");
}
/**
* Tests the correctness of the offline cache results.
*
* @throws Exception
*/
public void testCacheCorrectnessOffline() throws Exception {
OpenCms.getEventManager().fireEvent(I_CmsEventListener.EVENT_CLEAR_CACHES);
try {
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
String level3 = "/system/level1/level2/level3";
// a, b, c
checkConfigurationForPath(level3, "alpha", false, "key=c", "key=a", "key=b");
writeConfiguration(2, "d");
// a, d, c
checkConfigurationForPath(level3, "alpha", false, "key=c", "key=a", "key=d");
writeConfiguration(1, "b");
// b, d, c
checkConfigurationForPath(level3, "alpha", false, "key=c", "key=b", "key=d");
writeConfiguration(3, "a");
// b, d, a
checkConfigurationForPath(level3, "alpha", false, "key=a", "key=b", "key=d");
deleteConfiguration(2);
//b, -, a
checkConfigurationForPath(level3, "alpha", false, "key=a", "key=b");
} finally {
publish();
}
}
/**
* Tests the correctness of the online cache results.
*
* @throws Exception
*/
public void testCacheCorrectnessOnline() throws Exception {
OpenCms.getEventManager().fireEvent(I_CmsEventListener.EVENT_CLEAR_CACHES);
try {
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
publish();
String level3 = "/system/level1/level2/level3";
// OFFLINE: a, b, c ONLINE: a, b, c
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=c", "key=a", "key=b");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=b");
writeConfiguration(2, "d");
// OFFLINE: a, d, c ONLINE: a, b, c
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=c", "key=a", "key=d");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=b");
publish();
// OFFLINE: a, d, c ONLINE: a, d, c
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=c", "key=a", "key=d");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=d");
writeConfiguration(1, "b");
// OFFLINE: b, d, c ONLINE: a, d, c
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=c", "key=b", "key=d");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=d");
publish();
// OFFLINE: b, d, c ONLINE: b,d,c
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=c", "key=b", "key=d");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=b", "key=d");
writeConfiguration(3, "a");
// OFFLINE: b, d, a ONLINE: b,d,c
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=a", "key=b", "key=d");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=b", "key=d");
publish();
// OFFLINE: b, d, a ONLINE: b,d,a
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=a", "key=b", "key=d");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=a", "key=b", "key=d");
deleteConfiguration(2);
// OFFLINE: b, -, a ONLINE: b,d,a
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=a", "key=b");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=a", "key=b", "key=d");
publish();
checkConfigurationForPath(level3, "alpha", ONLINE, "key=a", "key=b");
} finally {
publish();
}
}
/**
* Tests whether the cache only loads configuration files when necessary.
*
* @throws Exception
*/
public void testCacheLoadCounts() throws Exception {
try {
OpenCms.getEventManager().fireEvent(I_CmsEventListener.EVENT_CLEAR_CACHES);
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
publish();
String level3 = "/system/level1/level2/level3";
// OFFLINE: a, b, c ONLINE: a, b, c
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=c", "key=a", "key=b");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=b");
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=c", "key=a", "key=b");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=b");
writeConfiguration(2, "d");
// OFFLINE: a, d, c ONLINE: a, b, c
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=c", "key=a", "key=d");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=b");
publish();
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=d");
// OFFLINE: a, d, c ONLINE: a, d, c
deleteConfiguration(3);
writeConfiguration(1, "b");
// OFFLINE: b, d, - ONLINE: a,d,c
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=d");
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=d", "key=b");
checkConfigurationForPath(level3, "alpha", ONLINE, "key=c", "key=a", "key=d");
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=d", "key=b");
publish();
// OFFLINE: b, d, - ONLINE: b, d, -
checkConfigurationForPath(level3, "alpha", ONLINE, "key=d", "key=b");
checkConfigurationForPath(level3, "alpha", OFFLINE, "key=d", "key=b");
} finally {
publish();
OpenCmsTestLogAppender.setHandler(null);
}
}
/**
* Tests rearrangement of inherited elements.
*
*
* @throws Exception
*/
public void testChangeOrder() throws Exception {
CmsInheritedContainerState result = new CmsInheritedContainerState();
result.addConfiguration(buildConfiguration("a b c|||a b c"));
result.addConfiguration(buildConfiguration("b c a|||"));
List elementBeans = result.getElements(true);
checkConfiguration(
elementBeans,
"key=b new=false visible=true",
"key=c new=false visible=true",
"key=a new=false visible=true");
}
/**
* Tests whether the inherited container cache is cleared correctly.
*
* @throws Exception
*/
public void testClearCaches() throws Exception {
try {
OpenCms.getEventManager().fireEvent(I_CmsEventListener.EVENT_CLEAR_CACHES);
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
publish();
checkConfigurationForPath("/system/level1/level2/level3", "alpha", OFFLINE, "key=c", "key=a", "key=b");
checkConfigurationForPath("/system/level1/level2/level3", "alpha", ONLINE, "key=c", "key=a", "key=b");
OpenCms.getEventManager().fireEvent(I_CmsEventListener.EVENT_CLEAR_CACHES);
checkConfigurationForPath("/system/level1/level2/level3", "alpha", OFFLINE, "key=c", "key=a", "key=b");
checkConfigurationForPath("/system/level1/level2/level3", "alpha", ONLINE, "key=c", "key=a", "key=b");
} finally {
OpenCmsTestLogAppender.setHandler(null);
}
}
/**
* Test for hiding of inherited elements.
*
*
* @throws Exception
*/
public void testHideElements() throws Exception {
CmsInheritedContainerState result = new CmsInheritedContainerState();
result.addConfiguration(buildConfiguration("a b c d|||a b c d"));
result.addConfiguration(buildConfiguration("||b d|"));
List elementBeans = result.getElements(true);
checkConfiguration(
elementBeans,
"key=a visible=true",
"key=c visible=true",
"key=b visible=false",
"key=d visible=false");
elementBeans = result.getElements(false);
checkConfiguration(elementBeans, "key=a visible=true", "key=c visible=true");
}
/**
* Tests that the 'new' states of inherited container elements are correct.
*
* @throws Exception
*/
public void testNewElements() throws Exception {
CmsInheritedContainerState result = new CmsInheritedContainerState();
result.addConfiguration(buildConfiguration("a b|||a b"));
checkConfiguration(result.getElements(true), "key=a new=true", "key=b new=true");
result.addConfiguration(buildConfiguration("c b a d|||c d"));
checkConfiguration(
result.getElements(true),
"key=c new=true",
"key=b new=false",
"key=a new=false",
"key=d new=true");
}
/**
* Tests that the configuration cache works if there are no configuration files, or there are configuration files which don't
* contain a configuration for a given name.
*
* @throws Exception
*/
public void testNoConfigurations() throws Exception {
try {
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
OpenCms.getADEManager().flushInheritanceGroupChanges();
checkConfigurationForPath("/system/level1/level2/level3", "beta", OFFLINE);
checkConfigurationForPath("/system/level1/level2/level3", "beta", ONLINE);
deleteConfiguration(1);
deleteConfiguration(2);
deleteConfiguration(3);
OpenCms.getADEManager().flushInheritanceGroupChanges();
checkConfigurationForPath("/system/level1/level2/level3", "alpha", OFFLINE);
publish();
OpenCms.getADEManager().flushInheritanceGroupChanges();
checkConfigurationForPath("/system/level1/level2/level3", "alpha", ONLINE);
} finally {
publish();
}
}
/**
* Tests that only correctly named inherited container configuration files are evaluated.
*
* @throws Exception
*/
public void testOnlyReadProperlyNamedFiles() throws Exception {
try {
OpenCms.getEventManager().fireEvent(I_CmsEventListener.EVENT_CLEAR_CACHES);
OpenCmsTestLogAppender.setBreakOnError(false);
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
writeConfiguration("/system/dummy.config", "d");
publish();
checkConfigurationForPath("/system/level1/level2/level3", "alpha", OFFLINE, "key=c", "key=a", "key=b");
deleteConfiguration(2);
writeConfiguration("/system/level1/level2/baz.config", "b");
checkConfigurationForPath("/system/level1/level2/level3", "alpha", OFFLINE, "key=c", "key=a");
} finally {
OpenCmsTestLogAppender.setBreakOnError(false);
OpenCmsTestLogAppender.setHandler(null);
deleteConfiguration("/system/dummy.config");
deleteConfiguration("/system/level1/level2/baz.config");
publish();
}
}
/**
* Tests parsing of container configuration files.
*
* @throws Exception
*/
public void testParseContainerConfiguration() throws Exception {
String xmlText = "\r\n"
+ "\r\n"
+ "\r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " 00000001-0000-0000-0000-000000000000 \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " 00000001-0000-0000-0000-000000000000 \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n";
byte[] xmlData = xmlText.getBytes("UTF-8");
CmsFile file = new CmsFile(
new CmsUUID()/* structureid */,
new CmsUUID()/* resourceid */,
"/test"/* rootpath */,
303/* typeid */,
0/* flags */,
new CmsUUID()/* projectlastmodified */,
CmsResourceState.STATE_NEW/* state */,
0/* datecreated */,
new CmsUUID()/* usercreated */,
0/* datemodified */,
new CmsUUID()/* usermodified */,
0/* datereleased */,
0/* dateexpired */,
0/* siblingcount */,
xmlData.length/* length */,
0/* datacontent */,
0/* version */,
xmlData/* content */);
CmsContainerConfigurationParser parser = new CmsContainerConfigurationParser(getCmsObject());
parser.parse(file);
Map> results = parser.getParsedResults();
Map configurationGroup = results.get(new Locale("en"));
assertNotNull(configurationGroup);
CmsContainerConfiguration config = configurationGroup.get("blubb");
assertNotNull(config);
Map newElements = config.getNewElements();
assertNotNull(newElements);
CmsContainerElementBean elementBean = newElements.get("this/is/another/key");
assertEquals(new CmsUUID("00000001-0000-0000-0000-000000000000"), elementBean.getId());
Map settings = elementBean.getIndividualSettings();
assertNotNull(settings);
assertEquals("testvalue", settings.get("testsetting"));
assertEquals("00000001-0000-0000-0000-000000000000", settings.get("testsetting2"));
}
/**
* Test case for saving the configuration.
*
* @throws Exception
*/
public void testReadAndSaveBack() throws Exception {
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
publish();
CmsObject cms = getCmsObject();
CmsInheritedContainerState state = OpenCms.getADEManager().getInheritedContainerState(
cms,
"/system/level1/level2",
"alpha");
List elements = state.getElements(true);
CmsContainerConfigurationWriter configWriter = new CmsContainerConfigurationWriter();
configWriter.save(cms, "alpha", true, cms.readResource("/system/level1/level2"), elements);
checkConfigurationForPath("/system/level1/level2/level3", "alpha", OFFLINE, "key=c", "key=a", "key=b");
}
/**
* Tests looking up inheritance groups by element resource.
*
* @throws Exception
*/
public void testReverseLookup() throws Exception {
publish();
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
publish();
CmsObject cms = getCmsObject();
Set expected = new HashSet();
expected.add("alpha");
CmsResource inheritanceConfig = cms.readResource("/system/level1/level2/.inherited");
CmsResource target = cms.readResource("/system/content/b.txt");
Set result = CmsInheritanceGroupUtils.getNamesOfGroupsContainingResource(
cms,
inheritanceConfig,
target);
assertEquals(expected, result);
target = cms.readResource("/system/content/");
result = CmsInheritanceGroupUtils.getNamesOfGroupsContainingResource(cms, inheritanceConfig, target);
assertEquals(Collections.emptySet(), result);
}
/**
* Tests saving an inherited container element list with a new element added.
* @throws Exception
*/
public void testSaveChangeVisibility() throws Exception {
try {
CmsContainerConfiguration config = buildConfiguration("a b c|||a b c");
saveConfiguration(
"/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME,
config,
"alpha");
CmsObject cms = getCmsObject();
CmsResource x2 = cms.readResource("/system/x1/x2");
List elements = OpenCms.getADEManager().getInheritedContainerState(
cms,
x2,
"alpha").getElements(true);
elements.get(1).getInheritanceInfo().setVisible(false);
elements.get(2).getInheritanceInfo().setVisible(false);
OpenCms.getADEManager().saveInheritedContainer(cms, "/system/x1/x2", "alpha", false, elements);
checkConfigurationForPath(
"/system/x1/x2",
"alpha",
OFFLINE,
"key=a new=false visible=true",
"key=b new=false visible=false",
"key=c new=false visible=false");
} finally {
deleteConfiguration("/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
deleteConfiguration("/system/x1/x2/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
publish();
}
}
/**
* Tests saving an inherited container element list with a new element added.
* @throws Exception
*/
public void testSaveNewElements() throws Exception {
try {
CmsContainerConfiguration config = buildConfiguration("a b c|||a b c");
saveConfiguration(
"/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME,
config,
"alpha");
CmsObject cms = getCmsObject();
CmsResource x2 = cms.readResource("/system/x1/x2");
List elements = OpenCms.getADEManager().getInheritedContainerState(
cms,
x2,
"alpha").getElements(true);
CmsContainerElementBean newElement = generateDummyElement("d");
CmsInheritanceInfo info = new CmsInheritanceInfo("d", true, true);
newElement.setInheritanceInfo(info);
elements.add(newElement);
OpenCms.getADEManager().saveInheritedContainer(cms, "/system/x1/x2", "alpha", true, elements);
checkConfigurationForPath(
"/system/x1/x2",
"alpha",
OFFLINE,
"key=a new=false",
"key=b new=false",
"key=c new=false",
"key=d new=true");
} finally {
deleteConfiguration("/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
deleteConfiguration("/system/x1/x2/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
publish();
}
}
public void testSaveRemoveDanglingKeys() throws Exception {
try {
CmsContainerConfiguration config = buildConfiguration("a b c|||a b c");
saveConfiguration(
"/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME,
config,
"alpha");
CmsObject cms = getCmsObject();
CmsResource x2 = cms.readResource("/system/x1/x2");
List elements = OpenCms.getADEManager().getInheritedContainerState(
cms,
x2,
"alpha").getElements(true);
config = buildConfiguration("a b|||a b");
saveConfiguration(
"/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME,
config,
"alpha");
CmsContainerElementBean elementBean = elements.get(0);
elements.remove(0);
elements.add(elementBean);
OpenCms.getADEManager().saveInheritedContainer(cms, "/system/x1/x2", "alpha", true, elements);
checkConfigurationForPath(
"/system/x1/x2",
"alpha",
OFFLINE,
"key=b new=false visible=true",
"key=a new=false visible=true");
CmsResource configResource = cms.readResource(
"/system/x1/x2/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
CmsFile file = cms.readFile(configResource);
String content = new String(file.getContents());
assertTrue(content.contains(""));
// should have been removed when saving
assertFalse(content.contains(""));
} finally {
deleteConfiguration("/system/x1/x2/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
deleteConfiguration("/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
publish();
}
}
/**
* Tests saving a reordered list of inherited container elements.
*
* @throws Exception
*/
public void testSaveReorder() throws Exception {
try {
CmsContainerConfiguration config = buildConfiguration("a b c|||a b c");
saveConfiguration(
"/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME,
config,
"alpha");
CmsObject cms = getCmsObject();
CmsResource x2 = cms.readResource("/system/x1/x2");
List elements = OpenCms.getADEManager().getInheritedContainerState(
cms,
x2,
"alpha").getElements(true);
CmsContainerElementBean firstElement = elements.get(0);
elements.remove(0);
elements.add(firstElement);
OpenCms.getADEManager().saveInheritedContainer(cms, "/system/x1/x2", "alpha", true, elements);
checkConfigurationForPath(
"/system/x1/x2",
"alpha",
OFFLINE,
"key=b new=false",
"key=c new=false",
"key=a new=false");
} finally {
deleteConfiguration("/system/x1/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
deleteConfiguration("/system/x1/x2/" + CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
publish();
}
}
/**
* Tests serialization of a single configuration node.
*
* @throws Exception
*/
public void testSerialization1() throws Exception {
Document document = createDocument(" ");
CmsContainerConfiguration config = buildConfiguration("a b c|d|e f|a b c");
CmsXmlContentProperty setting1def = new CmsXmlContentProperty(
"setting_a",
"string",
null,
null,
null,
null,
null,
null,
null,
null,
null);
final Map settingDefs = new HashMap();
settingDefs.put("setting_a", setting1def);
CmsContainerConfigurationWriter writer = new CmsContainerConfigurationWriter() {
@Override
protected java.util.Map getSettingConfiguration(
CmsObject cms,
CmsResource resource) {
return settingDefs;
}
};
Element element = writer.serializeSingleConfiguration(
getCmsObject(),
"configname",
config,
document.getRootElement());
assertNotNull(element);
assertEquals("Configuration", element.getName());
List nodes = CmsCollectionsGenericWrapper.list(element.selectNodes(N_ORDERKEY));
assertEquals(3, nodes.size());
Element element0 = (Element)nodes.get(0);
checkCDATA(element0, "a");
checkCDATA((Element)nodes.get(1), "b");
checkCDATA((Element)nodes.get(2), "c");
List visibleNodes = CmsCollectionsGenericWrapper.list(element.selectNodes(N_VISIBLE));
assertEquals(1, visibleNodes.size());
checkCDATA((Element)visibleNodes.get(0), "d");
List invisibleNodes = CmsCollectionsGenericWrapper.list(element.selectNodes(N_HIDDEN));
assertEquals(2, invisibleNodes.size());
Set actualInvisible = new HashSet();
Set expectedInvisible = new HashSet();
expectedInvisible.add("e");
expectedInvisible.add("f");
for (Node node : invisibleNodes) {
actualInvisible.add(getNestedText((Element)node));
}
assertEquals(expectedInvisible, actualInvisible);
Node targetIdNode = element.selectSingleNode("NewElement[Key='a']/Element/Uri/link/uuid");
String uuidString = getNestedText((Element)targetIdNode);
assertEquals(makeStructureId("a"), new CmsUUID(uuidString));
Node targetIdNode2 = element.selectSingleNode("NewElement[Key='b']/Element/Uri/link/uuid");
String uuidString2 = getNestedText((Element)targetIdNode2);
assertEquals(makeStructureId("b"), new CmsUUID(uuidString2));
Node targetIdNode3 = element.selectSingleNode("NewElement[Key='c']/Element/Uri/link/uuid");
String uuidString3 = getNestedText((Element)targetIdNode3);
assertEquals(makeStructureId("c"), new CmsUUID(uuidString3));
assertEquals(3, element.selectNodes("NewElement").size());
assertEquals(
"value_a",
getNestedText((Element)element.selectSingleNode(
"NewElement[Key='a']/Element/Properties[Name='setting_a']/Value/String")));
}
/**
* Tests whether a configuration file which has been first updated and then deleted is removed correctly from the cache.
*
* @throws Exception
*/
public void testUpdateAndRemove() throws Exception {
try {
OpenCmsTestLogAppender.setBreakOnError(false);
publish();
writeConfiguration(1, "a");
writeConfiguration(2, "b");
writeConfiguration(3, "c");
publish();
checkConfigurationForPath("/system/level1/level2/level3", "alpha", OFFLINE, "key=c", "key=a", "key=b");
writeConfiguration(2, "d");
deleteConfiguration(2);
checkConfigurationForPath("/system/level1/level2/level3", "alpha", OFFLINE, "key=c", "key=a");
} finally {
publish();
OpenCmsTestLogAppender.setBreakOnError(false);
OpenCmsTestLogAppender.setHandler(null);
}
}
/**
* Helper method to create a dummy configuration from a specification string.
*
* The specification string consists of 4 fields separated by the pipe symbol, which correspond to different
* parts of the configuration bean. The first field describes the ordering keys of the container configuration;
* the second field describes the keys which have been made visible by the configuration; the third field describes
* which keys have been hidden by the configuration, and the last field describes which new elements are contained in
* the configuration.
*
* @param spec
* @return the test configuration
*/
protected CmsContainerConfiguration buildConfiguration(String spec) {
Map visibility = new HashMap();
Map newElements = new HashMap();
List ordering = new ArrayList();
String[] tokens = spec.split("\\|", 4);
String orderingStr = tokens[0];
String visibleStr = tokens[1];
String hiddenStr = tokens[2];
String newElemStr = tokens[3];
if (orderingStr.length() == 0) {
ordering = null;
} else {
ordering = CmsStringUtil.splitAsList(orderingStr, " ");
}
for (String visible : visibleStr.split("\\s+")) {
if (CmsStringUtil.isEmptyOrWhitespaceOnly(visible)) {
continue;
}
visibility.put(visible, Boolean.TRUE);
}
for (String hidden : hiddenStr.split("\\s+")) {
if (CmsStringUtil.isEmptyOrWhitespaceOnly(hidden)) {
continue;
}
visibility.put(hidden, Boolean.FALSE);
}
for (String newElem : newElemStr.split("\\s+")) {
if (CmsStringUtil.isEmptyOrWhitespaceOnly(newElem)) {
continue;
}
newElements.put(newElem, generateDummyElement(newElem));
}
return new CmsContainerConfiguration(ordering, visibility, newElements);
}
/**
* Checks whether a given element contains a nested CDATA node with a given text.
*
* @param element the parent element
* @param expectedValue the text which should be contained in the CDATA node
*/
protected void checkCDATA(Element element, String expectedValue) {
Node childNode = element.node(0);
assertEquals("cdata", childNode.getNodeTypeName().toLowerCase());
assertEquals(expectedValue, childNode.getText());
}
/**
* Checks whether a container element bean with inheritance information fulfills a given specification string.
*
* The string has the form 'key1=value1 key2=value2....'.
*
* Each key-value pair corresponds to a check to perform on the given container element bean:
* The key 'key' performs a test whether the key of the inheritance info has a given value.
* The key 'new' performs a test whether the element bean was inherited from a parent configuration or is new.
* The key 'visible' performs a test whether the element bean is marked as visible
* @param element
* @param spec
*/
protected void checkConfiguration(CmsContainerElementBean element, String spec) {
Map specMap = CmsStringUtil.splitAsMap(spec, " ", "=");
for (Map.Entry entry : specMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if ("visible".equals(key)) {
boolean expectVisible = Boolean.parseBoolean(value);
assertEquals(expectVisible, element.getInheritanceInfo().isVisible());
} else if ("key".equals(key)) {
String expectedKey = value;
assertEquals(expectedKey, element.getInheritanceInfo().getKey());
} else if ("new".equals(key)) {
boolean expectNew = Boolean.parseBoolean(value);
assertEquals(expectNew, element.getInheritanceInfo().isNew());
} else {
throw new IllegalArgumentException("Invalid specification string: " + spec);
}
}
}
/**
* Checks whether the container element beans contained in a list satisfy a list of constraints.
*
* @param elements the elements for which the checks should be performed
*
* @param specs the constraints for the element beans, in the same order as the container element beans
*/
protected void checkConfiguration(List elements, String... specs) {
assertTrue(
"Number of elements does not match the number of specification strings!",
specs.length == elements.size());
for (int i = 0; i < elements.size(); i++) {
CmsContainerElementBean elementBean = elements.get(i);
String spec = specs[i];
checkConfiguration(elementBean, spec);
}
}
/**
* Checks whether the inherited container configuration given by the ADE manager for a specific
* root path satisfies a list of constraints.
*
* @param rootPath the root path for which the inherited container configuration should be tested
* @param name the name of the configuration to test
* @param online if true, checks in the online project, else in the offline project
* @param specs the list of constraints
*
* @throws CmsException if something goes wrong
*/
protected void checkConfigurationForPath(String rootPath, String name, boolean online, String... specs)
throws CmsException {
CmsObject cms = getCmsObject();
if (online) {
cms = OpenCms.initCmsObject(cms);
cms.getRequestContext().setCurrentProject(cms.readProject(CmsProject.ONLINE_PROJECT_ID));
}
CmsInheritedContainerState state = OpenCms.getADEManager().getInheritedContainerState(cms, rootPath, name);
List elementBeans = state.getElements(true);
checkConfiguration(elementBeans, specs);
}
/**
* Creates a document given a root element as a string.
*
* @param rootElement the root element string
* @return the created document
*
* @throws Exception
*/
protected Document createDocument(String rootElement) throws Exception {
SAXReader reader = new SAXReader();
return reader.read(new StringReader(rootElement));
}
/**
* Deletes a configuration at the given level of the /level1/level2/level3 tree branch.
*
* @param level the level id (1-3)
*
* @throws CmsException if something goes wrong
*/
protected void deleteConfiguration(int level) throws CmsException {
String dirPath = getLevelPath(level);
String configPath = CmsStringUtil.joinPaths(
dirPath,
CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
deleteConfiguration(configPath);
OpenCms.getADEManager().flushInheritanceGroupChanges();
}
/**
* Deletes the configuration for a given path.
*
* @param path the path of the configuration
* @throws CmsException if something goes wrong
*/
protected void deleteConfiguration(String path) throws CmsException {
CmsObject cms = getCmsObject();
if (cms.existsResource(path)) {
lock(path);
cms.deleteResource(path, CmsResource.DELETE_PRESERVE_SIBLINGS);
}
}
/**
* Helper method for generating a dummy container element.
*
*
* @param key
* the key to use
* @return the dummy container element
*/
protected CmsContainerElementBean generateDummyElement(String key) {
Map settings = new HashMap();
settings.put("setting_" + key, "value_" + key);
CmsUUID id = CmsUUID.getConstantUUID(key);
if (key.equals("a")) {
id = new CmsUUID("00000002-0000-0000-0000-000000000000");
} else if (key.equals("b")) {
id = new CmsUUID("00000003-0000-0000-0000-000000000000");
} else if (key.equals("c")) {
id = new CmsUUID("00000004-0000-0000-0000-000000000000");
} else if (key.equals("d")) {
id = new CmsUUID("00000005-0000-0000-0000-000000000000");
}
CmsContainerElementBean elementBean = new CmsContainerElementBean(id, CmsUUID.getNullUUID(), settings, false);
return elementBean;
}
/**
* Helper method for generating a test configuration which contains a single configured container elements.
*
* @param newName the key of the container element which should be put in the container element
* @return the contents of the generated container element
*
* @throws CmsException if something goes wrong
* @throws UnsupportedEncodingException
*/
protected byte[] generateTestConfig(String newName) throws CmsException, UnsupportedEncodingException {
CmsResource resource = getCmsObject().readResource("/system/content/" + newName + ".txt");
CmsUUID structureId = resource.getStructureId();
String rootPath = resource.getRootPath();
String xmlText = "\r\n"
+ "\r\n"
+ "\r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " "
+ structureId.toString()
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n"
+ " \r\n";
byte[] xmlData = xmlText.getBytes("UTF-8");
return xmlData;
}
/**
* Helper method for getting a path for the given level in the level1/level2/level3 tree branch.
*
* @param level the level index (1-3)
*
* @return the level path
*/
protected String getLevelPath(int level) {
switch (level) {
case 1:
return "/system/level1";
case 2:
return "/system/level1/level2";
case 3:
return "/system/level1/level2/level3";
default:
throw new IllegalArgumentException("Invalid level id!");
}
}
/**
* Gets the nested text of an element.
*
* @param element the element from which the text should be extracted
*
* @return the text nested inside the element
*/
protected String getNestedText(Element element) {
return element.node(0).getText();
}
/**
* Helper method to lock a resource.
*
* @param path the resource path
*/
protected void lock(String path) {
try {
getCmsObject().lockResource(path);
} catch (CmsException e) {
// no other users, this means we already have the lock
}
}
/**
* Helper method to create dummy structure ids from a name.
*
* @param name the name
* @return the dummy structure id
*/
protected CmsUUID makeStructureId(String name) {
CmsUUID id = CmsUUID.getConstantUUID(name);
if (name.equals("a")) {
id = new CmsUUID("00000002-0000-0000-0000-000000000000");
} else if (name.equals("b")) {
id = new CmsUUID("00000003-0000-0000-0000-000000000000");
} else if (name.equals("c")) {
id = new CmsUUID("00000004-0000-0000-0000-000000000000");
} else if (name.equals("d")) {
id = new CmsUUID("00000005-0000-0000-0000-000000000000");
}
return id;
}
/**
* Helper method which publishes the offline project.
*
* @throws Exception
*/
protected void publish() throws Exception {
CmsObject cms = getCmsObject();
CmsPublishManager publishManager = OpenCms.getPublishManager();
publishManager.publishProject(cms);
publishManager.waitWhileRunning();
OpenCms.getADEManager().flushInheritanceGroupChanges();
}
/**
* Helper method for reading the contents of the path into a file.
*
* @param path the path of the resource which should be read
* @return the content of the resource
*
* @throws Exception if something goes wrong
*/
protected String read(String path) throws Exception {
CmsObject cms = getCmsObject();
CmsResource resource = cms.readResource(path);
CmsFile file = cms.readFile(resource);
return new String(file.getContents(), "UTF-8");
}
/**
* Saves a configuration object to a file.
*
* @param path the path of the configuration file
* @param config the container configuration
* @param name the name under which the configuration object should be saved
*
* @throws Exception if something goes wrong
*/
protected void saveConfiguration(String path, CmsContainerConfiguration config, String name) throws Exception {
CmsContainerConfigurationWriter writer = new CmsContainerConfigurationWriter();
CmsXmlContent content = writer.saveInContentObject(getCmsObject(), null, Locale.ENGLISH, name, config);
byte[] data = content.marshal();
writeConfiguration(path, data);
OpenCms.getADEManager().flushInheritanceGroupChanges();
}
/**
* Writes a dummy configuration file at a given level in the level1/level2/level3 tree branch.
*
* @param level the level at which to write the configuration file
* @param name the name for the element defined in the configuration file
*
* @throws CmsException if something goes wrong
* @throws UnsupportedEncodingException
*/
protected void writeConfiguration(int level, String name) throws CmsException, UnsupportedEncodingException {
OpenCms.getADEManager();
String dirPath = getLevelPath(level);
String configPath = CmsStringUtil.joinPaths(
dirPath,
CmsContainerConfigurationCache.INHERITANCE_CONFIG_FILE_NAME);
writeConfiguration(configPath, name);
OpenCms.getADEManager().flushInheritanceGroupChanges();
}
/**
* Writes a dummy configuration file to a given path.
*
* @param path the path where the configuration file should be written
* @param data the configuration data to write
*
* @throws CmsException if something goes wrong
*/
protected void writeConfiguration(String path, byte[] data) throws CmsException {
String configPath = path;
CmsObject cms = getCmsObject();
if (cms.existsResource(configPath)) {
lock(configPath);
CmsFile file = cms.readFile(configPath);
byte[] newContent = data;
file.setContents(newContent);
cms.writeFile(file);
} else {
byte[] newContent = data;
cms.createResource(
configPath,
OpenCms.getResourceManager().getResourceType("inheritance_config").getTypeId(),
newContent,
new ArrayList());
}
}
/**
* Writes a dummy configuration file to a given path.
*
* @param path the path where the configuration file should be written
* @param name the name contained in the configuration file
*
* @throws CmsException if something goes wrong
* @throws UnsupportedEncodingException
*/
protected void writeConfiguration(String path, String name) throws CmsException, UnsupportedEncodingException {
String configPath = path;
CmsObject cms = getCmsObject();
if (cms.existsResource(configPath)) {
lock(configPath);
CmsFile file = cms.readFile(configPath);
byte[] newContent = generateTestConfig(name);
file.setContents(newContent);
cms.writeFile(file);
} else {
byte[] newContent = generateTestConfig(name);
cms.createResource(
configPath,
OpenCms.getResourceManager().getResourceType("inheritance_config").getTypeId(),
newContent,
new ArrayList());
}
}
}