OakMachine { public List<CheckReport> scanPackage(final @NotNull File... file) throws AbortedScanException { return scanPackages(Arrays.asList(file)); } 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 testReadManifest() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("null-dependency-test.zip"); final CompletableFuture<Boolean> manifestWasRead = new CompletableFuture<>(); ProgressCheck check = new SimpleProgressCheck() { @Override public void readManifest(final PackageId packageId, final Manifest manifest) { manifestWasRead.complete(Util.getManifestHeaderValues(manifest, "Content-Package-Id") .contains("my_packages:null-dependency-test")); } }; builder().withProgressChecks(check).withProgressChecks((ProgressCheck[]) null).build().scanPackage(testPackage); assertTrue("manifest was read, and produced correct value for Content-Package-Id", manifestWasRead.isDone() && manifestWasRead.get()); }
@Test public void testBuildWithPackagingService() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("null-dependency-test.zip"); assertTrue("no errors", builder().withPackagingService(new PackagingImpl()).build() .scanPackage(testPackage).get(0).getViolations().isEmpty()); }
@Test public void testBuildWithInstallWatcher() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("null-dependency-test.zip"); final SlingSimulatorBackend watcher = mock(SlingSimulatorBackend.class); assertTrue("no errors", builder().withSlingSimulator(watcher).build() .scanPackage(testPackage).get(0).getViolations().isEmpty()); }
@Test public void testBuildWithInstallClassLoaderAndScan() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final ClassLoader hookClassLoader = new URLClassLoader(new URL[]{testPackage.toURI().toURL()}, null); final CompletableFuture<Boolean> latch = new CompletableFuture<>(); final InstallHookProcessor processor = mock(InstallHookProcessor.class); when(processor.execute(any(InstallContext.class))).thenReturn(true); doAnswer(call -> latch.complete(hookClassLoader == call.getArgument(1, ClassLoader.class))) .when(processor) .registerHooks(any(Archive.class), any(ClassLoader.class)); builder().withInstallHookProcessorFactory(() -> processor) .withInstallHookClassLoader(hookClassLoader) .build().scanPackage(testPackage); }
@Test(expected = AbortedScanException.class) public void testBuildAndScanWithInstallHookPolicyAbort() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final InstallHookProcessor processor = mock(InstallHookProcessor.class); doThrow(new PackageException("abort")).when(processor) .registerHooks(any(Archive.class), any(ClassLoader.class)); builder().withInstallHookProcessorFactory(() -> processor) .withInstallHookPolicy(InstallHookPolicy.ABORT) .build().scanPackage(testPackage); }
@Test public void testBuildAndScanWithInstallHookPolicyReport() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final InstallHookProcessor processor = mock(InstallHookProcessor.class); when(processor.execute(any(InstallContext.class))).thenReturn(true); doThrow(PackageException.class).when(processor) .registerHooks(any(Archive.class), any(ClassLoader.class)); final Collection<CheckReport> reports = builder() .withInstallHookProcessorFactory(() -> processor) .withInstallHookPolicy(InstallHookPolicy.REPORT) .build().scanPackage(testPackage); assertTrue("reports has one report with one violation", reports.stream().anyMatch(report -> report.getViolations().size() == 1)); }
@Test public void testBuildAndScanWithInstallHookPolicySkip() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); InstallHookProcessor processor = mock(InstallHookProcessor.class, withSettings().lenient()); doThrow(new PackageException("shouldn't be thrown")).when(processor) .registerHooks(any(Archive.class), any(ClassLoader.class)); final Collection<CheckReport> reports = builder() .withInstallHookProcessorFactory(() -> processor) .withInstallHookPolicy(InstallHookPolicy.SKIP) .build().scanPackage(testPackage); assertTrue("reports has one report with no violations: " + reports.stream().findFirst(), reports.stream().anyMatch(report -> report.getViolations().size() == 0)); }
@Test public void testBuildAndScanWithInstallHookPolicyProhibit() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final InstallHookProcessor processor = mock(InstallHookProcessor.class); when(processor.hasHooks()).thenReturn(true); doThrow(new PackageException("prohibit")).when(processor) .registerHooks(any(Archive.class), any(ClassLoader.class)); final Collection<CheckReport> reports = builder() .withInstallHookProcessorFactory(() -> processor) .withInstallHookPolicy(InstallHookPolicy.PROHIBIT) .build().scanPackage(testPackage); assertTrue("reports has one report with two violations: " + reports.stream().findFirst(), reports.stream().anyMatch(report -> report.getViolations().size() == 2)); }
@Test public void testScanWithInitStage() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final InitStage stage = new InitStage.Builder().withNs("foo", "http: final CompletableFuture<String> fooUrlLatch = new CompletableFuture<>(); final ProgressCheck check = mock(ProgressCheck.class); doAnswer(call -> { fooUrlLatch.complete(call.getArgument(1, Session.class).getNamespaceURI("foo")); return true; }).when(check) .beforeExtract( any(PackageId.class), any(Session.class), any(PackageProperties.class), any(MetaInf.class), any(List.class) ); builder().withInitStage(stage).withProgressCheck(check).build().scanPackage(testPackage); assertEquals("uri is same", "http: }
@Test(expected = AbortedScanException.class) public void testScanWithInitStage_throws() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final Properties userProps = new Properties(); userProps.put(UserConstants.PARAM_ADMIN_ID, "anotheradmin"); final Properties securityProps = new Properties(); securityProps.put(UserConfiguration.NAME, ConfigurationParameters.of(userProps)); builder() .withJcrCustomizer(jcr -> { jcr.with(new SecurityProviderImpl(ConfigurationParameters.of(securityProps))); }) .build().scanPackage(testPackage); }
@Test public void testScanWithPreInstallUrl() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final InitStage stage = new InitStage.Builder().withNs("foo", "http: final CompletableFuture<Boolean> fooUrlLatch = new CompletableFuture<>(); final ProgressCheck check = mock(ProgressCheck.class); doAnswer(call -> { fooUrlLatch.complete(call.getArgument(1, Session.class).nodeExists("/tmp/foo/bar")); return true; }).when(check) .beforeExtract( any(PackageId.class), any(Session.class), any(PackageProperties.class), any(MetaInf.class), any(List.class) ); builder().withInitStage(stage) .withPreInstallUrl(testPackage.toURI().toURL()) .withProgressCheck(check) .build().scanPackage(testPackage); assertTrue("uri is same", fooUrlLatch.getNow(false)); }
@Test(expected = AbortedScanException.class) public void testScanInvalidPackage() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("unfiltered_package.zip"); builder().build().scanPackage(testPackage); }
@Test public void testScanOnListenerExceptionFromBeforeExtract() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final ProgressCheck check = mock(ProgressCheck.class); final ErrorListener errorListener = mock(ErrorListener.class); doThrow(RepositoryException.class).when(check).beforeExtract( any(PackageId.class), any(Session.class), any(PackageProperties.class), any(MetaInf.class), any(List.class) ); final CompletableFuture<Exception> eLatch = new CompletableFuture<>(); final CompletableFuture<ProgressCheck> handlerLatch = new CompletableFuture<>(); final CompletableFuture<PackageId> idLatch = new CompletableFuture<>(); doAnswer(call -> { eLatch.complete(call.getArgument(0, Exception.class)); handlerLatch.complete(call.getArgument(1, ProgressCheck.class)); idLatch.complete(call.getArgument(2, PackageId.class)); return true; }).when(errorListener).onListenerException(any(Exception.class), any(ProgressCheck.class), any(PackageId.class)); builder().withProgressCheck(check).withErrorListener(errorListener).build().scanPackage(testPackage); assertTrue("error is of type", eLatch.getNow(null) instanceof RepositoryException); assertSame("same check", check, handlerLatch.getNow(null)); assertEquals("package id is", PackageId.fromString("my_packages:tmp_foo_bar"), idLatch.getNow(null)); }
@Test public void testScanOnListenerExceptionFromAfterExtract() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final ProgressCheck check = mock(ProgressCheck.class); final ErrorListener errorListener = mock(ErrorListener.class); doThrow(RepositoryException.class).when(check).afterExtract( any(PackageId.class), any(Session.class) ); final CompletableFuture<Exception> eLatch = new CompletableFuture<>(); final CompletableFuture<ProgressCheck> handlerLatch = new CompletableFuture<>(); final CompletableFuture<PackageId> idLatch = new CompletableFuture<>(); doAnswer(call -> { eLatch.complete(call.getArgument(0, Exception.class)); handlerLatch.complete(call.getArgument(1, ProgressCheck.class)); idLatch.complete(call.getArgument(2, PackageId.class)); return true; }).when(errorListener).onListenerException(any(Exception.class), any(ProgressCheck.class), any(PackageId.class)); builder().withProgressCheck(check).withErrorListener(errorListener).build().scanPackage(testPackage); assertTrue("error is of type", eLatch.getNow(null) instanceof RepositoryException); assertSame("same check", check, handlerLatch.getNow(null)); assertEquals("package id is", PackageId.fromString("my_packages:tmp_foo_bar"), idLatch.getNow(null)); }
@Test public void testScanOnListenerExceptionFromIdentifyPackage() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final ProgressCheck check = mock(ProgressCheck.class); final ErrorListener errorListener = mock(ErrorListener.class); doThrow(RuntimeException.class).when(check).identifyPackage( any(PackageId.class), any(File.class) ); final CompletableFuture<Exception> eLatch = new CompletableFuture<>(); final CompletableFuture<ProgressCheck> handlerLatch = new CompletableFuture<>(); final CompletableFuture<PackageId> idLatch = new CompletableFuture<>(); doAnswer(call -> { eLatch.complete(call.getArgument(0, Exception.class)); handlerLatch.complete(call.getArgument(1, ProgressCheck.class)); idLatch.complete(call.getArgument(2, PackageId.class)); return true; }).when(errorListener).onListenerException(any(Exception.class), any(ProgressCheck.class), any(PackageId.class)); builder().withProgressCheck(check).withErrorListener(errorListener).build().scanPackage(testPackage); assertTrue("error is of type", eLatch.getNow(null) instanceof RuntimeException); assertSame("same check", check, handlerLatch.getNow(null)); assertEquals("package id is", PackageId.fromString("my_packages:tmp_foo_bar"), idLatch.getNow(null)); }
@Test public void testScanOnListenerExceptionFromIdentifySubpackage() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("subsubtest.zip"); final ProgressCheck check = mock(ProgressCheck.class); final ErrorListener errorListener = mock(ErrorListener.class); doThrow(RuntimeException.class).when(check).identifySubpackage( any(PackageId.class), any(PackageId.class) ); final CompletableFuture<Exception> eLatch = new CompletableFuture<>(); final CompletableFuture<ProgressCheck> handlerLatch = new CompletableFuture<>(); final CompletableFuture<PackageId> idLatch = new CompletableFuture<>(); doAnswer(call -> { eLatch.complete(call.getArgument(0, Exception.class)); handlerLatch.complete(call.getArgument(1, ProgressCheck.class)); idLatch.complete(call.getArgument(2, PackageId.class)); return true; }).when(errorListener).onListenerException(any(Exception.class), any(ProgressCheck.class), any(PackageId.class)); builder().withProgressCheck(check).withErrorListener(errorListener).build().scanPackage(testPackage); assertTrue("error is of type", eLatch.getNow(null) instanceof RuntimeException); assertSame("same check", check, handlerLatch.getNow(null)); assertEquals("package id is", PackageId.fromString("my_packages:subtest"), idLatch.getNow(null)); }
@Test public void testScanOnListenerExceptionFromIdentifySubpackage_silencedTho() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("subsubtest.zip"); final ProgressCheck check = mock(ProgressCheck.class, withSettings().lenient()); final ErrorListener errorListener = mock(ErrorListener.class, withSettings().lenient()); doThrow(RuntimeException.class).when(check).identifySubpackage( any(PackageId.class), any(PackageId.class) ); final CompletableFuture<Exception> eLatch = new CompletableFuture<>(); final CompletableFuture<ProgressCheck> handlerLatch = new CompletableFuture<>(); final CompletableFuture<PackageId> idLatch = new CompletableFuture<>(); doAnswer(call -> { eLatch.complete(call.getArgument(0, Exception.class)); handlerLatch.complete(call.getArgument(1, ProgressCheck.class)); idLatch.complete(call.getArgument(2, PackageId.class)); return true; }).when(errorListener).onListenerException(any(Exception.class), any(ProgressCheck.class), any(PackageId.class)); builder().withProgressCheck(check).withErrorListener(errorListener) .withSubpackageSilencer(((subpackageId, parentId) -> true)).build().scanPackage(testPackage); assertFalse("error is not thrown", eLatch.isDone()); }
@Test public void testScanWithSubpackages() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("subsubtest.zip"); final Map<PackageId, PackageId> expectIds = new LinkedHashMap<>(); final PackageId root = PackageId.fromString("my_packages:subsubtest"); final PackageId sub1 = PackageId.fromString("my_packages:subtest"); final PackageId suba = PackageId.fromString("my_packages:sub_a"); final PackageId subb = PackageId.fromString("my_packages:sub_b"); expectIds.put(sub1, root); expectIds.put(suba, sub1); expectIds.put(subb, sub1); final Map<PackageId, PackageId> subToParent = new LinkedHashMap<>(); final ProgressCheck check = mock(ProgressCheck.class); doAnswer(call -> subToParent.put(call.getArgument(0), call.getArgument(1))) .when(check).identifySubpackage(any(PackageId.class), any(PackageId.class)); builder().withProgressCheck(check).build().scanPackage(testPackage); assertEquals("expect ids", expectIds, subToParent); }
@Test public void testImporterListenerAdapter_onMessage_deletedPathException() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final InitStage stage = new InitStage.Builder().withForcedRoot("/tmp/foo/bar/cat").build(); final ProgressCheck check = mock(ProgressCheck.class); doThrow(RepositoryException.class).when(check) .deletedPath(any(PackageId.class), anyString(), any(Session.class)); final CompletableFuture<Exception> eLatch = new CompletableFuture<>(); final CompletableFuture<ProgressCheck> handlerLatch = new CompletableFuture<>(); final CompletableFuture<PackageId> idLatch = new CompletableFuture<>(); final CompletableFuture<String> pathLatch = new CompletableFuture<>(); final ErrorListener errorListener = mock(ErrorListener.class); doAnswer(call -> { eLatch.complete(call.getArgument(0, Exception.class)); handlerLatch.complete(call.getArgument(1, ProgressCheck.class)); idLatch.complete(call.getArgument(2, PackageId.class)); pathLatch.complete(call.getArgument(3, String.class)); return true; }).when(errorListener).onListenerPathException(any(Exception.class), any(ProgressCheck.class), any(PackageId.class), anyString()); builder().withInitStage(stage) .withProgressCheck(check) .withErrorListener(errorListener) .build().scanPackage(testPackage); assertTrue("error is of type", eLatch.getNow(null) instanceof RepositoryException); assertSame("same check", check, handlerLatch.getNow(null)); assertEquals("package id is", PackageId.fromString("my_packages:tmp_foo_bar"), idLatch.getNow(null)); assertEquals("path is", "/tmp/foo/bar/cat", pathLatch.getNow("")); }
@Test public void testImporterListenerAdapter_onMessage_importedPathException() throws Exception { final File testPackage = TestPackageUtil.prepareTestPackage("tmp_foo_bar.zip"); final ProgressCheck check = mock(ProgressCheck.class); doThrow(RepositoryException.class).when(check) .importedPath(any(PackageId.class), anyString(), any(Node.class), any(PathAction.class)); final CompletableFuture<Exception> eLatch = new CompletableFuture<>(); final CompletableFuture<ProgressCheck> handlerLatch = new CompletableFuture<>(); final CompletableFuture<PackageId> idLatch = new CompletableFuture<>(); final CompletableFuture<String> pathLatch = new CompletableFuture<>(); final ErrorListener errorListener = mock(ErrorListener.class); doAnswer(call -> { eLatch.complete(call.getArgument(0, Exception.class)); handlerLatch.complete(call.getArgument(1, ProgressCheck.class)); idLatch.complete(call.getArgument(2, PackageId.class)); pathLatch.complete(call.getArgument(3, String.class)); return true; }).when(errorListener).onListenerPathException(any(Exception.class), any(ProgressCheck.class), any(PackageId.class), anyString()); builder() .withProgressCheck(check) .withErrorListener(errorListener) .build().scanPackage(testPackage); assertTrue("error is of type", eLatch.getNow(null) instanceof RepositoryException); assertSame("same check", check, handlerLatch.getNow(null)); assertEquals("package id is", PackageId.fromString("my_packages:tmp_foo_bar"), idLatch.getNow(null)); assertEquals("path is", "/", pathLatch.getNow("")); }
@Test public void testCustomNodeStore() throws Exception { CompletableFuture<Boolean> usedCustomNodeStore = new CompletableFuture<>(); OakMachine.JcrCustomizer checker = uncheckVoid1(jcr -> { Object oak = PrivateAccessor.getField(jcr, "oak"); Object nodeStore = PrivateAccessor.getField(oak, "store"); usedCustomNodeStore.complete(nodeStore instanceof CustomNodeStore); })::accept; OakMachine machine = new OakMachine.Builder().withNodeStoreSupplier(CustomNodeStore::new).withJcrCustomizer(checker).build(); machine.scanPackage(); assertTrue("Custom node store was used", usedCustomNodeStore.getNow(false)); }