This is an automated email from the ASF dual-hosted git repository. simonetripodi pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-cpconverter.git
commit 677c41117e09feb596532e7524aac8aeb932892a Author: stripodi <[email protected]> AuthorDate: Thu Apr 18 15:03:24 2019 +0200 SLING-8363 - [cp2fm] map rep:SystemUser JCR nodes to repoinit Feature extension initial checkin --- .../ContentPackage2FeatureModelConverter.java | 17 ++++ .../handlers/AbstractJcrNodeParser.java | 58 +++++++++++++ .../handlers/SystemUsersEntryHandler.java | 64 +++++++++++++++ .../handlers/XmlConfigurationEntryHandler.java | 60 ++++++-------- ...ache.sling.feature.cpconverter.spi.EntryHandler | 1 + .../handlers/SystemUsersEntryHandlerTest.java | 95 ++++++++++++++++++++++ .../asd-index-definition-invalid/.content.xml | 22 +++++ .../asd-index-definition-reader/.content.xml | 22 +++++ 8 files changed, 303 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java b/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java index d686eb6..2bda617 100644 --- a/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java +++ b/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java @@ -66,6 +66,8 @@ public class ContentPackage2FeatureModelConverter { private static final String DEFEAULT_VERSION = "0.0.0"; + private static final String REPOINIT = "repoinit"; + private final Logger logger = LoggerFactory.getLogger(getClass()); private final PackageManager packageManager = new PackageManagerImpl(); @@ -313,6 +315,21 @@ public class ContentPackage2FeatureModelConverter { } } + public void addRepoinitStatement(String format, Object...args) { + Extension repoInitExtension = getTargetFeature().getExtensions().getByName(REPOINIT); + if (repoInitExtension == null) { + repoInitExtension = new Extension(ExtensionType.TEXT, REPOINIT, true); + getTargetFeature().getExtensions().add(repoInitExtension); + } + + String statement = String.format(format, args); + if (repoInitExtension.getText() == null) { + repoInitExtension.setText(statement); + } else { + repoInitExtension.setText(repoInitExtension.getText() + '\n' + statement); + } + } + public void addConfiguration(String runMode, String pid, Dictionary<String, Object> configurationProperties) { if (!mergeConfigurations) { checkConfigurationExist(getTargetFeature(), pid); diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractJcrNodeParser.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractJcrNodeParser.java new file mode 100644 index 0000000..12e3089 --- /dev/null +++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractJcrNodeParser.java @@ -0,0 +1,58 @@ +/* + * 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 org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE; + +import java.io.InputStream; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +abstract class AbstractJcrNodeParser extends DefaultHandler { + + private static final String JCR_ROOT = "jcr:root"; + + private static final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + + private final String primaryType; + + public AbstractJcrNodeParser(String primaryType) { + this.primaryType = primaryType; + } + + public void parse(InputStream input) throws Exception { + SAXParser saxParser = saxParserFactory.newSAXParser(); + saxParser.parse(input, this); + } + + @Override + public final void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + String primaryType = attributes.getValue(JCR_PRIMARYTYPE); + + if (JCR_ROOT.equals(qName) && this.primaryType.equals(primaryType)) { + onJcrRootElement(uri, localName, qName, attributes); + } + } + + protected abstract void onJcrRootElement(String uri, String localName, String qName, Attributes attributes) throws SAXException; + +} diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandler.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandler.java new file mode 100644 index 0000000..b451e8b --- /dev/null +++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandler.java @@ -0,0 +1,64 @@ +/* + * 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 java.io.InputStream; + +import org.apache.jackrabbit.vault.fs.io.Archive; +import org.apache.jackrabbit.vault.fs.io.Archive.Entry; +import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter; +import org.xml.sax.Attributes; + +public final class SystemUsersEntryHandler extends AbstractRegexEntryHandler { + + public SystemUsersEntryHandler() { + super("(jcr_root)?/home/users/.*/\\.content.xml"); + } + + @Override + public void handle(String path, Archive archive, Entry entry, ContentPackage2FeatureModelConverter converter) + throws Exception { + SystemUserParser systemUserParser = new SystemUserParser(converter); + try (InputStream input = archive.openInputStream(entry)) { + systemUserParser.parse(input); + } + } + + private static final class SystemUserParser extends AbstractJcrNodeParser { + + private final static String REP_SYSTEM_USER = "rep:SystemUser"; + + private final static String REP_AUTHORIZABLE_ID = "rep:authorizableId"; + + private final ContentPackage2FeatureModelConverter converter; + + public SystemUserParser(ContentPackage2FeatureModelConverter converter) { + super(REP_SYSTEM_USER); + this.converter = converter; + } + + @Override + protected void onJcrRootElement(String uri, String localName, String qName, Attributes attributes) { + String authorizableId = attributes.getValue(REP_AUTHORIZABLE_ID); + if (authorizableId != null && !authorizableId.isEmpty()) { + converter.addRepoinitStatement("create service user %s", authorizableId); + } + } + + } + +} diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java index ed6eabe..5188b24 100644 --- a/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java +++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java @@ -16,41 +16,30 @@ */ package org.apache.sling.feature.cpconverter.handlers; -import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE; - import java.io.InputStream; import java.util.Dictionary; import java.util.Hashtable; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - import org.apache.jackrabbit.vault.util.DocViewProperty; import org.xml.sax.Attributes; import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; public final class XmlConfigurationEntryHandler extends AbstractConfigurationEntryHandler { - private static final String JCR_ROOT = "jcr:root"; - - private static final String SLING_OSGICONFIG = "sling:OsgiConfig"; - - private final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); - public XmlConfigurationEntryHandler() { super("xml"); } @Override protected Dictionary<String, Object> parseConfiguration(String name, InputStream input) throws Exception { - SAXParser saxParser = saxParserFactory.newSAXParser(); JcrConfigurationHandler configurationHandler = new JcrConfigurationHandler(); - saxParser.parse(input, configurationHandler); + configurationHandler.parse(input); return configurationHandler.getConfiguration(); } - private static final class JcrConfigurationHandler extends DefaultHandler { + private static final class JcrConfigurationHandler extends AbstractJcrNodeParser { + + private static final String SLING_OSGICONFIG = "sling:OsgiConfig"; private final Dictionary<String, Object> configuration = new Hashtable<>(); @@ -58,28 +47,27 @@ public final class XmlConfigurationEntryHandler extends AbstractConfigurationEnt return configuration; } + public JcrConfigurationHandler() { + super(SLING_OSGICONFIG); + } + @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { - String primaryType = attributes.getValue(JCR_PRIMARYTYPE); - - if (JCR_ROOT.equals(qName) && SLING_OSGICONFIG.equals(primaryType)) { - for (int i = 0; i < attributes.getLength(); i++) { - String attributeQName = attributes.getQName(i); - - // ignore jcr: and similar properties - if (attributeQName.indexOf(':') == -1) { - String attributeValue = attributes.getValue(i); - - if (attributeValue != null && !attributeValue.isEmpty()) { - DocViewProperty property = DocViewProperty.parse(attributeQName, attributeValue); - - if (property.values.length > 0) { - if (property.isMulti) { - configuration.put(attributeQName, property.values); - } else { - configuration.put(attributeQName, property.values[0]); - } + protected void onJcrRootElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + for (int i = 0; i < attributes.getLength(); i++) { + String attributeQName = attributes.getQName(i); + + // ignore jcr: and similar properties + if (attributeQName.indexOf(':') == -1) { + String attributeValue = attributes.getValue(i); + + if (attributeValue != null && !attributeValue.isEmpty()) { + DocViewProperty property = DocViewProperty.parse(attributeQName, attributeValue); + + if (property.values.length > 0) { + if (property.isMulti) { + configuration.put(attributeQName, property.values); + } else { + configuration.put(attributeQName, property.values[0]); } } } diff --git a/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.spi.EntryHandler b/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.spi.EntryHandler index dfa616c..b4b9ec0 100644 --- a/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.spi.EntryHandler +++ b/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.spi.EntryHandler @@ -3,4 +3,5 @@ org.apache.sling.feature.cpconverter.handlers.ConfigurationEntryHandler org.apache.sling.feature.cpconverter.handlers.ContentPackageEntryHandler org.apache.sling.feature.cpconverter.handlers.JsonConfigurationEntryHandler org.apache.sling.feature.cpconverter.handlers.PropertiesConfigurationEntryHandler +org.apache.sling.feature.cpconverter.handlers.SystemUsersEntryHandler org.apache.sling.feature.cpconverter.handlers.XmlConfigurationEntryHandler diff --git a/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java b/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java new file mode 100644 index 0000000..5126e0f --- /dev/null +++ b/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java @@ -0,0 +1,95 @@ +/* + * 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 org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.*; + +import org.apache.jackrabbit.vault.fs.io.Archive; +import org.apache.jackrabbit.vault.fs.io.Archive.Entry; +import org.apache.sling.feature.ArtifactId; +import org.apache.sling.feature.Extension; +import org.apache.sling.feature.ExtensionType; +import org.apache.sling.feature.Feature; +import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class SystemUsersEntryHandlerTest { + + private SystemUsersEntryHandler systemUsersEntryHandler; + + @Before + public void setUp() { + systemUsersEntryHandler = new SystemUsersEntryHandler(); + } + + @After + public void tearDown() { + systemUsersEntryHandler = null; + } + + @Test + public void doesNotMatch() { + assertFalse(systemUsersEntryHandler.matches("/this/is/a/path/not/pointing/to/a/valid/configuration.asd")); + } + + @Test + public void matches() { + assertTrue(systemUsersEntryHandler.matches("/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml")); + assertTrue(systemUsersEntryHandler.matches("jcr_root/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml")); + } + + @Test + public void parseSystemUser() throws Exception { + String path = "jcr_root/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml"; + Extension repoinitExtension = parseAndSetRepoinit(path); + + assertNotNull(repoinitExtension); + assertEquals(ExtensionType.TEXT, repoinitExtension.getType()); + assertTrue(repoinitExtension.isRequired()); + assertEquals("create service user asd-share-commons-asd-index-definition-reader-service", repoinitExtension.getText()); + } + + @Test + public void unrecognisedSystemUserJcrNode() throws Exception { + String path = "jcr_root/home/users/system/asd-share-commons/asd-index-definition-invalid/.content.xml"; + Extension repoinitExtension = parseAndSetRepoinit(path); + assertNull(repoinitExtension); + } + + private Extension parseAndSetRepoinit(String path) throws Exception { + Archive archive = mock(Archive.class); + Entry entry = mock(Entry.class); + + when(archive.openInputStream(entry)).thenReturn(getClass().getResourceAsStream(path)); + + Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null)); + ContentPackage2FeatureModelConverter converter = spy(ContentPackage2FeatureModelConverter.class); + when(converter.getTargetFeature()).thenReturn(feature); + + systemUsersEntryHandler.handle(path, archive, entry, converter); + + return feature.getExtensions().getByName("repoinit"); + } + +} diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/asd-share-commons/asd-index-definition-invalid/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/asd-share-commons/asd-index-definition-invalid/.content.xml new file mode 100644 index 0000000..10d13f6 --- /dev/null +++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/asd-share-commons/asd-index-definition-invalid/.content.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal" + jcr:primaryType="rep:InvalidSystemUser" + jcr:uuid="b77dce45-d88d-31df-878b-8b076a68cb48" + rep:authorizableId="asd-share-commons-asd-index-definition-reader-service" + rep:principalName="asd-share-commons-asd-index-definition-reader-service"/> diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml new file mode 100644 index 0000000..6b0ebe6 --- /dev/null +++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal" + jcr:primaryType="rep:SystemUser" + jcr:uuid="b77dce45-d88d-31df-878b-8b076a68cb48" + rep:authorizableId="asd-share-commons-asd-index-definition-reader-service" + rep:principalName="asd-share-commons-asd-index-definition-reader-service"/>
