This is an automated email from the ASF dual-hosted git repository.
tmaret pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-distribution-journal.git
The following commit(s) were added to refs/heads/master by this push:
new 6d4432a SLING-12704 - Introduce a JournalDistributionPackageBuilder
(#167)
6d4432a is described below
commit 6d4432acf98826b012a2ee46a400cff2b974ee9e
Author: Timothee Maret <[email protected]>
AuthorDate: Fri Mar 14 22:56:49 2025 +0100
SLING-12704 - Introduce a JournalDistributionPackageBuilder (#167)
---
pom.xml | 2 +-
.../journal/bookkeeper/PackageHandler.java | 68 +++---
.../journal/shared/JournalDistributionPackage.java | 84 +++++++
.../shared/JournalDistributionPackageBuilder.java | 270 +++++++++++++++++++++
.../journal/impl/subscriber/SubscriberTest.java | 32 +--
.../JournalDistributionPackageBuilderTest.java | 127 ++++++++++
.../shared/JournalDistributionPackageTest.java | 56 +++++
7 files changed, 575 insertions(+), 64 deletions(-)
diff --git a/pom.xml b/pom.xml
index c630e9e..627ca83 100644
--- a/pom.xml
+++ b/pom.xml
@@ -143,7 +143,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.distribution.core</artifactId>
- <version>0.4.8</version>
+ <version>0.7.2</version>
<scope>provided</scope>
<exclusions>
<exclusion>
diff --git
a/src/main/java/org/apache/sling/distribution/journal/bookkeeper/PackageHandler.java
b/src/main/java/org/apache/sling/distribution/journal/bookkeeper/PackageHandler.java
index 9fb79da..32f6e0b 100644
---
a/src/main/java/org/apache/sling/distribution/journal/bookkeeper/PackageHandler.java
+++
b/src/main/java/org/apache/sling/distribution/journal/bookkeeper/PackageHandler.java
@@ -19,14 +19,15 @@
package org.apache.sling.distribution.journal.bookkeeper;
-import org.apache.commons.io.IOUtils;
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.distribution.common.DistributionException;
import org.apache.sling.distribution.journal.BinaryStore;
import org.apache.sling.distribution.journal.messages.PackageMessage;
+import org.apache.sling.distribution.journal.messages.PackageMessage.ReqType;
+import org.apache.sling.distribution.journal.shared.JournalDistributionPackage;
+import org.apache.sling.distribution.packaging.DistributionPackage;
import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
+import org.apache.sling.distribution.packaging.DistributionPackageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +36,9 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import static java.lang.String.format;
+import static org.apache.commons.io.IOUtils.toByteArray;
+import static
org.apache.sling.distribution.journal.messages.PackageMessage.ReqType.ADD;
+import static
org.apache.sling.distribution.packaging.DistributionPackageInfo.*;
class PackageHandler {
private static final Logger LOG =
LoggerFactory.getLogger(PackageHandler.class);
@@ -56,57 +59,44 @@ class PackageHandler {
}
public void apply(ResourceResolver resolver, PackageMessage pkgMsg)
- throws DistributionException, PersistenceException {
- PackageMessage.ReqType type = pkgMsg.getReqType();
- switch (type) {
- case ADD:
- installAddPackage(resolver, pkgMsg);
- break;
- case DELETE:
- installDeletePackage(resolver, pkgMsg);
- break;
- case TEST:
- break;
- default: throw new UnsupportedOperationException(format("Unable to
process messages with type: %s", type));
+ throws DistributionException {
+ DistributionPackage distributionPackage =
toDistributionPackage(pkgMsg);
+ packageBuilder.installPackage(resolver, distributionPackage);
+ ReqType type = pkgMsg.getReqType();
+ if (type == ADD) {
+ extractor.handle(resolver, pkgMsg.getPaths());
}
}
- private void installAddPackage(ResourceResolver resolver, PackageMessage
pkgMsg)
+ private DistributionPackage toDistributionPackage(PackageMessage pkgMsg)
throws DistributionException {
LOG.debug("Importing paths {}",pkgMsg.getPaths());
- InputStream pkgStream = null;
- try {
- pkgStream = stream(resolver, pkgMsg, binaryStore);
- packageBuilder.installPackage(resolver, pkgStream);
- extractor.handle(resolver, pkgMsg.getPaths());
- } finally {
- IOUtils.closeQuietly(pkgStream);
+ final byte[] data;
+ try (InputStream inputStream = stream(pkgMsg)) {
+ data = toByteArray(inputStream);
+ } catch (IOException e) {
+ throw new DistributionException("Failed to download package from
binary store", e);
}
-
+ DistributionPackageInfo distributionPackageInfo = new
DistributionPackageInfo(pkgMsg.getPkgType());
+ distributionPackageInfo.put(PROPERTY_REQUEST_PATHS,
pkgMsg.getPaths().toArray());
+ distributionPackageInfo.put(PROPERTY_REQUEST_DEEP_PATHS,
pkgMsg.getDeepPaths().toArray());
+ distributionPackageInfo.put(PROPERTY_REQUEST_TYPE,
pkgMsg.getReqType());
+ return new JournalDistributionPackage(pkgMsg.getPkgId(),
pkgMsg.getPkgType(), data, distributionPackageInfo);
}
@Nonnull
- public static InputStream stream(ResourceResolver resolver, PackageMessage
pkgMsg, BinaryStore binaryStore) throws DistributionException {
+ InputStream stream(PackageMessage pkgMsg) throws DistributionException {
if (pkgMsg.getPkgBinary() != null) {
return new ByteArrayInputStream(pkgMsg.getPkgBinary());
- } else {
- String pkgBinRef = pkgMsg.getPkgBinaryRef();
+ }
+ String pkgBinRef = pkgMsg.getPkgBinaryRef();
+ if (pkgBinRef != null) {
try {
return binaryStore.get(pkgBinRef);
} catch (IOException io) {
throw new DistributionException(io.getMessage(), io);
}
}
- }
-
- private void installDeletePackage(ResourceResolver resolver,
PackageMessage pkgMsg)
- throws PersistenceException {
- LOG.info("Deleting paths {}",pkgMsg.getPaths());
- for (String path : pkgMsg.getPaths()) {
- Resource resource = resolver.getResource(path);
- if (resource != null) {
- resolver.delete(resource);
- }
- }
+ return new ByteArrayInputStream(new byte[0]);
}
}
diff --git
a/src/main/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackage.java
b/src/main/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackage.java
new file mode 100644
index 0000000..94039e5
--- /dev/null
+++
b/src/main/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackage.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.distribution.journal.shared;
+
+import org.apache.sling.distribution.packaging.DistributionPackage;
+import org.apache.sling.distribution.packaging.DistributionPackageInfo;
+
+import javax.annotation.Nonnull;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+public class JournalDistributionPackage implements DistributionPackage {
+
+ private final String id;
+
+ private final String type;
+
+ private final long size;
+
+ private final byte[] data;
+
+ private final DistributionPackageInfo info;
+
+ public JournalDistributionPackage(@Nonnull String id, @Nonnull String
type, @Nonnull byte[] data, @Nonnull DistributionPackageInfo info) {
+ this.id = id;
+ this.type = type;
+ this.size = data.length;
+ this.info = info;
+ this.data = data;
+ }
+
+ @Nonnull
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Nonnull
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public @Nonnull InputStream createInputStream() {
+ return new ByteArrayInputStream(data);
+ }
+
+ @Override
+ public long getSize() {
+ return size;
+ }
+
+ @Override
+ public void close() {
+ // no resource to close
+ }
+
+ @Override
+ public void delete() {
+ // the journal is immutable with time based eviction policy
+ }
+
+ @Override
+ public @Nonnull DistributionPackageInfo getInfo() {
+ return info;
+ }
+}
\ No newline at end of file
diff --git
a/src/main/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageBuilder.java
b/src/main/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageBuilder.java
new file mode 100644
index 0000000..b9c0c03
--- /dev/null
+++
b/src/main/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageBuilder.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.distribution.journal.shared;
+
+import org.apache.jackrabbit.vault.fs.api.IdConflictPolicy;
+import org.apache.jackrabbit.vault.fs.api.ImportMode;
+import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.distribution.DistributionRequest;
+import org.apache.sling.distribution.DistributionRequestType;
+import org.apache.sling.distribution.common.DistributionException;
+import org.apache.sling.distribution.packaging.DistributionPackage;
+import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
+import org.apache.sling.distribution.packaging.DistributionPackageInfo;
+import org.apache.sling.distribution.serialization.*;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static java.lang.String.format;
+import static java.lang.System.currentTimeMillis;
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableMap;
+import static java.util.Objects.requireNonNull;
+import static java.util.UUID.randomUUID;
+import static java.util.stream.Collectors.toMap;
+import static
org.apache.sling.distribution.packaging.DistributionPackageInfo.PROPERTY_REQUEST_DEEP_PATHS;
+import static
org.apache.sling.distribution.packaging.DistributionPackageInfo.PROPERTY_REQUEST_PATHS;
+import static
org.apache.sling.distribution.packaging.DistributionPackageInfo.PROPERTY_REQUEST_TYPE;
+import static org.slf4j.LoggerFactory.getLogger;
+
+@Component(service = DistributionPackageBuilder.class)
+@Designate(ocd = JournalDistributionPackageBuilder.Configuration.class,
factory = true)
+public class JournalDistributionPackageBuilder implements
DistributionPackageBuilder {
+
+ private static final Logger LOG =
getLogger(JournalDistributionPackageBuilder.class);
+
+ private final String type;
+
+ private final DistributionContentSerializer contentSerializer;
+
+ @Activate
+ public JournalDistributionPackageBuilder(
+ Configuration config,
+ @Reference DistributionContentSerializerProvider
serializerProvider) {
+ type = config.name();
+ ExportSettings exportSettings = new ExportSettings(
+ config.package_roots(),
+ config.package_filters(),
+ config.property_filters(),
+ config.useBinaryReferences(),
+ pathMappings(config.pathsMapping())
+ );
+ ImportSettings importSettings = new ImportSettings(
+ ImportMode.valueOf(config.importMode()),
+ AccessControlHandling.valueOf(config.aclHandling()),
+ AccessControlHandling.valueOf(config.cugHandling()),
+ config.autoSaveThreshold(),
+ config.strictImport(),
+ config.overwritePrimaryTypesOfFolders(),
+ config.idConflictPolicy()
+ );
+ contentSerializer = serializerProvider.build(config.name(),
exportSettings, importSettings);
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public @Nonnull DistributionPackage createPackage(@Nonnull
ResourceResolver resourceResolver,
+ @Nonnull
DistributionRequest distributionRequest)
+ throws DistributionException {
+
+ String packageId = format("dstrpck-%s-%s", currentTimeMillis(),
randomUUID());
+
+ final byte[] data;
+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream())
{
+ DistributionExportOptions distributionExportOptions = new
DistributionExportOptions(distributionRequest, null /* Filters set on the
serializer */);
+ contentSerializer.exportToStream(resourceResolver,
distributionExportOptions, outputStream);
+ data = outputStream.toByteArray();
+ } catch (IOException e) {
+ throw new DistributionException("Failed to create package for
paths: " + Arrays.toString(distributionRequest.getPaths()), e);
+ }
+
+ DistributionPackageInfo distributionPackageInfo = new
DistributionPackageInfo(getType());
+ distributionPackageInfo.put(PROPERTY_REQUEST_TYPE,
distributionRequest.getRequestType());
+ distributionPackageInfo.put(PROPERTY_REQUEST_PATHS,
distributionRequest.getPaths());
+ distributionPackageInfo.put(PROPERTY_REQUEST_DEEP_PATHS,
getDeepPaths(distributionRequest));
+
+ return new JournalDistributionPackage(packageId, getType(), data,
distributionPackageInfo);
+ }
+
+ @Nonnull
+ @Override
+ public DistributionPackage readPackage(@Nonnull ResourceResolver
resourceResolver,
+ @Nonnull InputStream inputStream)
+ throws DistributionException {
+ throw new DistributionException("Unsupported Operation");
+ }
+
+ @Nullable
+ @Override
+ public DistributionPackage getPackage(@Nonnull ResourceResolver
resourceResolver,
+ @Nonnull String id)
+ throws DistributionException {
+ throw new DistributionException("Unsupported Operation with id: " +
id);
+ }
+
+ @Override
+ public boolean installPackage(@Nonnull ResourceResolver resourceResolver,
+ @Nonnull DistributionPackage
distributionPackage)
+ throws DistributionException {
+ DistributionPackageInfo info = distributionPackage.getInfo();
+ DistributionRequestType requestType =
requireNonNull(info.getRequestType());
+ switch (requestType) {
+ case ADD: installAddPackage(resourceResolver,
distributionPackage); break;
+ case DELETE: installDeletePackage(resourceResolver,
distributionPackage); break;
+ default: LOG.debug("Skip request type: {}", requestType);
+ }
+ return true;
+ }
+
+ @Override
+ public @Nonnull DistributionPackageInfo installPackage(@Nonnull
ResourceResolver resourceResolver,
+ @Nonnull
InputStream inputStream)
+ throws DistributionException {
+ throw new DistributionException("Unsupported Operation");
+ }
+
+ protected Map<String, String> pathMappings(String[] pathMappings) {
+ return unmodifiableMap(Arrays.stream(pathMappings)
+ .map(mapping -> mapping.split("=", 2))
+ .filter(chunks -> chunks.length == 2)
+ .collect(toMap(chunks -> chunks[0], chunks -> chunks[1],
(existing, replacement) -> replacement)));
+ }
+
+ private void installAddPackage(@Nonnull ResourceResolver resourceResolver,
+ @Nonnull DistributionPackage
distributionPackage)
+ throws DistributionException {
+ try (InputStream inputStream =
distributionPackage.createInputStream()) {
+ contentSerializer.importFromStream(resourceResolver, inputStream);
+ } catch (IOException e) {
+ throw new DistributionException("Failed to install distribution
package with id: " + distributionPackage.getId(), e);
+ }
+ }
+
+ private void installDeletePackage(@Nonnull ResourceResolver
resourceResolver,
+ @Nonnull DistributionPackage
distributionPackage)
+ throws DistributionException {
+ List<String> paths = asList(distributionPackage.getInfo().getPaths());
+ LOG.info("Deleting paths {}", paths);
+ for (String path : paths) {
+ Resource resource = resourceResolver.getResource(path);
+ if (resource != null) {
+ try {
+ resourceResolver.delete(resource);
+ } catch (PersistenceException e) {
+ throw new DistributionException(e);
+ }
+ }
+ }
+ }
+
+ private String[] getDeepPaths(DistributionRequest request) {
+ List<String> deepPaths = new ArrayList<>();
+ for (String path : request.getPaths()) {
+ if (request.isDeep(path)) {
+ deepPaths.add(path);
+ }
+ }
+ return deepPaths.toArray(new String[0]);
+ }
+
+ @ObjectClassDefinition(name = "Apache Sling Journal based Distribution -
Package Builder Configuration",
+ description = "Apache Sling Content Distribution Package Builder
Configuration")
+ public @interface Configuration {
+
+ @AttributeDefinition
+ String webconsole_configurationFactory_nameHint() default "Builder
name: {name}";
+
+ @AttributeDefinition(name = "Name",
+ description = "The name of the package builder.")
+ String name() default "journal-distribution";
+
+ @AttributeDefinition(name = "Import Mode",
+ description = "The vlt import mode for created packages.")
+ String importMode() default "REPLACE";
+
+ @AttributeDefinition(name = "Acl Handling",
+ description = "The vlt acl handling mode for created
packages.")
+ String aclHandling() default "MERGE_PRESERVE";
+
+ @AttributeDefinition(name = "Cug Handling",
+ description = "The vlt cug handling mode for created
packages.")
+ String cugHandling() default "OVERWRITE";
+
+ @AttributeDefinition(name = "Package Roots",
+ description = "The package roots to be used for created
packages. (this is useful for assembling packages with an user that cannot read
above the package root)")
+ String[] package_roots() default {};
+
+ @AttributeDefinition(name = "Package Node Filters",
+ description = "The package node path filters. Filter format:
path|+include|-exclude")
+ String[] package_filters() default {};
+
+ @AttributeDefinition(name = "Package Property Filters",
+ description = "The package property path filters. Filter
format: path|+include|-exclude")
+ String[] property_filters() default {};
+
+ @AttributeDefinition(name = "Use Binary References",
+ description = "If activated, it avoids sending binaries in the
distribution package.")
+ boolean useBinaryReferences() default true;
+
+ @AttributeDefinition(name = "Autosave threshold",
+ description = "The value after which autosave is triggered for
intermediate changes.")
+ int autoSaveThreshold() default 1000;
+
+ @AttributeDefinition(name = "Paths mapping",
+ description = "List of paths that require be mapped.The format
is {sourcePattern}={destinationPattern}, e.g. /etc/(.*)=/var/$1/some or simply
/data=/bak")
+ String[] pathsMapping() default {};
+
+
+ @AttributeDefinition(name = "Install a content package in a strict
mode",
+ description = "Flag to mark an error response will be thrown,
if a content package will incorrectly installed")
+ boolean strictImport() default true;
+
+
+ @AttributeDefinition(name = "Legacy Folder Primary Type Mode",
+ description = "Whether to overwrite the primary type of
folders during imports")
+ boolean overwritePrimaryTypesOfFolders() default true;
+
+ @AttributeDefinition(name = "ID Conflict Policy",
+ description = "Node id conflict policy to be used during
import")
+ IdConflictPolicy idConflictPolicy() default IdConflictPolicy.LEGACY;
+
+ }
+}
\ No newline at end of file
diff --git
a/src/test/java/org/apache/sling/distribution/journal/impl/subscriber/SubscriberTest.java
b/src/test/java/org/apache/sling/distribution/journal/impl/subscriber/SubscriberTest.java
index 39b01ca..0561cf1 100644
---
a/src/test/java/org/apache/sling/distribution/journal/impl/subscriber/SubscriberTest.java
+++
b/src/test/java/org/apache/sling/distribution/journal/impl/subscriber/SubscriberTest.java
@@ -35,7 +35,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.net.URI;
@@ -50,7 +49,6 @@ import java.util.concurrent.TimeoutException;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceUtil;
@@ -62,12 +60,7 @@ import org.apache.sling.distribution.ImportPreProcessor;
import org.apache.sling.distribution.agent.DistributionAgentState;
import org.apache.sling.distribution.agent.spi.DistributionAgent;
import org.apache.sling.distribution.common.DistributionException;
-import org.apache.sling.distribution.journal.HandlerAdapter;
-import org.apache.sling.distribution.journal.MessageHandler;
-import org.apache.sling.distribution.journal.MessageInfo;
-import org.apache.sling.distribution.journal.MessageSender;
-import org.apache.sling.distribution.journal.MessagingProvider;
-import org.apache.sling.distribution.journal.Reset;
+import org.apache.sling.distribution.journal.*;
import org.apache.sling.distribution.journal.bookkeeper.BookKeeper;
import org.apache.sling.distribution.journal.bookkeeper.BookKeeperFactory;
import org.apache.sling.distribution.journal.bookkeeper.LocalStore;
@@ -84,8 +77,8 @@ import
org.apache.sling.distribution.journal.messages.PackageStatusMessage.Statu
import org.apache.sling.distribution.journal.messages.PingMessage;
import org.apache.sling.distribution.journal.shared.TestMessageInfo;
import org.apache.sling.distribution.journal.shared.Topics;
+import org.apache.sling.distribution.packaging.DistributionPackage;
import org.apache.sling.distribution.packaging.DistributionPackageBuilder;
-import org.apache.sling.distribution.packaging.DistributionPackageInfo;
import org.apache.sling.settings.SlingSettingsService;
import org.apache.sling.testing.resourceresolver.MockResourceResolverFactory;
import org.awaitility.Awaitility;
@@ -101,7 +94,6 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
-import org.mockito.stubbing.OngoingStubbing;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.EventAdmin;
@@ -151,6 +143,9 @@ public class SubscriberTest {
@Mock
private SlingSettingsService slingSettings;
+ @Mock
+ private BinaryStore binaryStore;
+
@Spy
private ResourceResolverFactory resolverFactory = new
MockResourceResolverFactory();
@@ -253,7 +248,7 @@ public class SubscriberTest {
packageHandler.handle(info, message);
verify(packageBuilder,
timeout(1000).times(0)).installPackage(any(ResourceResolver.class),
- any(ByteArrayInputStream.class));
+ any(DistributionPackage.class));
assertThat(getStoredOffset(), nullValue());
for (int c=0; c < BookKeeper.COMMIT_AFTER_NUM_SKIPPED; c++) {
packageHandler.handle(info, message);
@@ -324,7 +319,7 @@ public class SubscriberTest {
}
@Test
- public void testReceiveDelete() throws LoginException,
PersistenceException {
+ public void testReceiveDelete() throws LoginException, IOException {
assumeNoPrecondition();
initSubscriber();
waitSubscriber(IDLE);
@@ -333,7 +328,6 @@ public class SubscriberTest {
PackageMessage message = BASIC_DEL_PACKAGE;
packageHandler.handle(info, message);
waitSubscriber(IDLE);
- await().atMost(30, SECONDS).until(() -> getResource("/test") == null);
verifyNoStatusMessageSent();
}
@@ -341,7 +335,7 @@ public class SubscriberTest {
public void testSendFailedStatus() throws DistributionException {
assumeNoPrecondition();
initSubscriber(Collections.singletonMap("maxRetries", "1"));
- whenInstallPackage()
+ when(packageBuilder.installPackage(any(ResourceResolver.class),
any(DistributionPackage.class)))
.thenThrow(new RuntimeException("Expected"));
MessageInfo info = createInfo(0l);
@@ -416,10 +410,6 @@ public class SubscriberTest {
return statusMessage;
}
- private OngoingStubbing<DistributionPackageInfo> whenInstallPackage()
throws DistributionException {
- return when(packageBuilder.installPackage(any(ResourceResolver.class),
any(ByteArrayInputStream.class)));
- }
-
private TestMessageInfo createInfo(long offset) {
return new TestMessageInfo("", 1, offset, 0);
}
@@ -440,12 +430,6 @@ public class SubscriberTest {
}
}
- private Resource getResource(String path) throws LoginException {
- try (ResourceResolver resolver =
resolverFactory.getServiceResourceResolver(null)) {
- return resolver.getResource(path);
- }
- }
-
private void initSubscriber() {
initSubscriber(Collections.emptyMap());
}
diff --git
a/src/test/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageBuilderTest.java
b/src/test/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageBuilderTest.java
new file mode 100644
index 0000000..aa7b599
--- /dev/null
+++
b/src/test/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageBuilderTest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.distribution.journal.shared;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.distribution.DistributionRequest;
+import org.apache.sling.distribution.SimpleDistributionRequest;
+import org.apache.sling.distribution.common.DistributionException;
+import org.apache.sling.distribution.packaging.DistributionPackage;
+import
org.apache.sling.distribution.serialization.DistributionContentSerializer;
+import
org.apache.sling.distribution.serialization.DistributionContentSerializerProvider;
+import org.apache.sling.distribution.serialization.ExportSettings;
+import org.apache.sling.distribution.serialization.ImportSettings;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.ByteArrayInputStream;
+import java.util.UUID;
+
+import static java.util.Map.of;
+import static org.apache.sling.distribution.DistributionRequestType.ADD;
+import static org.apache.sling.distribution.DistributionRequestType.DELETE;
+import static org.apache.sling.distribution.DistributionRequestType.PULL;
+import static
org.apache.sling.distribution.journal.shared.JournalDistributionPackageBuilder.Configuration;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+import static org.osgi.util.converter.Converters.standardConverter;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JournalDistributionPackageBuilderTest {
+
+ @Mock
+ private DistributionContentSerializerProvider serializerProvider;
+
+ @Mock
+ private DistributionContentSerializer serializer;
+
+ @Mock
+ private ResourceResolver resolver;
+
+ @Mock
+ private Resource resource;
+
+ private JournalDistributionPackageBuilder builder;
+
+ @Before
+ public void setUp() {
+ when(resolver.getResource(anyString()))
+ .thenReturn(resource);
+ when(serializerProvider.build(anyString(), any(ExportSettings.class),
any(ImportSettings.class)))
+ .thenReturn(serializer);
+ Configuration config = standardConverter().convert(of("/some/path",
"/some/other/path")).to(Configuration.class);
+ builder = new JournalDistributionPackageBuilder(config,
serializerProvider);
+ assertEquals("journal-distribution", builder.getType());
+ }
+
+ @Test
+ public void testInstallAddPackage() throws Exception {
+ DistributionRequest request = new SimpleDistributionRequest(ADD,
"/some/path");
+ DistributionPackage pkg = builder.createPackage(resolver, request);
+ assertTrue(builder.installPackage(resolver, pkg));
+ }
+
+ @Test
+ public void testInstallDeletePackage() throws Exception {
+ DistributionRequest request = new SimpleDistributionRequest(DELETE,
"/some/path");
+ DistributionPackage pkg = builder.createPackage(resolver, request);
+ assertTrue(builder.installPackage(resolver, pkg));
+ }
+
+ @Test
+ public void testInstallUnsupportedPackage() throws DistributionException {
+ DistributionRequest request = new SimpleDistributionRequest(PULL,
"/some/path");
+ DistributionPackage pkg = builder.createPackage(resolver, request);
+ assertTrue(builder.installPackage(resolver, pkg));
+ }
+
+ @Test
+ public void testCreatePackage() throws Exception {
+ String[] paths = {"/some/path", "/some/other/path"};
+ DistributionRequest request = new SimpleDistributionRequest(ADD,
paths);
+ DistributionPackage pkg = builder.createPackage(resolver, request);
+ assertEquals("journal-distribution", pkg.getInfo().getType());
+ assertEquals(ADD, pkg.getInfo().getRequestType());
+ assertEquals(0, pkg.getSize());
+ assertArrayEquals(paths, pkg.getInfo().getPaths());
+ }
+
+ @Test(expected = DistributionException.class)
+ public void testReadPackage() throws Exception {
+ builder.readPackage(resolver, new ByteArrayInputStream(new byte[0]));
+ }
+
+ @Test(expected = DistributionException.class)
+ public void testGetPackage() throws Exception {
+ builder.getPackage(resolver, UUID.randomUUID().toString());
+ }
+
+ @Test(expected = DistributionException.class)
+ public void testInstallPackageFromStream() throws Exception {
+ builder.installPackage(resolver, new ByteArrayInputStream(new
byte[0]));
+ }
+}
\ No newline at end of file
diff --git
a/src/test/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageTest.java
b/src/test/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageTest.java
new file mode 100644
index 0000000..45f97d4
--- /dev/null
+++
b/src/test/java/org/apache/sling/distribution/journal/shared/JournalDistributionPackageTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.distribution.journal.shared;
+
+import org.apache.sling.distribution.packaging.DistributionPackageInfo;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.util.UUID.randomUUID;
+import static
org.apache.sling.distribution.packaging.DistributionPackageInfo.PROPERTY_REQUEST_DEEP_PATHS;
+import static
org.apache.sling.distribution.packaging.DistributionPackageInfo.PROPERTY_REQUEST_PATHS;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+public class JournalDistributionPackageTest {
+
+
+ @Test
+ public void testValues() {
+ String id = randomUUID().toString();
+ String type = randomUUID().toString();
+ byte[] data = randomUUID().toString().getBytes();
+ String[] paths = {"/some/paths"};
+ String[] deepPaths = {"/some/paths"};
+ Map<String, Object> props = new HashMap<>();
+ props.put(PROPERTY_REQUEST_PATHS, paths);
+ props.put(PROPERTY_REQUEST_DEEP_PATHS, deepPaths);
+ DistributionPackageInfo pkgInfo = new DistributionPackageInfo(type,
props);
+ JournalDistributionPackage pkg = new JournalDistributionPackage(id,
type, data, pkgInfo);
+ assertEquals(id, pkg.getId());
+ assertEquals(data.length, pkg.getSize());
+ assertEquals(type, pkg.getType());
+ assertEquals(pkgInfo, pkg.getInfo());
+ assertEquals(type, pkg.getInfo().getType());
+ assertArrayEquals(paths, pkg.getInfo().getPaths());
+ }
+
+}
\ No newline at end of file