Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename RuntimeHelper methods to match their implementations closer #767

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ public void installPathBasedACEs(

private Set<String> filterReadOnlyPaths(Set<String> paths, InstallationLogger history, Session session) {

boolean isCompositeNodeStore = RuntimeHelper.isCompositeNodeStore(session);
if (isCompositeNodeStore) {
boolean isAppsReadOnly = RuntimeHelper.isAppsReadOnly(session);
if (isAppsReadOnly) {
Set<String> pathsToKeep = new TreeSet<String>();
Set<String> readOnlyPaths = new TreeSet<String>();
for (final String path : paths) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
public class RuntimeHelper {
public static final Logger LOG = LoggerFactory.getLogger(RuntimeHelper.class);

private static final String INSTALLER_CORE_BUNDLE_SYMBOLIC_ID = "org.apache.sling.installer.core";
public static final String INSTALLER_CORE_BUNDLE_SYMBOLIC_ID = "org.apache.sling.installer.core";

public static boolean isCompositeNodeStore(Session session) {
public static boolean isAppsReadOnly(Session session) {

try {
String pathToCheck = "/apps";
Expand All @@ -45,8 +45,8 @@ public static boolean isCompositeNodeStore(Session session) {
// see https://issues.apache.org/jira/browse/OAK-6563
boolean hasCapability = session.hasCapability("addNode", appsNode, new Object[] { "nt:folder" });

boolean isCompositeNode = hasPermission && !hasCapability;
return isCompositeNode;
boolean isAppsReadOnly = hasPermission && !hasCapability;
return isAppsReadOnly;
} catch(Exception e) {
throw new IllegalStateException("Could not check if session is connected to a composite node store: "+e, e);
}
Expand All @@ -60,7 +60,7 @@ public static int getCurrentStartLevel(BundleContext bundleContext) {
return bundleContext.getBundle(Constants.SYSTEM_BUNDLE_ID).adapt(FrameworkStartLevel.class).getStartLevel();
}

public static boolean isCloudReadyInstance() {
public static boolean isCompositeNodeStore() {

boolean isCloudReadyInstance = true;
Bundle[] bundles = FrameworkUtil.getBundle(RuntimeHelper.class).getBundleContext().getBundles();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ public static Node persistHistory(final Session session,
trigger = "startup_hook_pckmgr)";
} else {
// if the history is not yet copied to apps, it's the image build
boolean isImageBuild = RuntimeHelper.isCloudReadyInstance() && !session.itemExists(AC_HISTORY_PATH_IN_APPS);
if(isImageBuild) {
boolean isCompositeNodeStore = RuntimeHelper.isCompositeNodeStore() && !session.itemExists(AC_HISTORY_PATH_IN_APPS);
if(isCompositeNodeStore) {
trigger = "startup_hook_image_build";
} else {
trigger = "startup_hook";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ public boolean configIsUnchangedComparedToLastExecution(Map<String, String> conf
}

private String createExecutionKey(Map<String, String> configFiles, String[] restrictedToPaths, Session session) {
boolean isCompositeNodeStore= RuntimeHelper.isCompositeNodeStore(session);
boolean isAppsReadOnly= RuntimeHelper.isAppsReadOnly(session);
String restrictedToPathsKey = restrictedToPaths==null || restrictedToPaths.length==0 ? "ALL_PATHS" : StringUtils.join(restrictedToPaths, "+").replace("$", "").replace("^", "");
String effectiveRootPathOfConfigs = getEffectiveConfigRootPath(configFiles);
String executionKey = "hash("+StringUtils.removeEnd(effectiveRootPathOfConfigs, "/").replace('/', '\\') + "," + restrictedToPathsKey.replace('/', '\\').replace(':', '_')+","+(isCompositeNodeStore?"compNodeStore":"stdRepo")+")";
String executionKey = "hash("+StringUtils.removeEnd(effectiveRootPathOfConfigs, "/").replace('/', '\\') + "," + restrictedToPathsKey.replace('/', '\\').replace(':', '_')+","+(isAppsReadOnly?"compNodeStore":"stdRepo")+")";
return executionKey;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ private void install(InstallContext context) throws PackageException {
}
alreadyRan = true;

if (RuntimeHelper.isCloudReadyInstance()) {
if (RuntimeHelper.isCompositeNodeStore()) {
log("InstallHook is skipped by default in cloud (use package property 'actool.forceInstallHookInCloud = true' to force run)",
listener);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ public void activate(Config config) {
Set<String> defaultRunmodes = slingSettingsService.getRunModes();
extendedRunmodes = new HashSet<>();
extendedRunmodes.addAll(defaultRunmodes);
boolean isCloudReady = RuntimeHelper.isCloudReadyInstance();
if(isCloudReady) {
boolean isCompositeNodeStore = RuntimeHelper.isCompositeNodeStore();
if(isCompositeNodeStore) {
extendedRunmodes.add(ADDITIONAL_RUNMODE_CLOUD);
}

Expand All @@ -90,7 +90,7 @@ public void activate(Config config) {
extendedRunmodes.addAll(additionalRunmodes);
}

LOG.info("Default runmodes: {} Extended Runmodes: {} isCloudReady: {}", defaultRunmodes, extendedRunmodes, isCloudReady);
LOG.info("Default runmodes: {} Extended Runmodes: {} isCompositeNodeStore: {}", defaultRunmodes, extendedRunmodes, isCompositeNodeStore);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package biz.netcentric.cq.tools.actool.helper.runtime;

/*-
* #%L
* Access Control Tool Bundle
* %%
* Copyright (C) 2015 - 2024 Cognizant Netcentric
* %%
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* #L%
*/

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;

import javax.jcr.RepositoryException;
import javax.jcr.Session;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class RuntimeHelperTest {

@Mock
Session session;

@Mock
Bundle bundle;

@Mock
BundleContext bundleContext;

@Test
void shouldBeReadonlyIfRootWritable() throws RepositoryException {
when(session.hasPermission("/", Session.ACTION_SET_PROPERTY)).thenReturn(true);
assertTrue(RuntimeHelper.isAppsReadOnly(session));
}

@Test
void shouldNotBeReadonlyIfRootNotWritable() throws RepositoryException {
when(session.hasPermission("/", Session.ACTION_SET_PROPERTY)).thenReturn(false);
assertFalse(RuntimeHelper.isAppsReadOnly(session));
}

@Test
void shouldNotBeCompositeStoreWhenCoreInstallerPresent() {
try (MockedStatic<FrameworkUtil> mockedFrameworkUtil = mockStatic(FrameworkUtil.class)) {
setupOsgi(RuntimeHelper.INSTALLER_CORE_BUNDLE_SYMBOLIC_ID, mockedFrameworkUtil);
assertFalse(RuntimeHelper.isCompositeNodeStore());
}
}

@Test
void shouldBeCompositeStoreWhenCoreInstallerNotPresent() {
try (MockedStatic<FrameworkUtil> mockedFrameworkUtil = mockStatic(FrameworkUtil.class)) {
setupOsgi("unknown.bundle", mockedFrameworkUtil);
assertTrue(RuntimeHelper.isCompositeNodeStore());
}
}

private void setupOsgi(String t, MockedStatic<FrameworkUtil> mockedFrameworkUtil) {
when(bundle.getBundleContext()).thenReturn(bundleContext);
when(bundle.getSymbolicName()).thenReturn(t);
when(bundleContext.getBundles()).thenReturn(new Bundle[]{bundle});
mockedFrameworkUtil.when(() -> FrameworkUtil.getBundle(RuntimeHelper.class)).thenReturn(bundle);
}
}
21 changes: 21 additions & 0 deletions accesscontroltool-startuphook-bundle/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,27 @@
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- START: Test Dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!-- use the uber-jar always as last dependency because a lot of classes are provided also by other artifacts
It is only used here as replacement for com.adobe.granite:com.adobe.granite.crypto:3.0.0 whose pom.xml is not publicly available -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,45 +62,45 @@ public enum StartupHookActivation {
}

@Reference(policyOption = ReferencePolicyOption.GREEDY)
private AcInstallationService acInstallationService;
AcInstallationService acInstallationService;

@Reference(policyOption = ReferencePolicyOption.GREEDY)
private SlingRepository repository;
SlingRepository repository;

private boolean isCompositeNodeStore;
private boolean isAppsReadOnly;

@Activate
public void activate(BundleContext bundleContext, Config config) {

boolean isCloudReady = RuntimeHelper.isCloudReadyInstance();
boolean isCompositeNodeStore = RuntimeHelper.isCompositeNodeStore();
Config.StartupHookActivation activationMode = config.activationMode();
boolean runAsyncForMutableConent = config.runAsyncForMutableConent();
int currentStartLevel = RuntimeHelper.getCurrentStartLevel(bundleContext);
LOG.info("AcTool Startup Hook (start level: {} isCloudReady: {} activationMode: {} runAsyncForMutableConent: {})",
LOG.info("AcTool Startup Hook (start level: {} isCompositeNodeStore: {} activationMode: {} runAsyncForMutableConent: {})",
currentStartLevel,
isCloudReady,
isCompositeNodeStore,
activationMode,
runAsyncForMutableConent);

boolean applyOnStartup = (activationMode == Config.StartupHookActivation.ALWAYS)
|| (isCloudReady && activationMode == Config.StartupHookActivation.CLOUD_ONLY);
|| (isCompositeNodeStore && activationMode == Config.StartupHookActivation.CLOUD_ONLY);

if (applyOnStartup) {

List<String> relevantPathsForInstallation = getRelevantPathsForInstallation();
LOG.info("Running AcTool with "
+ (relevantPathsForInstallation.isEmpty() ? "all paths" : "paths " + relevantPathsForInstallation) + "...");

if (runAsyncForMutableConent && isCompositeNodeStore) {
if (runAsyncForMutableConent && isAppsReadOnly) {
LOG.info(
"Running AcTool asynchronously on mutable content of composite node store (config runAsyncForMutableConent=true)...");
runAcToolAsync(relevantPathsForInstallation, currentStartLevel, isCloudReady);
runAcToolAsync(relevantPathsForInstallation, currentStartLevel, isCompositeNodeStore);
} else {
runAcTool(relevantPathsForInstallation, currentStartLevel, isCloudReady);
runAcTool(relevantPathsForInstallation, currentStartLevel, isCompositeNodeStore);
}

} else {
LOG.debug("Skipping AcTool Startup Hook: activationMode: {} isCloudReady: {}", activationMode, isCloudReady);
LOG.debug("Skipping AcTool Startup Hook: activationMode: {} isCompositeNodeStore: {}", activationMode, isCompositeNodeStore);
}

}
Expand All @@ -118,23 +118,18 @@ private void runAcTool(List<String> relevantPathsForInstallation, int currentSta
private void runAcToolAsync(final List<String> relevantPathsForInstallation, final int currentStartLevel, final boolean isCloudReady) {

final AcToolStartupHookServiceImpl startupHook = this;
new Thread(new Runnable() {
@Override
public void run() {
startupHook.runAcTool(relevantPathsForInstallation, currentStartLevel, isCloudReady);
}
}, THREAD_NAME_ASYNC).start();
new Thread(() -> startupHook.runAcTool(relevantPathsForInstallation, currentStartLevel, isCloudReady), THREAD_NAME_ASYNC).start();
}

private List<String> getRelevantPathsForInstallation() {
Session session = null;
try {
session = repository.loginService(null, null);

isCompositeNodeStore = RuntimeHelper.isCompositeNodeStore(session);
LOG.info("Repo is running with Composite NodeStore: {}", isCompositeNodeStore);
isAppsReadOnly = RuntimeHelper.isAppsReadOnly(session);
LOG.info("Repo is running with Composite NodeStore: {}", isAppsReadOnly);

if(!isCompositeNodeStore) {
if(!isAppsReadOnly) {
return Collections.emptyList();
}

Expand All @@ -149,7 +144,7 @@ private List<String> getRelevantPathsForInstallation() {
AccessControlConstants.REP_REPO_POLICY).contains(node.getName())) {
continue;
}
if (isCompositeNodeStore && Arrays.asList("apps", "libs").contains(node.getName())) {
if (isAppsReadOnly && Arrays.asList("apps", "libs").contains(node.getName())) {
continue;
}
relevantPathsForInstallation.add(node.getPath());
Expand Down Expand Up @@ -179,7 +174,7 @@ private void copyAcHistoryToOrFromApps(boolean isCloudReady) {
try {
session = repository.loginService(null, null);

if(isCompositeNodeStore) {
if(isAppsReadOnly) {
LOG.info("Restoring history from /apps to /var");

if(session.nodeExists(HistoryUtils.AC_HISTORY_PATH_IN_APPS)) {
Expand Down
Loading
Loading