diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/BaseAceBeanInstaller.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/BaseAceBeanInstaller.java index d39d629d8..47e445ba1 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/BaseAceBeanInstaller.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/BaseAceBeanInstaller.java @@ -111,8 +111,8 @@ public void installPathBasedACEs( private Set filterReadOnlyPaths(Set paths, InstallationLogger history, Session session) { - boolean isCompositeNodeStore = RuntimeHelper.isCompositeNodeStore(session); - if (isCompositeNodeStore) { + boolean isAppsReadOnly = RuntimeHelper.isAppsReadOnly(session); + if (isAppsReadOnly) { Set pathsToKeep = new TreeSet(); Set readOnlyPaths = new TreeSet(); for (final String path : paths) { diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/runtime/RuntimeHelper.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/runtime/RuntimeHelper.java index aec9ef859..feb262a2b 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/runtime/RuntimeHelper.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/runtime/RuntimeHelper.java @@ -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"; @@ -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); } @@ -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(); diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/HistoryUtils.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/HistoryUtils.java index 2febe078e..dbfc22d25 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/HistoryUtils.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/HistoryUtils.java @@ -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"; diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcConfigChangeTracker.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcConfigChangeTracker.java index 7700a11c7..50d03fba7 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcConfigChangeTracker.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcConfigChangeTracker.java @@ -66,10 +66,10 @@ public boolean configIsUnchangedComparedToLastExecution(Map conf } private String createExecutionKey(Map 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; } diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java index 288e5f78a..74eaed0cd 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java @@ -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; diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/slingsettings/ExtendedSlingSettingsServiceImpl.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/slingsettings/ExtendedSlingSettingsServiceImpl.java index 448e1a573..136439b05 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/slingsettings/ExtendedSlingSettingsServiceImpl.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/slingsettings/ExtendedSlingSettingsServiceImpl.java @@ -80,8 +80,8 @@ public void activate(Config config) { Set 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); } @@ -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 diff --git a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/helper/runtime/RuntimeHelperTest.java b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/helper/runtime/RuntimeHelperTest.java new file mode 100644 index 000000000..fe79438b6 --- /dev/null +++ b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/helper/runtime/RuntimeHelperTest.java @@ -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 mockedFrameworkUtil = mockStatic(FrameworkUtil.class)) { + setupOsgi(RuntimeHelper.INSTALLER_CORE_BUNDLE_SYMBOLIC_ID, mockedFrameworkUtil); + assertFalse(RuntimeHelper.isCompositeNodeStore()); + } + } + + @Test + void shouldBeCompositeStoreWhenCoreInstallerNotPresent() { + try (MockedStatic mockedFrameworkUtil = mockStatic(FrameworkUtil.class)) { + setupOsgi("unknown.bundle", mockedFrameworkUtil); + assertTrue(RuntimeHelper.isCompositeNodeStore()); + } + } + + private void setupOsgi(String t, MockedStatic 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); + } +} \ No newline at end of file diff --git a/accesscontroltool-startuphook-bundle/pom.xml b/accesscontroltool-startuphook-bundle/pom.xml index de3b9b064..029e39c38 100644 --- a/accesscontroltool-startuphook-bundle/pom.xml +++ b/accesscontroltool-startuphook-bundle/pom.xml @@ -61,6 +61,27 @@ javax.servlet-api provided + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + diff --git a/accesscontroltool-startuphook-bundle/src/main/java/biz/netcentric/cq/tools/actool/startuphook/impl/AcToolStartupHookServiceImpl.java b/accesscontroltool-startuphook-bundle/src/main/java/biz/netcentric/cq/tools/actool/startuphook/impl/AcToolStartupHookServiceImpl.java index 35a32dad5..fa1a0e18a 100644 --- a/accesscontroltool-startuphook-bundle/src/main/java/biz/netcentric/cq/tools/actool/startuphook/impl/AcToolStartupHookServiceImpl.java +++ b/accesscontroltool-startuphook-bundle/src/main/java/biz/netcentric/cq/tools/actool/startuphook/impl/AcToolStartupHookServiceImpl.java @@ -62,28 +62,28 @@ 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) { @@ -91,16 +91,16 @@ public void activate(BundleContext bundleContext, Config config) { 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); } } @@ -118,12 +118,7 @@ private void runAcTool(List relevantPathsForInstallation, int currentSta private void runAcToolAsync(final List 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 getRelevantPathsForInstallation() { @@ -131,10 +126,10 @@ private List getRelevantPathsForInstallation() { 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(); } @@ -149,7 +144,7 @@ private List 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()); @@ -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)) { diff --git a/accesscontroltool-startuphook-bundle/src/test/java/biz/netcentric/cq/tools/actool/startuphook/impl/AcToolStartupHookServiceImplTest.java b/accesscontroltool-startuphook-bundle/src/test/java/biz/netcentric/cq/tools/actool/startuphook/impl/AcToolStartupHookServiceImplTest.java new file mode 100644 index 000000000..d90ca41ef --- /dev/null +++ b/accesscontroltool-startuphook-bundle/src/test/java/biz/netcentric/cq/tools/actool/startuphook/impl/AcToolStartupHookServiceImplTest.java @@ -0,0 +1,143 @@ +package biz.netcentric.cq.tools.actool.startuphook.impl; + +/*- + * #%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 biz.netcentric.cq.tools.actool.api.AcInstallationService; +import biz.netcentric.cq.tools.actool.helper.runtime.RuntimeHelper; +import org.apache.sling.jcr.api.SlingRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.startlevel.FrameworkStartLevel; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class AcToolStartupHookServiceImplTest { + + @Mock + Bundle bundle; + + @Mock + BundleContext bundleContext; + + @Mock + AcToolStartupHookServiceImpl.Config config; + + @Mock + Session session; + + @Mock + SlingRepository repository; + + @Mock + Node rootNode; + + @Mock + NodeIterator noChildren; + + @Spy + AcInstallationService installationService; + + @Test + void testActivationWithModifiableRoot() throws RepositoryException { + boolean canSetPropertiesOnRootNode = true, runAsync = false, cloudOnly = false; + setup(canSetPropertiesOnRootNode, runAsync, cloudOnly); + try (MockedStatic mockedFrameworkUtil = mockStatic(FrameworkUtil.class)) { + createAndActivateStartupHookService(mockedFrameworkUtil); + verify(installationService, times(1)).apply(null, new String[]{"^/$", "^$"}, true); + } + } + + @Test + void testActivationWithUnmodifiableRoot() throws RepositoryException { + boolean canSetPropertiesOnRootNode = false, runAsync = false, cloudOnly = false; + setup(canSetPropertiesOnRootNode, runAsync, cloudOnly); + try (MockedStatic mockedFrameworkUtil = mockStatic(FrameworkUtil.class)) { + createAndActivateStartupHookService(mockedFrameworkUtil); + verify(installationService, times(1)).apply(null, new String[]{}, true); + } + } + + @Test + void testActivationWithCloudOnly() throws RepositoryException { + boolean canSetPropertiesOnRootNode = false, runAsync = false, cloudOnly = true; + setup(canSetPropertiesOnRootNode, runAsync, cloudOnly); + try (MockedStatic mockedFrameworkUtil = mockStatic(FrameworkUtil.class)) { + createAndActivateStartupHookService(mockedFrameworkUtil); + verify(installationService, never()).apply(null, new String[]{"^/$", "^$"}, true); + } + } + + @Test + void testActivationWithAsync() throws RepositoryException, InterruptedException { + boolean canSetPropertiesOnRootNode = true, runAsync = true, cloudOnly = false; + setup(canSetPropertiesOnRootNode, runAsync, cloudOnly); + try (MockedStatic mockedFrameworkUtil = mockStatic(FrameworkUtil.class)) { + createAndActivateStartupHookService(mockedFrameworkUtil); + // best attempt to test asynchronous invocation in AcToolStartupHookServiceImpl#runAcToolAsync + Thread.sleep(1000L); + verify(installationService, times(1)).apply(null, new String[]{"^/$", "^$"}, true); + } + } + + void setup(boolean canSetPropertiesOnRootNode, boolean runAsyncForMutableContent, boolean cloudOnly) throws RepositoryException { + FrameworkStartLevel startLevel = Mockito.mock(FrameworkStartLevel.class); + when(startLevel.getStartLevel()).thenReturn(0); + + if (canSetPropertiesOnRootNode) { + when(session.hasPermission("/", Session.ACTION_SET_PROPERTY)).thenReturn(true); + when(noChildren.hasNext()).thenReturn(false); + when(rootNode.getNodes()).thenReturn(noChildren); + when(session.getRootNode()).thenReturn(rootNode); + } else if (!cloudOnly) { + when(session.hasPermission("/", Session.ACTION_SET_PROPERTY)).thenReturn(false); + } + if (!cloudOnly) { + when(repository.loginService(null, null)).thenReturn(session); + } + + when(bundle.getBundleContext()).thenReturn(bundleContext); + when(bundle.getSymbolicName()).thenReturn(RuntimeHelper.INSTALLER_CORE_BUNDLE_SYMBOLIC_ID); + when(bundle.adapt(FrameworkStartLevel.class)).thenReturn(startLevel); + + when(bundleContext.getBundles()).thenReturn(new Bundle[]{bundle}); + when(bundleContext.getBundle(anyLong())).thenReturn(bundle); + + when(config.runAsyncForMutableConent()).thenReturn(runAsyncForMutableContent); + when(config.activationMode()).thenReturn(cloudOnly ? + AcToolStartupHookServiceImpl.Config.StartupHookActivation.CLOUD_ONLY : + AcToolStartupHookServiceImpl.Config.StartupHookActivation.ALWAYS); + } + + private void createAndActivateStartupHookService(MockedStatic mockedFrameworkUtil) { + mockedFrameworkUtil.when(() -> FrameworkUtil.getBundle(RuntimeHelper.class)).thenReturn(bundle); + AcToolStartupHookServiceImpl startupHookService = new AcToolStartupHookServiceImpl(); + startupHookService.repository = repository; + startupHookService.acInstallationService = installationService; + startupHookService.activate(bundleContext, config); + } +} \ No newline at end of file diff --git a/accesscontroltool-startuphook-bundle/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/accesscontroltool-startuphook-bundle/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 000000000..1f0955d45 --- /dev/null +++ b/accesscontroltool-startuphook-bundle/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline diff --git a/pom.xml b/pom.xml index c6c9f62e2..d4fddaa4c 100644 --- a/pom.xml +++ b/pom.xml @@ -87,7 +87,7 @@ 1.64 8 - 4.8.0 + 5.13.0 5.10.0 ${project.build.directory}/${project.build.finalName}.zip