blob: deaa53944691337ed0291bb96b7943e7cb69e523 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You 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.apache.sling.feature.cpconverter.handlers;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.xmlunit.assertj.XmlAssert.assertThat;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;
import javax.xml.transform.Source;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.jackrabbit.vault.fs.api.VaultInputSource;
import org.apache.jackrabbit.vault.fs.io.Archive;
import org.apache.jackrabbit.vault.fs.io.Archive.Entry;
import org.apache.jackrabbit.vault.packaging.PackageId;
import org.apache.jackrabbit.vault.packaging.PackageProperties;
import org.apache.jackrabbit.vault.packaging.VaultPackage;
import org.apache.jackrabbit.vault.packaging.impl.PackageManagerImpl;
import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Configuration;
import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter.SlingInitialContentPolicy;
import org.apache.sling.feature.cpconverter.accesscontrol.DefaultAclManager;
import org.apache.sling.feature.cpconverter.artifacts.SimpleFolderArtifactsDeployer;
import org.apache.sling.feature.cpconverter.handlers.slinginitialcontent.BundleSlingInitialContentExtractor;
import org.apache.sling.feature.cpconverter.shared.ConverterConstants;
import org.apache.sling.feature.cpconverter.vltpkg.VaultPackageAssembler;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.xml.sax.SAXException;
import org.xmlunit.builder.Input;
import org.xmlunit.diff.ComparisonType;
import org.xmlunit.diff.DOMDifferenceEngine;
import org.xmlunit.diff.DifferenceEngine;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
@RunWith(MockitoJUnitRunner.class)
public class BundleEntryHandleSlingInitialContentTest extends AbstractBundleEntryHandlerTest {
@Captor
ArgumentCaptor<Dictionary<String, Object>> dictionaryCaptor;
@Captor
ArgumentCaptor<Configuration> cfgCaptor;
@Captor
ArgumentCaptor<String> repoinitTextCaptor;
@Test
public void testSlingInitialContent() throws Exception {
setUpArchive("/jcr_root/apps/gav/install/io.wcm.handler.media-1.11.6.jar", "io.wcm.handler.media-1.11.6.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager();
converter.setEntryHandlersManager(handlersManager);
Map<String, String> namespaceRegistry = Collections.singletonMap("granite", "http://www.adobe.com/jcr/granite/1.0");
when(featuresManager.getNamespaceUriByPrefix()).thenReturn(namespaceRegistry);
File targetFolder = tmpFolder.newFolder();
when(converter.getArtifactsDeployer()).thenReturn(new SimpleFolderArtifactsDeployer(targetFolder));
when(converter.isSubContentPackageIncluded("/jcr_root/apps/gav/install/io.wcm.handler.media-1.11.6.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "io.wcm");
props.setProperty(PackageProperties.NAME_NAME, "handler.media");
props.setProperty(PackageProperties.NAME_VERSION, "1.11.6");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
converter.setAclManager(new DefaultAclManager());
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_REMOVE);
handler.handle("/jcr_root/apps/gav/install/io.wcm.handler.media-1.11.6.jar", archive, entry, converter);
extractor.addRepoInitExtension(converter.getAssemblers(), featuresManager);
converter.deployPackages();
// verify generated bundle
try (JarFile jarFile = new JarFile(new File(targetFolder, "io.wcm.handler.media-1.11.6-cp2fm-converted.jar"))) {
String bundleVersion = jarFile.getManifest().getMainAttributes().getValue(Constants.BUNDLE_VERSION);
assertNotNull(bundleVersion);
assertNull(jarFile.getManifest().getMainAttributes().getValue("Sling-Initial-Content"));
assertEquals("_cp2fm-converted", Version.parseVersion(bundleVersion).getQualifier());
// make sure the initial content is no longer contained
assertNull(jarFile.getEntry("SLING-INF/app-root/"));
}
// verify generated package
try (VaultPackage vaultPackage = new PackageManagerImpl().open(new File(targetFolder, "io.wcm.handler.media-apps-1.11.6-cp2fm-converted.zip"));
Archive archive = vaultPackage.getArchive()) {
archive.open(true);
PackageId targetId = PackageId.fromString("io.wcm:io.wcm.handler.media-apps:1.11.6-cp2fm-converted");
assertEquals(targetId, vaultPackage.getId());
Entry entry = archive.getEntry("jcr_root/apps/wcm-io/handler/media/components/global/include/responsiveImageSettings/.content.xml");
assertNotNull("Archive does not contain expected item", entry);
Set<String> expectedCreatePathStatements = new HashSet<>();
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/content");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/components/granite/form/mediaformatselect(cq:Component)");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/i18n");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/components/global/include");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/components/placeholder");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/clientlibs/authoring/dialog(cq:ClientLibraryFolder)/css");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/components/granite/form/fileupload(cq:Component)");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/clientlibs/authoring/dialog(cq:ClientLibraryFolder)/js");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/components/granite/datasources/mediaformats");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/docroot/resources/img");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/components/granite/global");
expectedCreatePathStatements.add("create path (sling:Folder) /apps/wcm-io/handler/media/components/granite/form/pathfield(cq:Component)");
verify(featuresManager, times(1)).addOrAppendRepoInitExtension(eq("content-package"), repoinitTextCaptor.capture(), Mockito.isNull());
for(String expectedCreatePathStatement: expectedCreatePathStatements){
assertTrue("Repoinit text does not contain desired create path statement!",StringUtils.contains(repoinitTextCaptor.getValue(), expectedCreatePathStatement));
}
}
// verify nothing else has been deployed
assertEquals(2, targetFolder.list().length);
// verify changed id
ArgumentCaptor<Artifact> captor = ArgumentCaptor.forClass(Artifact.class);
verify(featuresManager).addArtifact(Mockito.isNull(), captor.capture(), Mockito.isNull());
final Artifact result = captor.getValue();
assertNotNull(result);
assertEquals(ArtifactId.fromMvnId("io.wcm:io.wcm.handler.media:1.11.6-cp2fm-converted"), result.getId());
assertEquals("io.wcm.handler.media", result.getMetadata().get(Constants.BUNDLE_SYMBOLICNAME));
assertEquals("1.11.6", result.getMetadata().get(Constants.BUNDLE_VERSION));
}
@Test
public void testJsonI18nWithXMLFolderDescriptors() throws Exception {
setUpArchive("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", "mysite.core-1.0.0-SNAPSHOT-i18n-xml-folderdescriptor.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager(Collections.emptyMap(), false, SlingInitialContentPolicy.KEEP, new BundleSlingInitialContentExtractor(), ConverterConstants.SYSTEM_USER_REL_PATH_DEFAULT);
converter.setEntryHandlersManager(handlersManager);
Map<String, String> namespaceRegistry = new HashMap<>();
namespaceRegistry.put("cq","http://www.day.com/jcr/cq/1.0");
namespaceRegistry.put("granite", "http://www.adobe.com/jcr/granite/1.0");
when(featuresManager.getNamespaceUriByPrefix()).thenReturn(namespaceRegistry);
File targetFolder = tmpFolder.newFolder();
when(converter.getArtifactsDeployer()).thenReturn(new SimpleFolderArtifactsDeployer(targetFolder));
when(converter.isSubContentPackageIncluded("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "com.mysite");
props.setProperty(PackageProperties.NAME_NAME, "mysite.core");
props.setProperty(PackageProperties.NAME_VERSION, "1.0.0-SNAPSHOT");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
converter.setAclManager(new DefaultAclManager());
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_REMOVE);
handler.handle("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", archive, entry, converter);
converter.deployPackages();
Type typeOfHashMap = new TypeToken<Map<String, String>>() { }.getType();
// verify generated package
try (VaultPackage vaultPackage = new PackageManagerImpl().open(new File(targetFolder, "mysite.core-apps-1.0.0-SNAPSHOT-cp2fm-converted.zip"));
Archive archive = vaultPackage.getArchive()) {
archive.open(true);
PackageId targetId = PackageId.fromString("com.mysite:mysite.core-apps:1.0.0-SNAPSHOT-cp2fm-converted");
assertEquals(targetId, vaultPackage.getId());
Entry jsonFileEntry = archive.getEntry("/jcr_root/apps/myinitialcontentest/test/i18n/en.json");
assertNotNull(jsonFileEntry);
//compare JSON
Reader actualJsonFileContents = new InputStreamReader(archive.getInputSource(jsonFileEntry).getByteStream(), UTF_8);
Reader expectedJsonFileContents = new InputStreamReader(getClass().getResourceAsStream("i18n-jsonfile-xml-descriptor-test/en.json"), UTF_8);
Gson GSON = new GsonBuilder().create();
Map<String,String> actualJson = GSON.fromJson(actualJsonFileContents, typeOfHashMap);
Map<String,String> expectedJson = GSON.fromJson(expectedJsonFileContents, typeOfHashMap);
assertEquals(expectedJson, actualJson);
//compare XML
Entry jsonFileDescriptorEntry = archive.getEntry("/jcr_root/apps/myinitialcontentest/test/i18n/en.json.dir/.content.xml");
assertNotNull(jsonFileDescriptorEntry);
String expectedXML = IOUtils.toString(getClass().getResourceAsStream("i18n-jsonfile-xml-descriptor-test/en.json.dir/.content.xml"), UTF_8);
String actualXML = IOUtils.toString(archive.getInputSource(jsonFileDescriptorEntry).getByteStream(), UTF_8);
assertThat(actualXML).and(expectedXML).areSimilar();
}
}
@Test
public void testSlingInitialContentWithNodeTypeAndNoDefinedParent() throws Exception {
setUpArchive("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", "mysite.core-1.0.0-SNAPSHOT-slinginitialcontent-test.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager(Collections.emptyMap(), false, SlingInitialContentPolicy.KEEP, new BundleSlingInitialContentExtractor(), ConverterConstants.SYSTEM_USER_REL_PATH_DEFAULT);
converter.setEntryHandlersManager(handlersManager);
Map<String, String> namespaceRegistry = new HashMap<>();
namespaceRegistry.put("cq","http://www.day.com/jcr/cq/1.0");
namespaceRegistry.put("granite", "http://www.adobe.com/jcr/granite/1.0");
when(featuresManager.getNamespaceUriByPrefix()).thenReturn(namespaceRegistry);
File targetFolder = tmpFolder.newFolder();
when(converter.getArtifactsDeployer()).thenReturn(new SimpleFolderArtifactsDeployer(targetFolder));
when(converter.isSubContentPackageIncluded("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "com.mysite");
props.setProperty(PackageProperties.NAME_NAME, "mysite.core");
props.setProperty(PackageProperties.NAME_VERSION, "1.0.0-SNAPSHOT");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
DefaultAclManager aclManager = new DefaultAclManager();
converter.setAclManager(aclManager);
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_REMOVE);
handler.handle("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", archive, entry, converter);
converter.deployPackages();
extractor.addRepoInitExtension(converter.getAssemblers(), featuresManager);
try (VaultPackage vaultPackage = new PackageManagerImpl().open(new File(targetFolder, "mysite.core-apps-1.0.0-SNAPSHOT-cp2fm-converted.zip"));
Archive archive = vaultPackage.getArchive()) {
archive.open(true);
PackageId targetId = PackageId.fromString("com.mysite:mysite.core-apps:1.0.0-SNAPSHOT-cp2fm-converted");
assertEquals(targetId, vaultPackage.getId());
InputStream inputStream = archive.getInputSource(archive.getEntry("jcr_root/apps/myinitialcontentest/test/parent-with-definition/.content.xml")).getByteStream();
assertNotNull(inputStream);
//this needs to be defined by repoinit, not the package itself
Archive.Entry parentWithoutDefinitionEntry = archive.getEntry("jcr_root/apps/myinitialcontentest/test/parent-with-definition/parent-without-definition/.content.xml");
assertNull(parentWithoutDefinitionEntry);
InputStream someUnstructuredNode = archive.getInputSource(archive.getEntry("jcr_root/apps/myinitialcontentest/test/parent-with-definition/parent-without-definition/someUnstructuredNode/.content.xml")).getByteStream();
assertNotNull(someUnstructuredNode);
String repoinitText = String.format(
"create path (sling:Folder) /content/test/myinitialcontentest2%n" +
"create path (sling:Folder) /apps/myinitialcontentest/test/parent-with-definition(my:parent)/parent-without-definition%n");
verify(featuresManager, times(1)).addOrAppendRepoInitExtension(eq("content-package"), eq(repoinitText), Mockito.isNull());
}
}
@Test
public void testSlingInitialContentWithNodeTypeAndPageJson() throws Exception {
setUpArchive("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", "mysite.core-1.0.0-SNAPSHOT-pagejson.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager(Collections.emptyMap(), false, SlingInitialContentPolicy.KEEP, new BundleSlingInitialContentExtractor(), ConverterConstants.SYSTEM_USER_REL_PATH_DEFAULT);
converter.setEntryHandlersManager(handlersManager);
Map<String, String> namespaceRegistry = new HashMap<>();
namespaceRegistry.put("cq","http://www.day.com/jcr/cq/1.0");
namespaceRegistry.put("granite", "http://www.adobe.com/jcr/granite/1.0");
when(featuresManager.getNamespaceUriByPrefix()).thenReturn(namespaceRegistry);
File targetFolder = tmpFolder.newFolder();
when(converter.getArtifactsDeployer()).thenReturn(new SimpleFolderArtifactsDeployer(targetFolder));
when(converter.isSubContentPackageIncluded("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "com.mysite");
props.setProperty(PackageProperties.NAME_NAME, "mysite.core");
props.setProperty(PackageProperties.NAME_VERSION, "1.0.0-SNAPSHOT");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
converter.setAclManager(new DefaultAclManager());
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_REMOVE);
handler.handle("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", archive, entry, converter);
converter.deployPackages();
// verify generated package
try (VaultPackage vaultPackage = new PackageManagerImpl().open(new File(targetFolder, "mysite.core-apps-1.0.0-SNAPSHOT-cp2fm-converted.zip"));
Archive archive = vaultPackage.getArchive()) {
archive.open(true);
PackageId targetId = PackageId.fromString("com.mysite:mysite.core-apps:1.0.0-SNAPSHOT-cp2fm-converted");
assertEquals(targetId, vaultPackage.getId());
assertPageStructureFromEntry(archive, "jcr_root/apps/mysite/components/global", "homepage");
assertPageStructureFromEntry(archive, "jcr_root/apps/mysite/components/global", "page", "body.html");
assertPageStructureFromEntry(archive, "jcr_root/apps/mysite/components/global", "xfpage","body.html");
InputStream inputStream = archive.getInputSource(archive.getEntry("jcr_root/apps/mysite/components/global/homepage/.content.xml")).getByteStream();
String expectedXML = IOUtils.toString(getClass().getResource("mysite-nodetype-and-page-json-xml-result.xml").openStream(), UTF_8);
String actualXML = IOUtils.toString(inputStream, UTF_8);
assertThat(expectedXML).and(actualXML).ignoreElementContentWhitespace().ignoreComments().areSimilar();
}
}
@Test
public void testSlingInitialContentWithSpecialCharacters() throws Exception {
// skip this test on windows - the special chars used in file and property names will not work on windows FS
assumeFalse(SystemUtils.IS_OS_WINDOWS);
setUpArchive("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", "mysite.core-1.0.0-SNAPSHOT-specialchars-json-inputstream.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager(Collections.emptyMap(), false, SlingInitialContentPolicy.KEEP, new BundleSlingInitialContentExtractor(), ConverterConstants.SYSTEM_USER_REL_PATH_DEFAULT);
converter.setEntryHandlersManager(handlersManager);
Map<String, String> namespaceRegistry = new HashMap<>();
namespaceRegistry.put("cq","http://www.day.com/jcr/cq/1.0");
namespaceRegistry.put("granite", "http://www.adobe.com/jcr/granite/1.0");
when(featuresManager.getNamespaceUriByPrefix()).thenReturn(namespaceRegistry);
File targetFolder = tmpFolder.newFolder();
when(converter.getArtifactsDeployer()).thenReturn(new SimpleFolderArtifactsDeployer(targetFolder));
when(converter.isSubContentPackageIncluded("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "com.mysite");
props.setProperty(PackageProperties.NAME_NAME, "mysite.core");
props.setProperty(PackageProperties.NAME_VERSION, "1.0.0-SNAPSHOT");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
converter.setAclManager(new DefaultAclManager());
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_REMOVE);
handler.handle("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", archive, entry, converter);
converter.deployPackages();
// verify generated package
try (VaultPackage vaultPackage = new PackageManagerImpl().open(new File(targetFolder, "mysite.core-apps-1.0.0-SNAPSHOT-cp2fm-converted.zip"));
Archive archive = vaultPackage.getArchive()) {
archive.open(true);
PackageId targetId = PackageId.fromString("com.mysite:mysite.core-apps:1.0.0-SNAPSHOT-cp2fm-converted");
assertEquals(targetId, vaultPackage.getId());
//json containing a property: "fancyCharacters": "<&\"'>"
assertPageStructureFromEntry(archive,"jcr_root/apps/mysite/components/global", "homepage" );
assertResultingEntry(archive, "homepage");
//xml with custom name element: nodeName and containing a textfile
assertPageStructureFromEntry(archive,"jcr_root/apps/mysite/components/global", "nodeName", "testfile.txt" );
assertResultingEntry(archive, "nodeName");
//xml with custom "name" element "xyz"
assertPageStructureFromEntry(archive, "jcr_root/apps/mysite/components/global", "xyz");
assertResultingEntry(archive, "xyz");
//xml with custom name element: 11&quot;&quot;&gt;&lt;mumbojumbo
assertResultingEntry(archive, "11mumbojumbo");
assertPageStructureFromEntry(archive,"jcr_root/apps/mysite/components/global", "11mumbojumbo" );
}
}
@Test
public void testSlingInitialContentWithNumberedEntries() throws Exception {
setUpArchive("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", "io.wcm.handler.link-1.7.02.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager(Collections.emptyMap(), false, SlingInitialContentPolicy.KEEP, new BundleSlingInitialContentExtractor(), ConverterConstants.SYSTEM_USER_REL_PATH_DEFAULT);
converter.setEntryHandlersManager(handlersManager);
Map<String, String> namespaceRegistry = new HashMap<>();
namespaceRegistry.put("cq","http://www.day.com/jcr/cq/1.0");
namespaceRegistry.put("granite", "http://www.adobe.com/jcr/granite/1.0");
when(featuresManager.getNamespaceUriByPrefix()).thenReturn(namespaceRegistry);
File targetFolder = tmpFolder.newFolder();
when(converter.getArtifactsDeployer()).thenReturn(new SimpleFolderArtifactsDeployer(targetFolder));
when(converter.isSubContentPackageIncluded("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "com.mysite");
props.setProperty(PackageProperties.NAME_NAME, "mysite.core");
props.setProperty(PackageProperties.NAME_VERSION, "1.0.0-SNAPSHOT");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
converter.setAclManager(new DefaultAclManager());
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_REMOVE);
handler.handle("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", archive, entry, converter);
converter.deployPackages();
// verify generated package
try (VaultPackage vaultPackage = new PackageManagerImpl().open(new File(targetFolder, "io.wcm.handler.link-apps-1.7.0-cp2fm-converted.zip"));
Archive archive = vaultPackage.getArchive()) {
archive.open(true);
InputStream xmlFile = archive.getInputSource(archive.getEntry("jcr_root/apps/wcm-io/handler/link/components/global/include/redirectStatus/.content.xml")).getByteStream();
String expectedXML = IOUtils.toString(getClass().getResourceAsStream("bundle-entry-xmls/include-redirectStatus.xml"), UTF_8);
String actualXML = IOUtils.toString(xmlFile, UTF_8);
assertThat(expectedXML).and(actualXML).areSimilar();
}
}
@Test
public void testSlingInitialContentWithNodeType() throws Exception {
setUpArchive("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", "mysite-slinginitialcontent-nodetype-def.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager();
converter.setEntryHandlersManager(handlersManager);
converter.setAclManager(new DefaultAclManager());
Map<String, String> namespaceRegistry = Collections.singletonMap("granite", "http://www.adobe.com/jcr/granite/1.0");
when(featuresManager.getNamespaceUriByPrefix()).thenReturn(namespaceRegistry);
File targetFolder = tmpFolder.newFolder();
when(converter.getArtifactsDeployer()).thenReturn(new SimpleFolderArtifactsDeployer(targetFolder));
when(converter.isSubContentPackageIncluded("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "com.mysite");
props.setProperty(PackageProperties.NAME_NAME, "mysite.core");
props.setProperty(PackageProperties.NAME_VERSION, "1.0.0-SNAPSHOT");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_REMOVE);
handler.handle("/jcr_root/apps/mysite/install/mysite-slinginitialcontent-nodetype-def.jar", archive, entry, converter);
converter.deployPackages();
// verify generated bundle
try (JarFile jarFile = new JarFile(new File(targetFolder, "mysite.core-1.0.0-SNAPSHOT-cp2fm-converted.jar"))) {
String bundleVersion = jarFile.getManifest().getMainAttributes().getValue(Constants.BUNDLE_VERSION);
assertNotNull(bundleVersion);
assertNull(jarFile.getManifest().getMainAttributes().getValue("Sling-Initial-Content"));
assertEquals("SNAPSHOT_cp2fm-converted", Version.parseVersion(bundleVersion).getQualifier());
// make sure the initial content is no longer contained
assertNull(jarFile.getEntry("SLING-INF/app-root/"));
}
// verify generated package
try (VaultPackage vaultPackage = new PackageManagerImpl().open(new File(targetFolder, "mysite.core-apps-1.0.0-SNAPSHOT-cp2fm-converted.zip"));
Archive archive = vaultPackage.getArchive()) {
archive.open(true);
PackageId targetId = PackageId.fromString("com.mysite:mysite.core-apps:1.0.0-SNAPSHOT-cp2fm-converted");
assertEquals(targetId, vaultPackage.getId());
Entry entry = archive.getEntry("jcr_root/apps/myinitialcontentest/my-first-node/.content.xml");
assertNotNull("Archive does not contain expected item", entry);
}
// verify nothing else has been deployed
assertEquals(2, targetFolder.list().length);
// verify changed id
ArgumentCaptor<Artifact> captor = ArgumentCaptor.forClass(Artifact.class);
verify(featuresManager).addArtifact(Mockito.isNull(), captor.capture(), Mockito.isNull());
final Artifact result = captor.getValue();
assertNotNull(result);
assertEquals(ArtifactId.fromMvnId("com.mysite:mysite.core:1.0.0-SNAPSHOT-cp2fm-converted"), result.getId());
assertEquals("mysite.core", result.getMetadata().get(Constants.BUNDLE_SYMBOLICNAME));
assertEquals("1.0.0.SNAPSHOT", result.getMetadata().get(Constants.BUNDLE_VERSION));
}
@Test
public void testSlingInitialContentContainingConfigurationExtractAndRemove() throws Exception {
setUpArchive("/jcr_root/apps/gav/install/composum-nodes-config-2.5.3.jar", "composum-nodes-config-2.5.3.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager();
converter.setEntryHandlersManager(handlersManager);
when(converter.isSubContentPackageIncluded("/jcr_root/apps/gav/install/composum-nodes-config-2.5.3.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "io.wcm");
props.setProperty(PackageProperties.NAME_NAME, "handler.media");
props.setProperty(PackageProperties.NAME_VERSION, "1.11.6");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
converter.setAclManager(new DefaultAclManager());
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_REMOVE);
handler.handle("/jcr_root/apps/gav/install/composum-nodes-config-2.5.3.jar", archive, entry, converter);
// modified bundle
ArgumentCaptor<Artifact> captor = ArgumentCaptor.forClass(Artifact.class);
verify(featuresManager).addArtifact(Mockito.isNull(), captor.capture(), Mockito.isNull());
final Artifact result = captor.getValue();
assertNotNull(result);
assertEquals(ArtifactId.fromMvnId("com.composum.nodes:composum-nodes-config:2.5.3-cp2fm-converted"), result.getId());
assertEquals("com.composum.nodes.config", result.getMetadata().get(Constants.BUNDLE_SYMBOLICNAME));
assertEquals("2.5.3", result.getMetadata().get(Constants.BUNDLE_VERSION));
// need to use ArgumentCaptur to properly compare string arrays
verify(featuresManager).addConfiguration(ArgumentMatchers.isNull(), cfgCaptor.capture(), eq("/jcr_root/libs/composum/nodes/install/org.apache.sling.jcr.base.internal.LoginAdminWhitelist.fragment-composum_core_v2.config"), dictionaryCaptor.capture());
assertEquals("composum_core", dictionaryCaptor.getValue().get("whitelist.name"));
assertEquals("org.apache.sling.jcr.base.internal.LoginAdminWhitelist.fragment~composum_core_v2", cfgCaptor.getValue().getPid());
assertArrayEquals(new String[] {
"com.composum.nodes.commons",
"com.composum.nodes.pckgmgr",
"com.composum.nodes.pckginstall" }, (String[])dictionaryCaptor.getValue().get("whitelist.bundles"));
}
@Test
public void testSlingInitialContentContainingConfigurationExtractAndKeep() throws Exception {
setUpArchive("/jcr_root/apps/gav/install/composum-nodes-config-2.5.3.jar", "composum-nodes-config-2.5.3.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager();
converter.setEntryHandlersManager(handlersManager);
when(converter.isSubContentPackageIncluded("/jcr_root/apps/gav/install/composum-nodes-config-2.5.3.jar-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "io.wcm");
props.setProperty(PackageProperties.NAME_NAME, "handler.media");
props.setProperty(PackageProperties.NAME_VERSION, "1.11.6");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
converter.setAclManager(new DefaultAclManager());
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_KEEP);
handler.handle("/jcr_root/apps/gav/install/composum-nodes-config-2.5.3.jar", archive, entry, converter);
// original bundle
ArgumentCaptor<Artifact> captor = ArgumentCaptor.forClass(Artifact.class);
verify(featuresManager).addArtifact(Mockito.isNull(), captor.capture(), Mockito.isNull());
final Artifact result = captor.getValue();
assertNotNull(result);
assertEquals(ArtifactId.fromMvnId("com.composum.nodes:composum-nodes-config:2.5.3"), result.getId());
assertEquals("com.composum.nodes.config", result.getMetadata().get(Constants.BUNDLE_SYMBOLICNAME));
assertEquals("2.5.3", result.getMetadata().get(Constants.BUNDLE_VERSION));
// need to use ArgumentCaptur to properly compare string arrays
verify(featuresManager).addConfiguration(ArgumentMatchers.isNull(),
cfgCaptor.capture(),
eq("/jcr_root/libs/composum/nodes/install/org.apache.sling.jcr.base.internal.LoginAdminWhitelist.fragment-composum_core_v2.config"), dictionaryCaptor.capture());
assertEquals("composum_core", dictionaryCaptor.getValue().get("whitelist.name"));
assertEquals("org.apache.sling.jcr.base.internal.LoginAdminWhitelist.fragment~composum_core_v2", cfgCaptor.getValue().getPid());
assertArrayEquals(new String[] {
"com.composum.nodes.commons",
"com.composum.nodes.pckgmgr",
"com.composum.nodes.pckginstall" }, (String[])dictionaryCaptor.getValue().get("whitelist.bundles"));
}
@Test
public void testSlingInitialContentWithMissingNamespaceDeclaration() throws Exception {
String embeddedEntryPath = "/jcr_root/apps/mysite-packages/application/install/mysite.core-1.0.0-SNAPSHOT.jar";
setUpArchive(embeddedEntryPath, "mysite.core-1.0.0-SNAPSHOT.jar");
DefaultEntryHandlersManager handlersManager = new DefaultEntryHandlersManager();
File targetFolder = tmpFolder.newFolder();
when(converter.getArtifactsDeployer()).thenReturn(new SimpleFolderArtifactsDeployer(targetFolder));
converter.setEntryHandlersManager(handlersManager);
when(converter.isSubContentPackageIncluded(embeddedEntryPath+"-APPLICATION")).thenReturn(true);
VaultPackageAssembler assembler = Mockito.mock(VaultPackageAssembler.class);
Properties props = new Properties();
props.setProperty(PackageProperties.NAME_GROUP, "org.apache.sling");
props.setProperty(PackageProperties.NAME_NAME, "testSlingInitialContentWithMissingNamespaceDeclaration");
props.setProperty(PackageProperties.NAME_VERSION, "1.0-SNAPSHOT");
when(assembler.getPackageProperties()).thenReturn(props);
converter.setMainPackageAssembler(assembler);
converter.setAclManager(new DefaultAclManager());
BundleSlingInitialContentExtractor extractor = new BundleSlingInitialContentExtractor();
handler.setBundleSlingInitialContentExtractor(extractor);
handler.setSlingInitialContentPolicy(SlingInitialContentPolicy.EXTRACT_AND_KEEP);
handler.handle(embeddedEntryPath, archive, entry, converter);
converter.deployPackages();
// original bundle
ArgumentCaptor<Artifact> captor = ArgumentCaptor.forClass(Artifact.class);
verify(featuresManager).addArtifact(Mockito.isNull(), captor.capture(), Mockito.isNull());
// verify generated package
try (VaultPackage vaultPackage = new PackageManagerImpl().open(new File(targetFolder, "mysite.core-apps-1.0.0-SNAPSHOT-cp2fm-converted.zip"));
Archive archive = vaultPackage.getArchive()) {
archive.open(true);
VaultInputSource inputSource = archive.getInputSource(archive.getEntry("jcr_root/apps/myinitialcontentest/test/my-first-node/.content.xml"));
MatcherAssert.assertThat(inputSource, CoreMatchers.notNullValue());
}
}
private void assertResultingEntry(Archive archive, String entryKey) throws IOException, SAXException {
InputStream xmlFile = archive.getInputSource(archive.getEntry("jcr_root/apps/mysite/components/global/" + entryKey +"/.content.xml")).getByteStream();
InputStream expectedXmlFileStream = getClass().getResourceAsStream("bundle-entry-xmls/" + entryKey + ".xml");
String expectedXML = IOUtils.toString(expectedXmlFileStream, UTF_8);
String actualXML = IOUtils.toString(xmlFile, UTF_8);
Source control = Input.fromString(expectedXML).build();
Source test = Input.fromString(actualXML).build();
DifferenceEngine diff = new DOMDifferenceEngine();
diff.addDifferenceListener((comparison, outcome) -> {
if(comparison.getType() == ComparisonType.CHILD_NODELIST_LENGTH){
//this comparison is buggy so we can't use it.
return;
}
String actualString = comparison.getTestDetails().getValue().toString();
String expectedString = comparison.getControlDetails().getValue().toString();
if(!actualString.trim().equals(expectedString.trim())){
Assert.fail("difference found in XML: " + actualString + " vs " + expectedString);
}
});
diff.compare(control, test);
}
private void assertPageStructureFromEntry(Archive archive, String basePath, String pageName, String... files) throws IOException {
Entry contentXml = archive.getEntry( basePath + "/" + pageName + "/.content.xml");
assertNotNull(contentXml);
Entry pageXml = archive.getEntry( basePath + "/" + pageName + ".xml");
assertNull(pageXml);
for(String file: files){
Entry expectedEntry = archive.getEntry( basePath + "/" + pageName + "/" + file);
assertNotNull(expectedEntry);
}
}
}