OakMachine { void processInstallableQueue(final @NotNull Session admin, final @NotNull JcrPackageManager manager, final @NotNull PackageId lastPackageId, final boolean preInstall) throws RepositoryException { final Session inspectSession = Util.wrapSessionReadOnly(admin); SlingInstallable dequeued = slingSimulator.dequeueInstallable(); while (dequeued != null) { final SlingInstallable installable = dequeued; propagateCheckPackageEvent(preInstall, installable.getParentId(), check -> check.beforeSlingInstall(lastPackageId, installable, inspectSession)); Optional<SlingRepoInitScripts> initScriptsResult = Optional.ofNullable(SlingRepoInitScripts.fromSlingInstallable(installable)); initScriptsResult.ifPresent(initScripts -> { for (final String repoInitScript : initScripts.getScripts()) { try (Reader reader = new StringReader(repoInitScript)) { repoInitProcessor.apply(admin, reader); admin.save(); } catch (final Exception e) { getErrorListener().onSlingRepoInitScriptsError(e, initScripts.getScripts(), repoInitScript, installable); Fun.<Session>uncheckVoid1(session -> session.refresh(false)).accept(admin); } } propagateCheckPackageEvent(preInstall, installable.getParentId(), check -> check.appliedRepoInitScripts(lastPackageId, initScripts.getScripts(), installable, inspectSession)); }); if (installable instanceof EmbeddedPackageInstallable) { processEmbeddedPackage(admin, manager, (EmbeddedPackageInstallable) installable, preInstall); } dequeued = slingSimulator.dequeueInstallable(); } } private  OakMachine(final Packaging packagingService,
                       final List<ProgressCheck> progressChecks,
                       final ErrorListener errorListener,
                       final List<URL> preInstallUrls,
                       final List<InitStage> initStages,
                       final JcrCustomizer jcrCustomizer,
                       final InstallHookProcessorFactory installHookProcessorFactory,
                       final ClassLoader installHookClassLoader,
                       final boolean enablePreInstallHooks,
                       final InstallHookPolicy scanInstallHookPolicy,
                       final Supplier<NodeStore> nodeStoreSupplier,
                       final SubpackageSilencer subpackageSilencer,
                       final RepoInitProcessor repoInitProcessor,
                       final SlingSimulatorBackend slingSimulator,
                       final Set<String> runModes); List<ProgressCheck> getProgressChecks(); ErrorListener getErrorListener(); @Deprecated List<File> getPreInstallFiles(); List<URL> getPreInstallUrls(); @SuppressWarnings("WeakerAccess") void initAndInspect(final InspectBody<E> inspectBody); void adminInitAndInspect(final InspectBody<E> inspectBody); List<CheckReport> scanPackage(final @NotNull File... file); List<CheckReport> scanPackages(final List<File> files); static Packaging newOakpalPackagingService(); static Packaging newOakpalPackagingService(final @NotNull ClassLoader classLoader); static final String NS_URI_OAKPAL; static final String NS_PREFIX_OAKPAL; static final String LN_UNDECLARED; static final String NT_UNDECLARED; }
@Test public void testProcessInstallableQueue_noop() throws Exception { final JcrPackageManager manager = mock(JcrPackageManager.class); final Session session = mock(Session.class); final PackageId root = PackageId.fromString("my_packages:subsubtest"); new OakMachine.Builder().build().processInstallableQueue(session, manager, root, false); }
@Test public void testProcessInstallableQueue_singleSubpackageInstallable() throws Exception { final JcrPackageManager manager = mock(JcrPackageManager.class); final Session session = mock(Session.class); final PackageId root = PackageId.fromString("my_packages:subsubtest"); final PackageId sub1 = PackageId.fromString("my_packages:subtest"); final String jcrPath = "/some/path"; final EmbeddedPackageInstallable installable = new EmbeddedPackageInstallable(root, jcrPath, sub1); final List<EmbeddedPackageInstallable> installables = new ArrayList<>(); installables.add(installable); final SlingSimulatorBackend installWatcher = mock(SlingSimulatorBackend.class); final List<Optional<EmbeddedPackageInstallable>> dequeuedValues = new ArrayList<>(); doAnswer(call -> { if (installables.isEmpty()) { dequeuedValues.add(Optional.empty()); return null; } else { EmbeddedPackageInstallable toReturn = installables.remove(0); dequeuedValues.add(Optional.ofNullable(toReturn)); return toReturn; } }).when(installWatcher).dequeueInstallable(); final JcrPackage jcrPackage = mock(JcrPackage.class); final CompletableFuture<EmbeddedPackageInstallable> openedSlot = new CompletableFuture<>(); doAnswer(call -> { openedSlot.complete(call.getArgument(0)); return (Fun.ThrowingSupplier<JcrPackage>) () -> jcrPackage; }).when(installWatcher).open(installable); new OakMachine.Builder() .withSlingSimulator(installWatcher) .build().processInstallableQueue(session, manager, root, false); assertEquals("expect dequeued values", Arrays.asList(Optional.of(installable), Optional.empty()), dequeuedValues); assertSame("expect request to open installable", installable, openedSlot.getNow(null)); }
@Test public void testProcessInstallableQueue_singleRepoInitInstallable() throws Exception { final String expectScript = "create user testProcessInstallableQueue_singleRepoInitInstallable"; final JcrPackageManager manager = mock(JcrPackageManager.class); final Session session = mock(Session.class); final PackageId root = PackageId.fromString("my_packages:subsubtest"); final OsgiConfigInstallable installable = new OsgiConfigInstallable( root, "/repoInit", Collections.singletonMap(SlingRepoInitScripts.CONFIG_SCRIPTS, Collections.singletonList(expectScript)), "init", SlingRepoInitScripts.REPO_INIT_FACTORY_PID); final List<OsgiConfigInstallable> installables = new ArrayList<>(); installables.add(installable); final SlingSimulatorBackend installWatcher = mock(SlingSimulatorBackend.class); final List<Optional<OsgiConfigInstallable>> dequeuedValues = new ArrayList<>(); doAnswer(call -> { if (installables.isEmpty()) { dequeuedValues.add(Optional.empty()); return null; } else { OsgiConfigInstallable toReturn = installables.remove(0); dequeuedValues.add(Optional.ofNullable(toReturn)); return toReturn; } }).when(installWatcher).dequeueInstallable(); final CompletableFuture<Reader> readerSlot = new CompletableFuture<>(); final OakMachine.RepoInitProcessor repoInitProcessor = (Session sess, Reader read) -> { readerSlot.complete(read); }; final ProgressCheck check = mock(ProgressCheck.class); final CompletableFuture<PackageId> packIdLatch = new CompletableFuture<>(); final CompletableFuture<List> scriptsLatch = new CompletableFuture<>(); final CompletableFuture<SlingInstallable> installableLatch = new CompletableFuture<>(); final CompletableFuture<Session> sessionLatch = new CompletableFuture<>(); final ErrorListener errorListener = mock(ErrorListener.class); doAnswer(call -> { packIdLatch.complete(call.getArgument(0, PackageId.class)); scriptsLatch.complete(call.getArgument(1, List.class)); installableLatch.complete(call.getArgument(2, SlingInstallable.class)); sessionLatch.complete(call.getArgument(3, Session.class)); return true; }).when(check).appliedRepoInitScripts(any(PackageId.class), any(List.class), any(SlingInstallable.class), any(Session.class)); new OakMachine.Builder() .withErrorListener(errorListener) .withRepoInitProcesser(repoInitProcessor) .withSlingSimulator(installWatcher) .withProgressCheck(check) .build().processInstallableQueue(session, manager, root, false); assertEquals("expect dequeued values", Arrays.asList(Optional.of(installable), Optional.empty()), dequeuedValues); assertTrue("expect reader is complete", readerSlot.isDone()); assertSame("packageId is", root, packIdLatch.getNow(null)); assertEquals("scripts is", Collections.singletonList(expectScript), scriptsLatch.getNow(null)); assertSame("expect same installable", installable, installableLatch.getNow(null)); final Session inspectSession = sessionLatch.getNow(null); assertNotNull("expect non-null inspectSession", inspectSession); assertNotSame("expect same session", session, inspectSession); }
@Test public void testProcessInstallableQueue_singleRepoInitInstallable_fails() throws Exception { final String expectScript = "create user testProcessInstallableQueue_singleRepoInitInstallable"; final JcrPackageManager manager = mock(JcrPackageManager.class); final Session session = mock(Session.class); final PackageId root = PackageId.fromString("my_packages:subsubtest"); final OsgiConfigInstallable installable = new OsgiConfigInstallable( root, "/repoInit", Collections.singletonMap(SlingRepoInitScripts.CONFIG_SCRIPTS, Collections.singletonList(expectScript)), "init", SlingRepoInitScripts.REPO_INIT_FACTORY_PID); final List<OsgiConfigInstallable> installables = new ArrayList<>(); installables.add(installable); final SlingSimulatorBackend installWatcher = mock(SlingSimulatorBackend.class); final List<Optional<OsgiConfigInstallable>> dequeuedValues = new ArrayList<>(); doAnswer(call -> { if (installables.isEmpty()) { dequeuedValues.add(Optional.empty()); return null; } else { OsgiConfigInstallable toReturn = installables.remove(0); dequeuedValues.add(Optional.ofNullable(toReturn)); return toReturn; } }).when(installWatcher).dequeueInstallable(); final CompletableFuture<Reader> readerSlot = new CompletableFuture<>(); final OakMachine.RepoInitProcessor repoInitProcessor = (Session sess, Reader read) -> { readerSlot.complete(read); throw new NullPointerException("for some reason"); }; final CompletableFuture<Throwable> eLatch = new CompletableFuture<>(); final CompletableFuture<List> scriptsLatch = new CompletableFuture<>(); final CompletableFuture<String> scriptLatch = new CompletableFuture<>(); final CompletableFuture<SlingInstallable> installableLatch = new CompletableFuture<>(); final ErrorListener errorListener = mock(ErrorListener.class); doAnswer(call -> { eLatch.complete(call.getArgument(0, Throwable.class)); scriptsLatch.complete(call.getArgument(1, List.class)); scriptLatch.complete(call.getArgument(2, String.class)); installableLatch.complete(call.getArgument(3, SlingInstallable.class)); return true; }).when(errorListener).onSlingRepoInitScriptsError(any(Throwable.class), nullable(List.class), nullable(String.class), any(SlingInstallable.class)); new OakMachine.Builder() .withErrorListener(errorListener) .withRepoInitProcesser(repoInitProcessor) .withSlingSimulator(installWatcher) .build().processInstallableQueue(session, manager, root, false); assertEquals("expect dequeued values", Arrays.asList(Optional.of(installable), Optional.empty()), dequeuedValues); assertTrue("expect reader is complete", readerSlot.isDone()); assertTrue("error is of type", eLatch.getNow(null) instanceof NullPointerException); assertEquals("scripts is", Collections.singletonList(expectScript), scriptsLatch.getNow(null)); assertEquals("failedScript is", expectScript, scriptLatch.getNow(null)); assertSame("expect same installable in error", installable, installableLatch.getNow(null)); }