You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2019/02/25 12:38:22 UTC

[sling-org-apache-sling-installer-provider-installhook] 03/24: SLING-7790 Introduced package property "installPathRegex" to control what bundles/configs are taken into consideration and runmode support

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/SLING-8291_expose-error
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-provider-installhook.git

commit 19eba2c26f323ca7851c41530ec1257264d2a2f1
Author: Georg Henzler <ge...@netcentric.biz>
AuthorDate: Tue Aug 21 17:15:34 2018 +0200

    SLING-7790 Introduced package property "installPathRegex" to control
    what bundles/configs are taken into consideration and runmode support
---
 pom.xml                                            |   6 ++
 .../provider/installhook/OsgiInstallerHook.java    | 113 ++++++++++++++++-----
 2 files changed, 91 insertions(+), 28 deletions(-)

diff --git a/pom.xml b/pom.xml
index 820c8bb..533af9b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,6 +86,12 @@
 			<version>3.6.8</version>
 			<scope>provided</scope>
 		</dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.settings</artifactId>
+            <version>1.0.0</version>
+            <scope>provided</scope>
+        </dependency>		
 		<dependency>
 			<groupId>org.osgi</groupId>
 			<artifactId>osgi.core</artifactId>
diff --git a/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHook.java b/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHook.java
index 1245725..362ae6e 100644
--- a/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHook.java
+++ b/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHook.java
@@ -21,6 +21,7 @@ package org.apache.sling.installer.provider.installhook;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -45,10 +46,12 @@ import org.apache.jackrabbit.vault.fs.io.ImportOptions;
 import org.apache.jackrabbit.vault.packaging.InstallContext;
 import org.apache.jackrabbit.vault.packaging.InstallHook;
 import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.apache.jackrabbit.vault.packaging.PackageProperties;
 import org.apache.jackrabbit.vault.packaging.VaultPackage;
 import org.apache.sling.installer.api.InstallableResource;
 import org.apache.sling.installer.api.OsgiInstaller;
 import org.apache.sling.installer.api.event.InstallationListener;
+import org.apache.sling.settings.SlingSettingsService;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
@@ -77,28 +80,57 @@ public class OsgiInstallerHook implements InstallHook {
 
 	public static final String URL_SCHEME = "jcrinstall";
 	public static final String CONFIG_SUFFIX = ".config";
+	public static final String JAR_SUFFIX = ".jar";
+
+	public static final String PACKAGE_PROP_INSTALL_PATH_REGEX = "installPathRegex";
+
+	public static final String DOT = ".";
+	public static final int PRIORITY_INSTALL_HOOK = 2000;
 
 	private InstallHookLogger logger = new InstallHookLogger();
 
 	@Override
 	public void execute(InstallContext context) throws PackageException {
 
+		VaultPackage vaultPackage = context.getPackage();
+		PackageProperties packageProperties = vaultPackage.getProperties();
+		String installPathRegex = packageProperties.getProperty(PACKAGE_PROP_INSTALL_PATH_REGEX);
+
 		ServiceReference<OsgiInstaller> osgiInstallerServiceRef = null;
 		ServiceReference<ConfigurationAdmin> configAdminServiceRef = null;
+		ServiceReference<SlingSettingsService> slingSettingsServiceRef = null;
 		ServiceRegistration<InstallationListener> hookInstallationListenerServiceRegistration = null;
+
 		try {
 			switch (context.getPhase()) {
+			case PREPARE:
+				if (StringUtils.isBlank(installPathRegex)) {
+					throw new IllegalArgumentException(
+							"When using OSGi installer install hook for synchronous installation, the package property "
+									+ PACKAGE_PROP_INSTALL_PATH_REGEX + " has to be provided.");
+				}
+				break;
 			case INSTALLED:
 				ImportOptions options = context.getOptions();
 				logger.setOptions(options);
-				VaultPackage vaultPackage = context.getPackage();
 
 				logger.log(getClass().getSimpleName() + " is active in " + vaultPackage.getId());
 
 				List<BundleInPackage> bundleResources = new ArrayList<>();
 				List<String> configResourcePaths = new ArrayList<>();
 				Archive archive = vaultPackage.getArchive();
-				collectResources(archive, archive.getRoot(), "", bundleResources, configResourcePaths);
+
+				configAdminServiceRef = getBundleContext().getServiceReference(ConfigurationAdmin.class);
+				ConfigurationAdmin confAdmin = (ConfigurationAdmin) getBundleContext()
+						.getService(configAdminServiceRef);
+
+				slingSettingsServiceRef = getBundleContext().getServiceReference(SlingSettingsService.class);
+				SlingSettingsService slingSettingsService = (SlingSettingsService) getBundleContext()
+						.getService(slingSettingsServiceRef);
+				Set<String> runModes = slingSettingsService.getRunModes();
+
+				collectResources(archive, archive.getRoot(), "", bundleResources, configResourcePaths, installPathRegex,
+						runModes);
 
 				logger.log("Bundles in package " + bundleResources);
 
@@ -114,10 +146,6 @@ public class OsgiInstallerHook implements InstallHook {
 				Set<String> bundleSymbolicNamesToInstall = getBundlesToInstall(bundleResources,
 						bundleVersionsBySymbolicId, session, installableResources);
 
-				configAdminServiceRef = getBundleContext().getServiceReference(ConfigurationAdmin.class);
-				ConfigurationAdmin confAdmin = (ConfigurationAdmin) getBundleContext()
-						.getService(configAdminServiceRef);
-
 				Set<String> configPidsToInstall = getConfigPidsToInstall(configResourcePaths, session,
 						installableResources, confAdmin);
 
@@ -140,7 +168,7 @@ public class OsgiInstallerHook implements InstallHook {
 				osgiInstaller.updateResources(URL_SCHEME,
 						installableResources.toArray(new InstallableResource[installableResources.size()]), null);
 
-				String maxWaitForOsgiInstallerInSecStr = vaultPackage.getProperties()
+				String maxWaitForOsgiInstallerInSecStr = packageProperties
 						.getProperty(PACKAGE_PROPERTY_MAX_WAIT_IN_SEC);
 				int maxWaitForOsgiInstallerInSec = maxWaitForOsgiInstallerInSecStr != null
 						? Integer.parseInt(maxWaitForOsgiInstallerInSecStr)
@@ -162,7 +190,7 @@ public class OsgiInstallerHook implements InstallHook {
 				break;
 			}
 		} catch (Exception e) {
-			throw new PackageException("Could not execute install hook to apply env vars: " + e, e);
+			throw new PackageException("Could not execute install hook to for synchronous installation: " + e, e);
 		} finally {
 			if (osgiInstallerServiceRef != null) {
 				getBundleContext().ungetService(osgiInstallerServiceRef);
@@ -170,6 +198,9 @@ public class OsgiInstallerHook implements InstallHook {
 			if (configAdminServiceRef != null) {
 				getBundleContext().ungetService(configAdminServiceRef);
 			}
+			if (slingSettingsServiceRef != null) {
+				getBundleContext().ungetService(slingSettingsServiceRef);
+			}
 
 			if (hookInstallationListenerServiceRegistration != null) {
 				hookInstallationListenerServiceRegistration.unregister();
@@ -248,31 +279,58 @@ public class OsgiInstallerHook implements InstallHook {
 	}
 
 	private void collectResources(Archive archive, Entry entry, String dirPath, List<BundleInPackage> bundleResources,
-			List<String> configResources) {
+			List<String> configResources, String installPathRegex, Set<String> actualRunmodes) {
 		String entryName = entry.getName();
-
-		if (entryName.endsWith(".jar") && dirPath.contains("/install")) {
-
-			try (InputStream entryInputStream = archive.getInputSource(entry).getByteStream();
-					JarInputStream jarInputStream = new JarInputStream(entryInputStream)) {
-				Manifest manifest = jarInputStream.getManifest();
-				String symbolicName = manifest.getMainAttributes().getValue(MANIFEST_BUNDLE_SYMBOLIC_NAME);
-				String version = manifest.getMainAttributes().getValue(MANIFEST_BUNDLE_VERSION);
-				String bundlePath = StringUtils.substringAfter(dirPath + entryName, "/jcr_root");
-				bundleResources.add(new BundleInPackage(bundlePath, symbolicName, version));
-			} catch (Exception e) {
-				throw new IllegalStateException(
-						"Could not read symbolic name and version from manifest of bundle " + entryName);
+		if(entryName.equals("META-INF")) {
+			return;
+		} 
+
+		String dirPathWithoutJcrRoot = StringUtils.substringAfter(dirPath, "/jcr_root");
+		String entryPath = dirPathWithoutJcrRoot + entryName;
+		String dirPathWithoutSlash = StringUtils.chomp(dirPathWithoutJcrRoot, "/");
+
+		String dirPathWithoutRunmodes;
+		boolean runmodesMatch;
+		if (dirPathWithoutSlash.contains(DOT)) {
+			String[] bits = dirPathWithoutSlash.split("\\"+DOT, 2);
+			dirPathWithoutRunmodes = bits[0];
+			List<String> runmodesOfResource = Arrays.asList(bits[1].split("\\"+DOT));
+			Set<String> matchingRunmodes = new HashSet<String>(runmodesOfResource);
+			matchingRunmodes.retainAll(actualRunmodes);
+			LOG.debug("Entry with runmode(s): entryPath={} runmodesOfResource={} actualRunmodes={} matchingRunmodes={}", entryPath, runmodesOfResource, actualRunmodes, matchingRunmodes);
+			runmodesMatch = matchingRunmodes.size() == runmodesOfResource.size();
+			if (!runmodesMatch) {
+				logger.log("Skipping installation of  " + entryPath
+						+ " because the path is not matching all actual runmodes " + actualRunmodes);
 			}
+		} else {
+			dirPathWithoutRunmodes = dirPathWithoutSlash;
+			runmodesMatch = true;
 		}
 
-		if (entryName.endsWith(CONFIG_SUFFIX) && dirPath.contains("/config")) {
-			String configPath = StringUtils.substringAfter(dirPath + entryName, "/jcr_root");
-			configResources.add(configPath);
+		if (dirPathWithoutRunmodes.matches(installPathRegex) && runmodesMatch) {
+
+			if (entryName.endsWith(CONFIG_SUFFIX)) {
+				configResources.add(entryPath);
+			} else if (entryName.endsWith(JAR_SUFFIX)) {
+				try (InputStream entryInputStream = archive.getInputSource(entry).getByteStream();
+						JarInputStream jarInputStream = new JarInputStream(entryInputStream)) {
+					Manifest manifest = jarInputStream.getManifest();
+					String symbolicName = manifest.getMainAttributes().getValue(MANIFEST_BUNDLE_SYMBOLIC_NAME);
+					String version = manifest.getMainAttributes().getValue(MANIFEST_BUNDLE_VERSION);
+
+					bundleResources.add(new BundleInPackage(entryPath, symbolicName, version));
+				} catch (Exception e) {
+					throw new IllegalStateException(
+							"Could not read symbolic name and version from manifest of bundle " + entryName);
+				}
+			}
+
 		}
 
 		for (Entry child : entry.getChildren()) {
-			collectResources(archive, child, dirPath + entryName + "/", bundleResources, configResources);
+			collectResources(archive, child, dirPath + entryName + "/", bundleResources, configResources,
+					installPathRegex, actualRunmodes);
 		}
 	}
 
@@ -282,7 +340,7 @@ public class OsgiInstallerHook implements InstallHook {
 		final InputStream is = node.getProperty(JCR_CONTENT_DATA).getStream();
 		final Dictionary<String, Object> dict = new Hashtable<String, Object>();
 		dict.put(InstallableResource.INSTALLATION_HINT, node.getParent().getName());
-		return new InstallableResource(path, is, dict, digest, null, null);
+		return new InstallableResource(path, is, dict, digest, null, PRIORITY_INSTALL_HOOK);
 	}
 
 	// always get fresh bundle context to avoid "Dynamic class loader has already
@@ -294,7 +352,6 @@ public class OsgiInstallerHook implements InstallHook {
 			throw new IllegalStateException(
 					"The class " + InstallHook.class + " was not loaded through a bundle classloader");
 		}
-
 		BundleContext bundleContext = currentBundle.getBundleContext();
 		if (bundleContext == null) {
 			throw new IllegalStateException("Could not get bundle context for bundle " + currentBundle);