-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
eschleb
committed
Sep 23, 2024
0 parents
commit 340c8bd
Showing
32 changed files
with
2,496 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
name: "Setup maven" | ||
description: "Configures maven settings" | ||
|
||
inputs: | ||
mgnl_nexus_user: | ||
description: “Username for magnolia nexus” | ||
required: true | ||
mgnl_nexus_pass: | ||
description: “Password for magnolia nexus” | ||
required: true | ||
|
||
runs: | ||
using: "composite" | ||
steps: | ||
- uses: s4u/maven-settings-action@v2 | ||
with: | ||
servers: | | ||
[{ | ||
"id": "magnolia.enterprise.group", | ||
"username": "${{ inputs.mgnl_nexus_user }}", | ||
"password": "${{ inputs.mgnl_nexus_pass }}" | ||
}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
name: release and deploy | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
release: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
# Checkout source code | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: '0' | ||
# Setup Java environment | ||
- name: Set up JDK 17 | ||
uses: actions/setup-java@v1 | ||
with: | ||
java-version: 17 | ||
- name: Maven setup | ||
uses: ./.github/actions/mvn-setup | ||
with: | ||
mgnl_nexus_user: ${{secrets.MGNL_NEXUS_USER}} | ||
mgnl_nexus_pass: ${{secrets.MGNL_NEXUS_PASS}} | ||
# Install xmllint | ||
- name: Install dependencies | ||
run: sudo apt-get update && sudo apt-get install libxml2-utils | ||
# Set git user name and email | ||
- name: Set up Git | ||
run: | | ||
chmod +x ci/setup-git.sh | ||
ci/setup-git.sh | ||
# Release, set correct versions and create tag | ||
- name: Release (versioning/tag) | ||
run: | | ||
chmod +x ci/mvn-release.sh | ||
ci/mvn-release.sh | ||
deploy-release: | ||
|
||
needs: release | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
# Checkout source code | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
with: | ||
ref: 'main' | ||
# Setup Java environment | ||
- name: Set up JDK 17 | ||
uses: actions/setup-java@v4 | ||
with: | ||
distribution: temurin | ||
java-version: 17 | ||
server-id: central | ||
server-username: MAVEN_USERNAME | ||
server-password: MAVEN_PASSWORD | ||
gpg-passphrase: MAVEN_GPG_PASSPHRASE | ||
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} | ||
- name: Maven setup | ||
uses: ./.github/actions/mvn-setup | ||
with: | ||
mgnl_nexus_user: ${{secrets.MGNL_NEXUS_USER}} | ||
mgnl_nexus_pass: ${{secrets.MGNL_NEXUS_PASS}} | ||
# Run maven verify | ||
- name: Maven verify | ||
run: mvn verify --batch-mode | ||
# Publish | ||
- name: Release Maven package (SNAPSHOT) | ||
run: mvn deploy -Pdeploy | ||
env: | ||
MAVEN_USERNAME: ${{ secrets.SONATYPE_USER }} | ||
MAVEN_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} | ||
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
name: verify | ||
|
||
on: | ||
push: | ||
branches-ignore: | ||
- main | ||
|
||
jobs: | ||
verify: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
# Checkout source code | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
# Setup Java environment | ||
- name: Set up JDK 17 | ||
uses: actions/setup-java@v4 | ||
with: | ||
distribution: temurin | ||
java-version: 17 | ||
- name: Maven setup | ||
uses: ./.github/actions/mvn-setup | ||
with: | ||
mgnl_nexus_user: ${{secrets.MGNL_NEXUS_USER}} | ||
mgnl_nexus_pass: ${{secrets.MGNL_NEXUS_PASS}} | ||
# Run maven verify | ||
- name: Maven verify | ||
run: mvn verify --batch-mode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# OS | ||
.DS_Store | ||
Thumbs.db | ||
|
||
target | ||
|
||
.idea | ||
*.iml | ||
|
||
#JRebel | ||
rebel.xml | ||
codesigning.asc |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# Magnolia setup task | ||
|
||
Setup task to help bootstrap magnolia. | ||
|
||
## Implementation | ||
|
||
```java | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.module.model.Version; | ||
|
||
import java.util.Optional; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
import com.merkle.oss.magnolia.setup.task.type.InstallAndUpdateTask; | ||
import com.merkle.oss.magnolia.setup.task.type.VersionAwareTask; | ||
|
||
public class SomeTask implements InstallAndUpdateTask { | ||
|
||
@Override | ||
public String getName() { | ||
return "someTask"; | ||
} | ||
|
||
@Override | ||
public String getDescription() { | ||
return "someTask description"; | ||
} | ||
|
||
@Override | ||
public void execute(InstallContext installContext) { | ||
//do stuff | ||
} | ||
|
||
//Optional | ||
@Override | ||
public boolean test(final Version forVersion, @Nullable final Version fromVersion) { | ||
return true; | ||
} | ||
|
||
//Optional | ||
@Override | ||
public Optional<VersionAwareTask> dependsOn() { | ||
return Optional.empty(); | ||
} | ||
} | ||
|
||
``` | ||
|
||
|
||
## Setup | ||
### Guice Set-Binding | ||
```java | ||
import com.google.inject.Binder; | ||
import com.google.inject.multibindings.Multibinder; | ||
|
||
import info.magnolia.objectfactory.guice.AbstractGuiceComponentConfigurer; | ||
|
||
public class CustomGuiceComponentConfigurer extends AbstractGuiceComponentConfigurer { | ||
@Override | ||
protected void configure() { | ||
super.configure(); | ||
final Multibinder<InstallTask> installTaskSetBinder = Multibinder.newSetBinder(binder(), InstallTask.class, Names.named("myModule")); | ||
installTaskSetBinder.addBinding().to(SomeInstallTask.class); | ||
... | ||
} | ||
} | ||
``` | ||
|
||
### Module version handler | ||
```xml | ||
<module> | ||
<name>myModule</name> | ||
<versionHandler>...MyModuleVersionHandler</versionHandler> | ||
... | ||
</module> | ||
``` | ||
```java | ||
import java.util.Set; | ||
|
||
import javax.inject.Inject; | ||
import javax.inject.Named; | ||
|
||
import com.merkle.oss.magnolia.setup.EnhancedModuleVersionHandler; | ||
import com.merkle.oss.magnolia.setup.task.type.InstallAndUpdateTask; | ||
import com.merkle.oss.magnolia.setup.task.type.InstallTask; | ||
import com.merkle.oss.magnolia.setup.task.type.LocalDevelopmentStartupTask; | ||
import com.merkle.oss.magnolia.setup.task.type.ModuleStartupTask; | ||
import com.merkle.oss.magnolia.setup.task.type.SnapshotStartupTask; | ||
import com.merkle.oss.magnolia.setup.task.type.UpdateTask; | ||
|
||
public class MyModuleVersionHandler extends EnhancedModuleVersionHandler { | ||
|
||
// Multibinding configured in SetupTasksGuiceComponentConfigurer | ||
@Inject | ||
public MyModuleVersionHandler( | ||
@Named("myModule") final Set<InstallTask> installTasks, | ||
@Named("myModule") final Set<UpdateTask> updateTasks, | ||
@Named("myModule") final Set<InstallAndUpdateTask> installAndUpdateTasks, | ||
@Named("myModule") final Set<ModuleStartupTask> moduleStartupTasks, | ||
@Named("myModule") final Set<SnapshotStartupTask> snapshotStartupTasks, | ||
@Named("myModule") final Set<LocalDevelopmentStartupTask> localDevelopmentStartupTasks | ||
) { | ||
super(installTasks, updateTasks, installAndUpdateTasks, moduleStartupTasks, snapshotStartupTasks, localDevelopmentStartupTasks); | ||
} | ||
|
||
@Override | ||
protected boolean isLocalDevelopmentEnvironment() { | ||
return false; //TODO implement | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>com.merkle.oss.magnolia</groupId> | ||
<artifactId>magnolia-setup-task</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>magnolia-setup-task-common</artifactId> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.merkle.oss.magnolia</groupId> | ||
<artifactId>magnolia-setup-task-core</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.namics.oss.magnolia</groupId> | ||
<artifactId>magnolia-powernode</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>info.magnolia.scheduler</groupId> | ||
<artifactId>magnolia-module-scheduler</artifactId> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>info.magnolia.ui</groupId> | ||
<artifactId>magnolia-ui-framework</artifactId> | ||
<scope>provided</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
59 changes: 59 additions & 0 deletions
59
...ain/java/com/merkle/oss/magnolia/setup/task/common/AbstractConfigureSchedulerJobTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.merkle.oss.magnolia.setup.task.common; | ||
|
||
import info.magnolia.jcr.nodebuilder.NodeOperation; | ||
import info.magnolia.jcr.nodebuilder.task.ErrorHandling; | ||
import info.magnolia.jcr.util.PropertyUtil; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.module.scheduler.JobDefinition; | ||
import info.magnolia.repository.RepositoryConstants; | ||
|
||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.stream.Stream; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
import org.apache.jackrabbit.value.ValueFactoryImpl; | ||
|
||
import com.merkle.oss.magnolia.powernode.NodeOperationFactory; | ||
import com.merkle.oss.magnolia.powernode.ValueConverter; | ||
import com.merkle.oss.magnolia.setup.task.nodebuilder.AbstractPathNodeBuilderTask; | ||
import com.merkle.oss.magnolia.setup.task.type.InstallAndUpdateTask; | ||
|
||
public abstract class AbstractConfigureSchedulerJobTask extends AbstractPathNodeBuilderTask implements InstallAndUpdateTask { | ||
private static final String PATH = "/modules/scheduler/config/jobs"; | ||
|
||
private final NodeOperationFactory ops; | ||
|
||
protected AbstractConfigureSchedulerJobTask( | ||
final NodeOperationFactory nodeOperationFactory, | ||
final String taskName, | ||
final String description, | ||
final ErrorHandling errorHandling | ||
) { | ||
super(taskName, description, errorHandling, RepositoryConstants.CONFIG, PATH); | ||
this.ops = nodeOperationFactory; | ||
} | ||
|
||
@Override | ||
protected NodeOperation[] getNodeOperations(InstallContext ctx) { | ||
return getJobs().map(this::configureJob).toArray(NodeOperation[]::new); | ||
} | ||
|
||
protected abstract Stream<JobDefinition> getJobs(); | ||
|
||
private NodeOperation configureJob(final JobDefinition jobDefinition) { | ||
return ops.getOrAddContentNode(jobDefinition.getName()).then( | ||
ops.setProperty("catalog", jobDefinition.getCatalog(), ValueConverter::toValue), | ||
ops.setProperty("command", jobDefinition.getCommand(), ValueConverter::toValue), | ||
ops.setProperty("cron", jobDefinition.getCron(), ValueConverter::toValue), | ||
ops.setProperty("description", Optional.ofNullable(jobDefinition.getDescription()).orElse(StringUtils.EMPTY), ValueConverter::toValue), | ||
ops.setProperty("concurrent", jobDefinition.isConcurrent(), ValueConverter::toValue), | ||
ops.getOrAddContentNode("params").then( | ||
((Map<String, Object>) jobDefinition.getParams()).entrySet().stream().map(entry -> | ||
ops.setProperty(entry.getKey(), entry.getValue(), (valueConverter, property) -> Optional.of(PropertyUtil.createValue(property, ValueFactoryImpl.getInstance()))) | ||
).toArray(NodeOperation[]::new) | ||
), | ||
ops.setEnabledProperty(jobDefinition.isEnabled()) | ||
); | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
...n/java/com/merkle/oss/magnolia/setup/task/common/AbstractInstallDialogFieldTypesTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package com.merkle.oss.magnolia.setup.task.common; | ||
|
||
import info.magnolia.jcr.nodebuilder.NodeOperation; | ||
import info.magnolia.jcr.nodebuilder.task.ErrorHandling; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.repository.RepositoryConstants; | ||
import info.magnolia.ui.field.ConfiguredFieldDefinition; | ||
import info.magnolia.ui.field.factory.AbstractFieldFactory; | ||
|
||
import java.lang.invoke.MethodHandles; | ||
import java.text.MessageFormat; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.merkle.oss.magnolia.powernode.NodeOperationFactory; | ||
import com.merkle.oss.magnolia.powernode.ValueConverter; | ||
import com.merkle.oss.magnolia.setup.task.nodebuilder.AbstractPathNodeBuilderTask; | ||
|
||
/** | ||
* Base class for dialog field type install tasks. | ||
*/ | ||
public abstract class AbstractInstallDialogFieldTypesTask extends AbstractPathNodeBuilderTask { | ||
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); | ||
|
||
private static final String TASK_NAME = "Install Dialog Field Types"; | ||
private static final String TASK_DESCRIPTION = "Install Dialog Field Types"; | ||
|
||
public static final String MODULE_PATH = "modules/{0}"; | ||
|
||
private final NodeOperationFactory ops; | ||
private final String fieldTypeName; | ||
private final Class<? extends ConfiguredFieldDefinition> definitionClass; | ||
private final Class<? extends AbstractFieldFactory> factoryClass; | ||
|
||
protected AbstractInstallDialogFieldTypesTask( | ||
final NodeOperationFactory nodeOperationFactory, | ||
final String fieldTypeName, | ||
final Class<? extends ConfiguredFieldDefinition> definitionClass, | ||
final Class<? extends AbstractFieldFactory> factoryClass | ||
) { | ||
super(TASK_NAME, TASK_DESCRIPTION, ErrorHandling.strict, RepositoryConstants.CONFIG); | ||
this.ops = nodeOperationFactory; | ||
this.fieldTypeName = fieldTypeName; | ||
this.definitionClass = definitionClass; | ||
this.factoryClass = factoryClass; | ||
} | ||
|
||
@Override | ||
protected NodeOperation[] getNodeOperations(final InstallContext ctx) { | ||
final String moduleName = ctx.getCurrentModuleDefinition().getName(); | ||
final String modulePath = MessageFormat.format(MODULE_PATH, moduleName); | ||
LOG.info("installing dialogFieldType '{}' for module {}", fieldTypeName, modulePath); | ||
return new NodeOperation[]{ | ||
ops.getOrAddContentNode(modulePath).then( | ||
ops.getOrAddContentNode("fieldTypes").then( | ||
ops.getOrAddContentNode(fieldTypeName).then( | ||
ops.setProperty("definitionClass", definitionClass.getName(), ValueConverter::toValue), | ||
ops.setProperty("factoryClass", factoryClass.getName(), ValueConverter::toValue) | ||
) | ||
) | ||
) | ||
}; | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
...sk/src/main/java/com/merkle/oss/magnolia/setup/task/common/AbstractInstallFilterTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package com.merkle.oss.magnolia.setup.task.common; | ||
|
||
import com.merkle.oss.magnolia.powernode.NodeOperationFactory; | ||
import com.merkle.oss.magnolia.setup.task.nodebuilder.AbstractPathNodeBuilderTask; | ||
import com.merkle.oss.magnolia.powernode.ValueConverter; | ||
import info.magnolia.cms.filters.FilterManager; | ||
import info.magnolia.cms.filters.MgnlFilter; | ||
import info.magnolia.jcr.nodebuilder.NodeOperation; | ||
import info.magnolia.jcr.nodebuilder.task.ErrorHandling; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.module.delta.FilterOrderingTask; | ||
import info.magnolia.module.delta.TaskExecutionException; | ||
import info.magnolia.repository.RepositoryConstants; | ||
|
||
import javax.jcr.RepositoryException; | ||
import java.util.Arrays; | ||
import java.util.stream.Stream; | ||
|
||
public abstract class AbstractInstallFilterTask extends AbstractPathNodeBuilderTask { | ||
protected final NodeOperationFactory ops; | ||
private final Class<? extends MgnlFilter> filterClass; | ||
private final String filterName; | ||
private final String[] requiredFiltersBefore; | ||
|
||
/** | ||
* Installs a Filter into the filter chain (and replaces an existing filter at the same place with the same name) | ||
* | ||
* @param filterClass class of the magnolia filter | ||
* @param filterName name of the node the filter should be created in. Must be a relative path below the root path of the filter chain (/server/filters) | ||
* @param requiredFiltersBefore an array of filter names that must appear before the filter specified as filterName. | ||
*/ | ||
protected AbstractInstallFilterTask( | ||
final NodeOperationFactory nodeOperationFactory, | ||
final Class<? extends MgnlFilter> filterClass, | ||
final String filterName, | ||
final String... requiredFiltersBefore | ||
) { | ||
super( | ||
"Install Filter " + filterName + "(" + filterClass + ")", | ||
"", | ||
ErrorHandling.strict, | ||
RepositoryConstants.CONFIG, | ||
FilterManager.SERVER_FILTERS | ||
); | ||
this.ops = nodeOperationFactory; | ||
this.filterClass = filterClass; | ||
this.filterName = filterName; | ||
this.requiredFiltersBefore = requiredFiltersBefore; | ||
} | ||
|
||
@Override | ||
protected final void doExecute(final InstallContext installContext) throws RepositoryException, TaskExecutionException { | ||
super.doExecute(installContext); | ||
new FilterOrderingTask(filterName, requiredFiltersBefore).execute(installContext); | ||
} | ||
|
||
@Override | ||
protected final NodeOperation[] getNodeOperations(InstallContext ctx) { | ||
return new NodeOperation[]{ | ||
ops.getOrAddNode(filterName).then( | ||
append( | ||
getFilterNodeOperations(), | ||
ops.setProperty("class", filterClass.getName(), ValueConverter::toValue), | ||
ops.setProperty("enabled", true, ValueConverter::toValue) | ||
) | ||
) | ||
}; | ||
} | ||
|
||
private NodeOperation[] append(final NodeOperation[] ops1, final NodeOperation... ops2) { | ||
return Stream | ||
.concat( | ||
Arrays.stream(ops1), | ||
Arrays.stream(ops2) | ||
) | ||
.toArray(NodeOperation[]::new); | ||
} | ||
|
||
/** | ||
* NodeOperations to be executed in the context of the newly created filter node. | ||
*/ | ||
protected NodeOperation[] getFilterNodeOperations() { | ||
return new NodeOperation[]{}; | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
common-task/src/main/java/com/merkle/oss/magnolia/setup/task/common/InstallLicenseTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.merkle.oss.magnolia.setup.task.common; | ||
|
||
import info.magnolia.init.MagnoliaConfigurationProperties; | ||
import info.magnolia.jcr.nodebuilder.NodeOperation; | ||
import info.magnolia.jcr.nodebuilder.task.ErrorHandling; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.repository.RepositoryConstants; | ||
|
||
import java.util.Optional; | ||
|
||
import javax.inject.Inject; | ||
|
||
import com.merkle.oss.magnolia.powernode.NodeOperationFactory; | ||
import com.merkle.oss.magnolia.powernode.ValueConverter; | ||
import com.merkle.oss.magnolia.setup.task.nodebuilder.AbstractPathNodeBuilderTask; | ||
import com.merkle.oss.magnolia.setup.task.type.InstallAndUpdateTask; | ||
import com.merkle.oss.magnolia.setup.task.type.LocalDevelopmentStartupTask; | ||
|
||
/** | ||
* Configure magnolia license. | ||
* <p> | ||
* Use the following properties in magnolia.properties: | ||
* <p> | ||
* magnolia.license.owner= | ||
* magnolia.license.key= | ||
* <p> | ||
* - Add to according 'ModuleVersionHandler' in a project | ||
* - Execute as getInstallAndUpdateTask | ||
*/ | ||
public class InstallLicenseTask extends AbstractPathNodeBuilderTask implements InstallAndUpdateTask { | ||
private static final String TASK_NAME = "Install License Task"; | ||
private static final String TASK_DESCRIPTION = "This task installs the Magnolia license."; | ||
private static final String PATH = "/modules/enterprise"; | ||
|
||
private final MagnoliaConfigurationProperties properties; | ||
private final NodeOperationFactory ops; | ||
|
||
@Inject | ||
public InstallLicenseTask( | ||
final NodeOperationFactory nodeOperationFactory, | ||
final MagnoliaConfigurationProperties properties | ||
) { | ||
super(TASK_NAME, TASK_DESCRIPTION, ErrorHandling.strict, RepositoryConstants.CONFIG, PATH); | ||
this.ops = nodeOperationFactory; | ||
this.properties = properties; | ||
} | ||
|
||
@Override | ||
protected NodeOperation[] getNodeOperations(final InstallContext ctx) { | ||
return getOwner().flatMap(owner -> getKey().map(key -> | ||
ops.getOrAddContentNode("license").then( | ||
ops.setProperty("owner", owner, ValueConverter::toValue), | ||
ops.setProperty("key", key, ValueConverter::toValue) | ||
) | ||
)).stream().toArray(NodeOperation[]::new); | ||
} | ||
|
||
private Optional<String> getOwner() { | ||
return getProperty("magnolia.license.owner"); | ||
} | ||
|
||
private Optional<String> getKey() { | ||
return getProperty("magnolia.license.key"); | ||
} | ||
|
||
private Optional<String> getProperty(final String key) { | ||
return Optional.ofNullable(properties.getProperty(key)); | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
...-task/src/main/java/com/merkle/oss/magnolia/setup/task/common/ReregisterServletsTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package com.merkle.oss.magnolia.setup.task.common; | ||
|
||
import info.magnolia.jcr.util.NodeNameHelper; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.module.delta.ArrayDelegateTask; | ||
import info.magnolia.module.delta.RegisterServletTask; | ||
import info.magnolia.module.delta.TaskExecutionException; | ||
import info.magnolia.module.model.ModuleDefinition; | ||
import info.magnolia.module.model.ServletDefinition; | ||
|
||
import javax.inject.Inject; | ||
import javax.jcr.RepositoryException; | ||
import javax.jcr.Session; | ||
|
||
import com.merkle.oss.magnolia.setup.task.type.InstallAndUpdateTask; | ||
|
||
/** | ||
* Reregistering servlets. Normally they only get registered on install, but not on update (info.magnolia.module.delta.RegisterModuleServletsTask) | ||
*/ | ||
public class ReregisterServletsTask extends ArrayDelegateTask implements InstallAndUpdateTask { | ||
private static final String DEFAULT_SERVLET_FILTER_PATH = "server/filters/servlets"; | ||
private final NodeNameHelper nodeNameHelper; | ||
|
||
@Inject | ||
public ReregisterServletsTask(final NodeNameHelper nodeNameHelper) { | ||
super("Reregister module servlets", "Reregisters servlets for this module."); | ||
this.nodeNameHelper = nodeNameHelper; | ||
} | ||
|
||
@Override | ||
public void execute(InstallContext installContext) throws TaskExecutionException { | ||
final ModuleDefinition moduleDefinition = installContext.getCurrentModuleDefinition(); | ||
for (ServletDefinition servletDefinition : moduleDefinition.getServlets()) { | ||
addTask(new ReregisterServletTask(servletDefinition, nodeNameHelper)); | ||
} | ||
super.execute(installContext); | ||
} | ||
|
||
private static class ReregisterServletTask extends RegisterServletTask { | ||
public ReregisterServletTask(ServletDefinition servletDefinition, NodeNameHelper nodeNameHelper) { | ||
super(servletDefinition, nodeNameHelper); | ||
} | ||
|
||
@Override | ||
public void execute(final InstallContext installContext) throws TaskExecutionException { | ||
if(!isRegistered(installContext)) { | ||
super.execute(installContext); | ||
} | ||
} | ||
|
||
private boolean isRegistered(final InstallContext installContext) throws TaskExecutionException { | ||
try { | ||
final Session session = installContext.getConfigJCRSession(); | ||
return session.getRootNode().hasNode(DEFAULT_SERVLET_FILTER_PATH + "/" + getServletDefinition().getName()); | ||
} catch (RepositoryException e) { | ||
throw new TaskExecutionException("Failed to reregister servlet "+getServletDefinition().getName(), e); | ||
} | ||
} | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
...src/main/java/com/merkle/oss/magnolia/setup/task/common/SetEmptyDefaultExtensionTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.merkle.oss.magnolia.setup.task.common; | ||
|
||
import com.merkle.oss.magnolia.powernode.NodeOperationFactory; | ||
import com.merkle.oss.magnolia.powernode.ValueConverter; | ||
import com.merkle.oss.magnolia.setup.task.nodebuilder.AbstractPathNodeBuilderTask; | ||
import com.merkle.oss.magnolia.setup.task.type.InstallAndUpdateTask; | ||
|
||
import info.magnolia.jcr.nodebuilder.NodeOperation; | ||
import info.magnolia.jcr.nodebuilder.task.ErrorHandling; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.repository.RepositoryConstants; | ||
import org.apache.commons.lang3.StringUtils; | ||
|
||
import javax.inject.Inject; | ||
|
||
public class SetEmptyDefaultExtensionTask extends AbstractPathNodeBuilderTask implements InstallAndUpdateTask { | ||
private static final String TASK_NAME = "Set default Extension"; | ||
private static final String TASK_DESCRIPTION = "Set default Extension"; | ||
private static final String ACTIONS_PATH = "/server"; | ||
private final NodeOperationFactory ops; | ||
|
||
@Inject | ||
public SetEmptyDefaultExtensionTask(final NodeOperationFactory nodeOperationFactory) { | ||
super(TASK_NAME, TASK_DESCRIPTION, ErrorHandling.strict, RepositoryConstants.CONFIG, ACTIONS_PATH); | ||
ops = nodeOperationFactory; | ||
} | ||
|
||
@Override | ||
protected NodeOperation[] getNodeOperations(final InstallContext ctx) { | ||
return new NodeOperation[]{ | ||
ops.setProperty("defaultExtension", StringUtils.EMPTY, ValueConverter::toValue) | ||
}; | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
common-task/src/main/java/com/merkle/oss/magnolia/setup/task/common/SetupSmtpTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package com.merkle.oss.magnolia.setup.task.common; | ||
|
||
import com.merkle.oss.magnolia.powernode.NodeOperationFactory; | ||
import com.merkle.oss.magnolia.powernode.PowerNode; | ||
import com.merkle.oss.magnolia.powernode.PowerNodeService; | ||
import com.merkle.oss.magnolia.powernode.ValueConverter; | ||
import com.merkle.oss.magnolia.setup.task.nodebuilder.AbstractPathNodeBuilderTask; | ||
import com.merkle.oss.magnolia.setup.task.type.InstallAndUpdateTask; | ||
|
||
import info.magnolia.init.MagnoliaConfigurationProperties; | ||
import info.magnolia.jcr.nodebuilder.NodeOperation; | ||
import info.magnolia.jcr.nodebuilder.Ops; | ||
import info.magnolia.jcr.nodebuilder.task.ErrorHandling; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.objectfactory.Components; | ||
import info.magnolia.repository.RepositoryConstants; | ||
|
||
import javax.inject.Inject; | ||
import java.util.Optional; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
|
||
/** | ||
* Configure SMTP server. | ||
* <p> | ||
* Use the following properties in magnolia.properties: | ||
* <p> | ||
* magnolia.smtp.security=none|ssl|tls | ||
* magnolia.smtp.auth=null|userPassword | ||
* magnolia.smtp.user=user | ||
* magnolia.smtp.keystorePath=/folder/smtp # get path from the password app | ||
* magnolia.smtp.server=mailgateway.sg.ch.namics.com | ||
* magnolia.smtp.port=25 | ||
* <p> | ||
* - Add to according 'ModuleVersionHandler' in a project | ||
* - Execute as getInstallAndUpdateTask | ||
*/ | ||
public class SetupSmtpTask extends AbstractPathNodeBuilderTask implements InstallAndUpdateTask { | ||
private static final String TASK_NAME = "SetupSmtpTask"; | ||
private static final String TASK_DESCRIPTION = "Set SMTP configuration from magnolia.properties"; | ||
|
||
private static final String MAIL_MODULE_CONFIG_PATH = "/modules/mail/config"; | ||
|
||
private final MagnoliaConfigurationProperties properties; | ||
private final PowerNodeService powerNodeService; | ||
private final NodeOperationFactory ops; | ||
|
||
@Inject | ||
public SetupSmtpTask( | ||
final PowerNodeService powerNodeService, | ||
final NodeOperationFactory nodeOperationFactory | ||
) { | ||
super(TASK_NAME, TASK_DESCRIPTION, ErrorHandling.strict, RepositoryConstants.CONFIG, MAIL_MODULE_CONFIG_PATH); | ||
this.powerNodeService = powerNodeService; | ||
this.ops = nodeOperationFactory; | ||
this.properties = Components.getComponent(MagnoliaConfigurationProperties.class); | ||
} | ||
|
||
@Override | ||
protected NodeOperation[] getNodeOperations(final InstallContext ctx) { | ||
final String security = getProperty("magnolia.smtp.security", "none"); | ||
final String auth = getProperty("magnolia.smtp.auth", "null"); | ||
final String server = getProperty("magnolia.smtp.server", "localhost"); | ||
final String port = getProperty("magnolia.smtp.port", "25"); | ||
final String user = getProperty("magnolia.smtp.user", StringUtils.EMPTY); | ||
final String keystorePath = getProperty("magnolia.smtp.keystorePath", StringUtils.EMPTY); | ||
|
||
return new NodeOperation[]{ | ||
ops.getOrAddContentNode("smtpConfiguration").then( | ||
ops.getOrAddNode("authentication").then(ops.clearProperties().then( | ||
getAuth(auth, user, keystorePath) | ||
)), | ||
ops.setProperty("server", server, ValueConverter::toValue), | ||
ops.setProperty("port", port, ValueConverter::toValue), | ||
ops.setProperty("security", security, ValueConverter::toValue) | ||
) | ||
}; | ||
} | ||
|
||
private NodeOperation[] getAuth(final String auth, final String user, final String keystorePath) { | ||
if ("userPassword".equals(auth)) { | ||
return getUserPasswordAuth(user, getKeystoreId(keystorePath).orElse(null)); | ||
} | ||
return getNullAuth(); | ||
} | ||
|
||
private Optional<String> getKeystoreId(final String keystorePath) { | ||
return powerNodeService.getByPath("keystore", keystorePath).map(PowerNode::getIdentifier); | ||
} | ||
|
||
private NodeOperation[] getUserPasswordAuth(final String user, final String passwordKeyStoreId) { | ||
return new NodeOperation[]{ | ||
ops.setProperty("class", "info.magnolia.module.mail.smtp.authentication.UsernamePasswordSmtpAuthentication", ValueConverter::toValue), | ||
ops.setProperty("user", user, ValueConverter::toValue), | ||
passwordKeyStoreId != null ? ops.setProperty("passwordKeyStoreId", passwordKeyStoreId, ValueConverter::toValue) : Ops.noop() | ||
}; | ||
} | ||
|
||
private NodeOperation[] getNullAuth() { | ||
return new NodeOperation[]{ | ||
ops.setProperty("class", "info.magnolia.module.mail.smtp.authentication.NullSmtpAuthentication", ValueConverter::toValue) | ||
}; | ||
} | ||
|
||
private String getProperty(final String name, final String fallback) { | ||
if (properties.hasProperty(name)) { | ||
return properties.getProperty(name); | ||
} | ||
return fallback; | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
...c/main/java/com/merkle/oss/magnolia/setup/task/common/security/util/GroupManagerUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.merkle.oss.magnolia.setup.task.common.security.util; | ||
|
||
import info.magnolia.cms.security.AccessDeniedException; | ||
import info.magnolia.cms.security.Group; | ||
import info.magnolia.cms.security.GroupManager; | ||
import info.magnolia.cms.security.SecuritySupport; | ||
|
||
import java.lang.invoke.MethodHandles; | ||
import java.util.Arrays; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Collectors; | ||
|
||
import javax.inject.Inject; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class GroupManagerUtil { | ||
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); | ||
private final Supplier<GroupManager> groupManager; | ||
|
||
@Inject | ||
public GroupManagerUtil(final SecuritySupport securitySupport) { | ||
groupManager = securitySupport::getGroupManager; | ||
} | ||
|
||
public Set<Group> getGroups(final String... groupNames) { | ||
return Arrays.stream(groupNames) | ||
.map(this::getGroup) | ||
.flatMap(Optional::stream) | ||
.collect(Collectors.toSet()); | ||
} | ||
|
||
public Optional<Group> getGroup(final String groupName) { | ||
try { | ||
return Optional.ofNullable(groupManager.get().getGroup(groupName)); | ||
} catch (AccessDeniedException e) { | ||
LOG.error("Access denied to get group " + groupName, e); | ||
return Optional.empty(); | ||
} | ||
} | ||
} |
123 changes: 123 additions & 0 deletions
123
...rc/main/java/com/merkle/oss/magnolia/setup/task/common/security/util/RoleManagerUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package com.merkle.oss.magnolia.setup.task.common.security.util; | ||
|
||
import info.magnolia.cms.security.Permission; | ||
import info.magnolia.cms.security.Role; | ||
import info.magnolia.cms.security.RoleManager; | ||
import info.magnolia.cms.security.SecuritySupport; | ||
import info.magnolia.cms.security.SilentSessionOp; | ||
import info.magnolia.cms.security.auth.ACL; | ||
import info.magnolia.context.MgnlContext; | ||
import info.magnolia.jcr.util.NodeTypes; | ||
import info.magnolia.jcr.util.NodeUtil; | ||
import info.magnolia.repository.RepositoryConstants; | ||
|
||
import java.util.Arrays; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
import java.util.function.Predicate; | ||
import java.util.function.Supplier; | ||
|
||
import javax.annotation.Nullable; | ||
import javax.inject.Inject; | ||
import javax.jcr.Node; | ||
import javax.jcr.RepositoryException; | ||
import javax.jcr.Session; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
|
||
public class RoleManagerUtil { | ||
private static final String WEB_ACCESS_WORKSPACE = "uri"; | ||
private final Supplier<RoleManager> roleManager; | ||
|
||
@Inject | ||
public RoleManagerUtil(final SecuritySupport securitySupport) { | ||
roleManager = securitySupport::getRoleManager; | ||
} | ||
|
||
public Optional<Role> getRole(final String name) { | ||
return Optional.ofNullable(roleManager.get().getRole(name)); | ||
} | ||
|
||
public Role getOrCreateRole(final String name) throws Exception { | ||
return getOrCreateRole(null, name); | ||
} | ||
|
||
public Role getOrCreateRole(@Nullable final String path, final String name) throws Exception { | ||
@Nullable final Role role = getRole(name).orElse(null); | ||
if (role == null) { | ||
final Node parent = getOrCreateNode(path); | ||
return roleManager.get().createRole(parent.getPath(), name); | ||
} | ||
return role; | ||
} | ||
|
||
private Node getOrCreateNode(@Nullable final String path) { | ||
return MgnlContext.doInSystemContext(new SilentSessionOp<>(RepositoryConstants.USER_ROLES) { | ||
@Override | ||
public Node doExec(final Session session) throws RepositoryException { | ||
if(path != null) { | ||
return NodeUtil.createPath(session.getRootNode(), StringUtils.removeStart(path, "/"), NodeTypes.Folder.NAME); | ||
} | ||
return session.getRootNode(); | ||
} | ||
}); | ||
} | ||
|
||
public void addWebAccess(final Role role, final long permission, final String... paths) { | ||
addPermission(role, WEB_ACCESS_WORKSPACE, permission, paths); | ||
} | ||
|
||
public void removeWebAccess(final Role role, final long permission, final String... paths) { | ||
removePermission(role, WEB_ACCESS_WORKSPACE, permission, paths); | ||
} | ||
|
||
public void removeAllWebAccess(final Role role) { | ||
removePermissions(role, WEB_ACCESS_WORKSPACE, permission -> true); | ||
} | ||
|
||
public void setPermission(final Role role, final String workspace, final long permission, final String... paths) { | ||
removePermissions(role, workspace, paths); | ||
addPermission(role, workspace, permission, paths); | ||
} | ||
|
||
public void addPermission(final Role role, final String workspace, final long permission, final String... paths) { | ||
Arrays.stream(paths).forEach(path -> | ||
roleManager.get().addPermission(role, workspace, path, permission) | ||
); | ||
} | ||
|
||
public void removePermission(final Role role, final String workspace, final long permission, final String... paths) { | ||
Arrays.stream(paths).forEach(path -> | ||
roleManager.get().removePermission(role, workspace, path, permission) | ||
); | ||
} | ||
|
||
public void removePermissions(final Role role, final String workspace, final String... paths) { | ||
removePermissions(role, workspace, permission -> Set.of(paths).contains(permission.getPattern().getPatternString())); | ||
} | ||
|
||
public void removeAllPermissions(final Role role) { | ||
roleManager.get().getACLs(role.getName()).entrySet().stream() | ||
.filter(entry -> !WEB_ACCESS_WORKSPACE.equals(entry.getKey())) | ||
.forEach(entry -> | ||
removePermissions(role, entry.getKey(), entry.getValue(), permission -> true) | ||
); | ||
} | ||
|
||
private void removePermissions(final Role role, final String workspace, final Predicate<Permission> filter) { | ||
Optional.ofNullable(roleManager.get().getACLs(role.getName()).get(workspace)).ifPresent(acls -> | ||
removePermissions(role, workspace, acls, filter) | ||
); | ||
} | ||
|
||
private void removePermissions(final Role role, final String workspace, final ACL acl, final Predicate<Permission> filter) { | ||
acl.getList().stream().filter(filter).forEach(permission -> | ||
removePermission( | ||
role, | ||
workspace, | ||
permission.getPermissions(), | ||
permission.getPattern().getPatternString() | ||
) | ||
); | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
...rc/main/java/com/merkle/oss/magnolia/setup/task/common/security/util/UserManagerUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.merkle.oss.magnolia.setup.task.common.security.util; | ||
|
||
import info.magnolia.cms.security.Group; | ||
import info.magnolia.cms.security.MgnlUserManager; | ||
import info.magnolia.cms.security.Realm; | ||
import info.magnolia.cms.security.Role; | ||
import info.magnolia.cms.security.SecuritySupport; | ||
import info.magnolia.cms.security.User; | ||
import info.magnolia.cms.security.UserManager; | ||
|
||
import java.util.Optional; | ||
import java.util.Set; | ||
import java.util.function.Supplier; | ||
|
||
import javax.inject.Inject; | ||
|
||
import org.apache.http.auth.Credentials; | ||
|
||
public class UserManagerUtil { | ||
private final Supplier<UserManager> userManager; | ||
|
||
public UserManagerUtil( | ||
final SecuritySupport securitySupport, | ||
final Realm realm | ||
) { | ||
userManager = () -> securitySupport.getUserManager(realm.getName()); | ||
} | ||
|
||
public Optional<User> getUser(final String username) { | ||
return Optional.ofNullable(userManager.get().getUser(username)); | ||
} | ||
|
||
public Optional<User> getOrCreateUserAndSetPassword(final Credentials credentials, final Set<Group> groups, final Set<Role> roles) { | ||
final User user = getOrCreateUserAndSetPassword(credentials.getUserPrincipal().getName(), credentials.getPassword()); | ||
for (String group : user.getGroups()) { | ||
if(groups.stream().map(Group::getName).noneMatch(group::equals)) { | ||
userManager.get().removeGroup(user, group); | ||
} | ||
} | ||
for (Group group : groups) { | ||
userManager.get().addGroup(user, group.getName()); | ||
} | ||
for (String role : user.getRoles()) { | ||
if(roles.stream().map(Role::getName).noneMatch(role::equals)) { | ||
userManager.get().removeRole(user, role); | ||
} | ||
} | ||
for (Role role : roles) { | ||
userManager.get().addRole(user, role.getName()); | ||
} | ||
return Optional.ofNullable(userManager.get().getUser(user.getName())); | ||
} | ||
|
||
private User getOrCreateUserAndSetPassword(final String name, final String password) { | ||
return Optional | ||
.ofNullable(userManager.get().getUser(name)) | ||
.map(user -> userManager.get().changePassword(user, password)) | ||
.orElseGet(() -> userManager.get().createUser(name, password)); | ||
} | ||
|
||
public void enable(final User user) { | ||
userManager.get().setProperty(user, MgnlUserManager.PROPERTY_ENABLED, "true"); | ||
} | ||
|
||
public static class Factory { | ||
private final SecuritySupport securitySupport; | ||
|
||
@Inject | ||
public Factory(final SecuritySupport securitySupport) { | ||
this.securitySupport = securitySupport; | ||
} | ||
|
||
public UserManagerUtil create(final Realm realm) { | ||
return new UserManagerUtil(securitySupport, realm); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>com.merkle.oss.magnolia</groupId> | ||
<artifactId>magnolia-setup-task</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>magnolia-setup-task-core</artifactId> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>info.magnolia</groupId> | ||
<artifactId>magnolia-core</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.code.findbugs</groupId> | ||
<artifactId>jsr305</artifactId> | ||
</dependency> | ||
|
||
<!-- TESTING DEPENDENCIES --> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
127 changes: 127 additions & 0 deletions
127
core/src/main/java/com/merkle/oss/magnolia/setup/EnhancedModuleVersionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package com.merkle.oss.magnolia.setup; | ||
|
||
import info.magnolia.module.DefaultModuleVersionHandler; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.module.delta.Delta; | ||
import info.magnolia.module.delta.DeltaBuilder; | ||
import info.magnolia.module.delta.Task; | ||
import info.magnolia.module.model.Version; | ||
|
||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.function.Function; | ||
import java.util.stream.Stream; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
import com.merkle.oss.magnolia.setup.task.type.DepdendsOnComparator; | ||
import com.merkle.oss.magnolia.setup.task.type.InstallAndUpdateTask; | ||
import com.merkle.oss.magnolia.setup.task.type.InstallTask; | ||
import com.merkle.oss.magnolia.setup.task.type.LocalDevelopmentStartupTask; | ||
import com.merkle.oss.magnolia.setup.task.type.ModuleStartupTask; | ||
import com.merkle.oss.magnolia.setup.task.type.SnapshotStartupTask; | ||
import com.merkle.oss.magnolia.setup.task.type.UpdateTask; | ||
import com.merkle.oss.magnolia.setup.task.type.VersionAwareTask; | ||
|
||
public abstract class EnhancedModuleVersionHandler extends DefaultModuleVersionHandler { | ||
private final Set<InstallTask> installTasks; | ||
private final Set<UpdateTask> updateTasks; | ||
private final Set<InstallAndUpdateTask> installAndUpdateTasks; | ||
private final Set<ModuleStartupTask> moduleStartupTasks; | ||
private final Set<SnapshotStartupTask> snapshotStartupTasks; | ||
private final Set<LocalDevelopmentStartupTask> localDevelopmentStartupTasks; | ||
|
||
protected EnhancedModuleVersionHandler( | ||
final Set<InstallTask> installTasks, | ||
final Set<UpdateTask> updateTasks, | ||
final Set<InstallAndUpdateTask> installAndUpdateTasks, | ||
final Set<ModuleStartupTask> moduleStartupTasks, | ||
final Set<SnapshotStartupTask> snapshotStartupTasks, | ||
final Set<LocalDevelopmentStartupTask> localDevelopmentStartupTasks | ||
) { | ||
this.installTasks = installTasks; | ||
this.updateTasks = updateTasks; | ||
this.installAndUpdateTasks = installAndUpdateTasks; | ||
this.moduleStartupTasks = moduleStartupTasks; | ||
this.snapshotStartupTasks = snapshotStartupTasks; | ||
this.localDevelopmentStartupTasks = localDevelopmentStartupTasks; | ||
} | ||
|
||
@Override | ||
public List<Delta> getDeltas(final InstallContext installContext, @Nullable final Version versionFrom) { | ||
final Version forVersion = installContext.getCurrentModuleDefinition().getVersion(); | ||
return Stream.concat( | ||
super.getDeltas(installContext, versionFrom).stream(), | ||
getDeltas(installContext, forVersion, versionFrom) | ||
).toList(); | ||
} | ||
|
||
private Stream<Delta> getDeltas(final InstallContext installContext, final Version forVersion, @Nullable final Version versionFrom) { | ||
return Stream.of( | ||
getInstallAndUpdateTasksDelta(installContext, forVersion, versionFrom), | ||
getStartupTasksDelta(installContext, forVersion, versionFrom) | ||
); | ||
} | ||
|
||
private Delta getInstallAndUpdateTasksDelta(final InstallContext installContext, final Version forVersion, @Nullable final Version versionFrom) { | ||
final boolean isUpdate = forVersion.isStrictlyAfter(versionFrom); | ||
final boolean isInstall = versionFrom == null; | ||
|
||
return DeltaBuilder.install(forVersion, "setup-task install and update").addTasks(Stream.of( | ||
isInstall ? getInstallTasks(installContext, forVersion) : Stream.<Task>empty(), | ||
isUpdate ? getInstallAndUpdateTasks(installContext, forVersion, null) : Stream.<Task>empty(), | ||
(isInstall || isUpdate)? getUpdateTasks(installContext, forVersion, versionFrom) : Stream.<Task>empty() | ||
).flatMap(Function.identity()).sorted(new DepdendsOnComparator()).toList()); | ||
} | ||
|
||
private Delta getStartupTasksDelta(final InstallContext installContext, final Version forVersion, @Nullable final Version versionFrom) { | ||
return DeltaBuilder.startup(forVersion, "setup-task startup").addTasks( Stream.of( | ||
getModuleStartupTasks(installContext, forVersion, versionFrom), | ||
isSnapshot(forVersion) ? getSnapshotStartupTasks(installContext, forVersion, versionFrom) : Stream.<Task>empty(), | ||
isLocalDevelopmentEnvironment() ? getLocalDevelopmentStartupTasks(installContext, forVersion, versionFrom) : Stream.<Task>empty() | ||
).flatMap(Function.identity()).sorted(new DepdendsOnComparator()).toList()); | ||
} | ||
|
||
protected abstract boolean isLocalDevelopmentEnvironment(); | ||
|
||
private boolean isSnapshot(final Version version) { | ||
return "SNAPSHOT".equalsIgnoreCase(version.getClassifier()); | ||
} | ||
|
||
protected Stream<Task> getInstallTasks(final InstallContext installContext, final Version forVersion) { | ||
return filter(installTasks, forVersion, null); | ||
} | ||
|
||
protected Stream<Task> getInstallAndUpdateTasks(final InstallContext installContext, final Version forVersion, @Nullable final Version fromVersion) { | ||
return filter(installAndUpdateTasks, forVersion, fromVersion); | ||
} | ||
|
||
protected Stream<Task> getUpdateTasks(final InstallContext installContext, final Version forVersion, @Nullable final Version fromVersion) { | ||
return filter(updateTasks, forVersion, fromVersion); | ||
} | ||
|
||
protected Stream<Task> getModuleStartupTasks(final InstallContext installContext, final Version forVersion, @Nullable final Version fromVersion) { | ||
return filter(moduleStartupTasks, forVersion, fromVersion); | ||
} | ||
|
||
protected Stream<Task> getSnapshotStartupTasks(final InstallContext installContext, final Version forVersion, @Nullable final Version fromVersion) { | ||
return Stream.of( | ||
filter(snapshotStartupTasks, forVersion, fromVersion), | ||
// execute all general install and update tasks on snapshot | ||
getInstallAndUpdateTasks(installContext, forVersion, fromVersion), | ||
getUpdateTasks(installContext, forVersion, fromVersion) | ||
).flatMap(Function.identity()); | ||
} | ||
|
||
protected Stream<Task> getLocalDevelopmentStartupTasks(final InstallContext installContext, final Version forVersion, @Nullable final Version fromVersion) { | ||
return filter(localDevelopmentStartupTasks, forVersion, fromVersion); | ||
} | ||
|
||
protected Stream<Task> filter(final Collection<? extends VersionAwareTask> tasks, final Version forVersion, @Nullable final Version fromVersion) { | ||
return tasks | ||
.stream() | ||
.filter(task -> task.test(forVersion, fromVersion)) | ||
.map(task -> task); | ||
} | ||
} |
119 changes: 119 additions & 0 deletions
119
core/src/main/java/com/merkle/oss/magnolia/setup/task/TaskExecutor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package com.merkle.oss.magnolia.setup.task; | ||
|
||
import info.magnolia.module.InstallContextImpl; | ||
import info.magnolia.module.InstallStatus; | ||
import info.magnolia.module.ModuleRegistry; | ||
import info.magnolia.module.delta.Delta; | ||
import info.magnolia.module.delta.Task; | ||
import info.magnolia.module.delta.TaskExecutionException; | ||
import info.magnolia.module.model.ModuleDefinition; | ||
import info.magnolia.module.model.Version; | ||
import info.magnolia.objectfactory.ComponentProvider; | ||
|
||
import java.util.Collection; | ||
import java.util.HashSet; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
|
||
import javax.annotation.Nullable; | ||
import javax.inject.Inject; | ||
import javax.jcr.RepositoryException; | ||
import javax.jcr.Session; | ||
|
||
/** | ||
* Can be used to execute tasks from magnolia groovy console: | ||
* <pre>{@code | ||
* import com.namics.common.setup.task.TaskExecutor; | ||
* import info.magnolia.objectfactory.Components; | ||
* | ||
* final TaskExecutor executor = Components.newInstance(TaskExecutor.class); | ||
* executor.execute(com.namics.snb.web.setup.task.migration.VisionTeaserTargetNodeNameMigrationTask.class) | ||
* }</pre> | ||
*/ | ||
public class TaskExecutor { | ||
private final ModuleRegistry moduleRegistry; | ||
private final ComponentProvider componentProvider; | ||
private final Set<Session> sessions = new HashSet<>(); | ||
|
||
@Inject | ||
public TaskExecutor( | ||
final ModuleRegistry moduleRegistry, | ||
final ComponentProvider componentProvider | ||
) { | ||
this.moduleRegistry = moduleRegistry; | ||
this.componentProvider = componentProvider; | ||
} | ||
|
||
public void execute(final Class<? extends Task> taskClazz) throws TaskExecutionException { | ||
execute(componentProvider.newInstance(taskClazz)); | ||
} | ||
|
||
public void execute(final Task task) throws TaskExecutionException { | ||
execute(task, getModuleDefinition(task.getClass()).orElse(null)); | ||
} | ||
|
||
public void execute(final Class<? extends Task> taskClazz, @Nullable final ModuleDefinition module) throws TaskExecutionException { | ||
execute(componentProvider.newInstance(taskClazz), module); | ||
} | ||
|
||
public void execute(final Task task, @Nullable final ModuleDefinition module) throws TaskExecutionException { | ||
execute(task, module, true); | ||
} | ||
|
||
public void execute(final Task task, @Nullable final ModuleDefinition module, final boolean saveSession) throws TaskExecutionException { | ||
final InstallContextImpl installContext = new InstallContextImpl(moduleRegistry) { | ||
@Override | ||
public int getTotalTaskCount() { | ||
return 1; | ||
} | ||
@Override | ||
public InstallStatus getStatus() { | ||
return InstallStatus.inProgress; | ||
} | ||
@Override | ||
public Session getJCRSession(String workspaceName) throws RepositoryException { | ||
final Session session = super.getJCRSession(workspaceName); | ||
sessions.add(session); | ||
return session; | ||
} | ||
}; | ||
if(module != null) { | ||
installContext.setCurrentModule(module); | ||
} | ||
task.execute(installContext); | ||
if(saveSession) { | ||
for (Session session : sessions) { | ||
try { | ||
session.save(); | ||
} catch (Exception e) { | ||
throw new TaskExecutionException("Failed to save session", e); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private Optional<ModuleDefinition> getModuleDefinition(final Class<? extends Task> taskClass) { | ||
return moduleRegistry.getModuleNames().stream() | ||
.map(moduleRegistry::getDefinition) | ||
.filter(moduleDefinition -> contains(moduleDefinition, taskClass)) | ||
.findFirst(); | ||
} | ||
|
||
private boolean contains(final ModuleDefinition moduleDefinition, final Class<? extends Task> taskClass) { | ||
final InstallContextImpl installContext = new InstallContextImpl(moduleRegistry); | ||
installContext.setCurrentModule(new ModuleDefinition( | ||
moduleDefinition.getName(), | ||
Version.parseVersion(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE), | ||
moduleDefinition.getClassName(), | ||
moduleDefinition.getVersionHandler() | ||
)); | ||
return moduleRegistry | ||
.getVersionHandler(moduleDefinition.getName()) | ||
.getDeltas(installContext, null) | ||
.stream() | ||
.map(Delta::getTasks) | ||
.flatMap(Collection::stream) | ||
.map(Object::getClass) | ||
.anyMatch(taskClass::equals); | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
...n/java/com/merkle/oss/magnolia/setup/task/nodebuilder/AbstractContentNodeBuilderTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package com.merkle.oss.magnolia.setup.task.nodebuilder; | ||
|
||
|
||
import info.magnolia.jcr.nodebuilder.*; | ||
import info.magnolia.jcr.nodebuilder.task.ErrorHandling; | ||
import info.magnolia.jcr.nodebuilder.task.TaskLogErrorHandler; | ||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.module.delta.AbstractRepositoryTask; | ||
import info.magnolia.module.delta.TaskExecutionException; | ||
|
||
import java.lang.invoke.MethodHandles; | ||
|
||
import javax.jcr.Node; | ||
import javax.jcr.RepositoryException; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
|
||
public abstract class AbstractContentNodeBuilderTask extends AbstractRepositoryTask { | ||
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); | ||
|
||
private final ErrorHandling errorHandling; | ||
|
||
protected AbstractContentNodeBuilderTask(String name, String description, ErrorHandling errorHandling) { | ||
super(name, description); | ||
this.errorHandling = errorHandling; | ||
} | ||
|
||
@Override | ||
protected void doExecute(final InstallContext ctx) throws RepositoryException, TaskExecutionException { | ||
final Node root = getRootNode(ctx); | ||
final NodeOperation[] operations = obtainNodeOperations(ctx); | ||
final ErrorHandler errorHandler = newErrorHandler(ctx); | ||
final NodeBuilder nodeBuilder = new NodeBuilder(errorHandler, root, operations); | ||
try { | ||
nodeBuilder.exec(); | ||
} catch (NodeOperationException e) { | ||
LOG.error("Could not execute node builder task", e); | ||
throw new TaskExecutionException(e.getMessage(), e.getCause()); | ||
} | ||
} | ||
|
||
/** | ||
* This method must be used to set NodeOperations. Use this pattern: | ||
* return new NodeOperation[]{ addNode(...).then( ) }; | ||
* | ||
* @return node operations to be used in this tasks | ||
* @param ctx install context | ||
*/ | ||
protected abstract NodeOperation[] getNodeOperations(final InstallContext ctx); | ||
|
||
protected abstract Node getRootNode(final InstallContext ctx) throws RepositoryException; | ||
|
||
protected ErrorHandler newErrorHandler(final InstallContext ctx) { | ||
if (errorHandling == ErrorHandling.strict) { | ||
return new StrictErrorHandler(); | ||
} | ||
return new TaskLogErrorHandler(ctx); | ||
} | ||
|
||
private NodeOperation[] obtainNodeOperations(final InstallContext ctx) throws TaskExecutionException { | ||
final NodeOperation[] operations = getNodeOperations(ctx); | ||
if (operations == null) { | ||
if (errorHandling == ErrorHandling.logging) { | ||
LOG.warn("No NodeOperations have been specified. Doing nothing"); | ||
return new NodeOperation[0]; | ||
} | ||
throw new TaskExecutionException("Please specify NodeOperations. Can be an empty array if no operations should be done..."); | ||
} | ||
return operations; | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
...main/java/com/merkle/oss/magnolia/setup/task/nodebuilder/AbstractPathNodeBuilderTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package com.merkle.oss.magnolia.setup.task.nodebuilder; | ||
|
||
import info.magnolia.jcr.nodebuilder.task.ErrorHandling; | ||
import info.magnolia.module.InstallContext; | ||
|
||
import javax.jcr.Node; | ||
import javax.jcr.RepositoryException; | ||
import javax.jcr.Session; | ||
|
||
/** | ||
* A task using the NodeBuilder API, applying operations on a given path. | ||
*/ | ||
public abstract class AbstractPathNodeBuilderTask extends AbstractContentNodeBuilderTask { | ||
private final String workspaceName; | ||
private final String rootPath; | ||
|
||
protected AbstractPathNodeBuilderTask( | ||
final String taskName, | ||
final String description, | ||
final ErrorHandling errorHandling, | ||
final String workspaceName | ||
) { | ||
this(taskName, description, errorHandling, workspaceName, "/"); | ||
} | ||
|
||
protected AbstractPathNodeBuilderTask( | ||
final String taskName, | ||
final String description, | ||
final ErrorHandling errorHandling, | ||
final String workspaceName, | ||
final String rootPath | ||
) { | ||
super(taskName, description, errorHandling); | ||
this.workspaceName = workspaceName; | ||
this.rootPath = rootPath; | ||
} | ||
|
||
@Override | ||
protected Node getRootNode(final InstallContext ctx) throws RepositoryException { | ||
final Session hm = ctx.getJCRSession(workspaceName); | ||
return hm.getNode(rootPath); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
core/src/main/java/com/merkle/oss/magnolia/setup/task/type/DepdendsOnComparator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
import info.magnolia.module.delta.Task; | ||
|
||
import java.util.Comparator; | ||
import java.util.Objects; | ||
|
||
|
||
public class DepdendsOnComparator implements Comparator<Task> { | ||
@Override | ||
public int compare(final Task task1, final Task task2) { | ||
if (!(task1 instanceof VersionAwareTask) && !(task2 instanceof VersionAwareTask)) { | ||
return 0; | ||
} | ||
if (!(task1 instanceof VersionAwareTask versionAwareTask1)) { | ||
return -1; | ||
} | ||
if (!(task2 instanceof VersionAwareTask versionAwareTask2)) { | ||
return 1; | ||
} | ||
|
||
if (versionAwareTask1.dependsOn().isEmpty() && versionAwareTask2.dependsOn().isEmpty()) { | ||
return 0; | ||
} | ||
if (versionAwareTask1.dependsOn().isEmpty()) { | ||
return -1; | ||
} | ||
if (versionAwareTask2.dependsOn().isEmpty()) { | ||
return 1; | ||
} | ||
|
||
if (Objects.equals(versionAwareTask1.dependsOn().get().getClass(), versionAwareTask2.getClass())) { | ||
return 1; | ||
} | ||
if (Objects.equals(versionAwareTask2.dependsOn().get().getClass(), versionAwareTask1.getClass())) { | ||
return -1; | ||
} | ||
return compare(versionAwareTask1.dependsOn().get(), versionAwareTask2.dependsOn().get()); | ||
|
||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
core/src/main/java/com/merkle/oss/magnolia/setup/task/type/InstallAndUpdateTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
/** | ||
* Tasks to be executed on Module install and update | ||
*/ | ||
public interface InstallAndUpdateTask extends VersionAwareTask { | ||
} |
7 changes: 7 additions & 0 deletions
7
core/src/main/java/com/merkle/oss/magnolia/setup/task/type/InstallTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
/** | ||
* Tasks to be executed on Module Install | ||
*/ | ||
public interface InstallTask extends VersionAwareTask { | ||
} |
7 changes: 7 additions & 0 deletions
7
core/src/main/java/com/merkle/oss/magnolia/setup/task/type/LocalDevelopmentStartupTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
/** | ||
* Tasks to be executed when the module starts up in local development. | ||
*/ | ||
public interface LocalDevelopmentStartupTask extends VersionAwareTask { | ||
} |
7 changes: 7 additions & 0 deletions
7
core/src/main/java/com/merkle/oss/magnolia/setup/task/type/ModuleStartupTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
/** | ||
* Tasks to be executed when the module starts up | ||
*/ | ||
public interface ModuleStartupTask extends VersionAwareTask { | ||
} |
7 changes: 7 additions & 0 deletions
7
core/src/main/java/com/merkle/oss/magnolia/setup/task/type/SnapshotStartupTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
/** | ||
* Tasks to be executed when the module starts up with a SNAPSHOT version. | ||
*/ | ||
public interface SnapshotStartupTask extends VersionAwareTask { | ||
} |
7 changes: 7 additions & 0 deletions
7
core/src/main/java/com/merkle/oss/magnolia/setup/task/type/UpdateTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
/** | ||
* Tasks to be executed on Module update | ||
*/ | ||
public interface UpdateTask extends VersionAwareTask { | ||
} |
22 changes: 22 additions & 0 deletions
22
core/src/main/java/com/merkle/oss/magnolia/setup/task/type/VersionAwareTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
import info.magnolia.module.delta.Task; | ||
import info.magnolia.module.model.Version; | ||
|
||
import java.util.Optional; | ||
import java.util.function.BiPredicate; | ||
import java.util.function.Predicate; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
public interface VersionAwareTask extends Task, BiPredicate<Version, Version> { | ||
|
||
@Override | ||
default boolean test(final Version forVersion, @Nullable final Version fromVersion) { | ||
return true; | ||
} | ||
|
||
default Optional<VersionAwareTask> dependsOn() { | ||
return Optional.empty(); | ||
} | ||
} |
80 changes: 80 additions & 0 deletions
80
core/src/test/java/com/merkle/oss/magnolia/setup/task/type/DepdendsOnComparatorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package com.merkle.oss.magnolia.setup.task.type; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
import info.magnolia.module.InstallContext; | ||
import info.magnolia.module.delta.Task; | ||
import info.magnolia.module.delta.TaskExecutionException; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.stream.Stream; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
class DepdendsOnComparatorTest { | ||
|
||
@Test | ||
void sort() { | ||
final VersionAwareTask task2 = new Task2(); | ||
final VersionAwareTask task1 = new Task1(); | ||
final VersionAwareTask task3 = new Task3(); | ||
final VersionAwareTask task4 = new Task4(); | ||
final VersionAwareTask task5 = new Task5(); | ||
final Task task6 = new MockTask(); | ||
assertEquals( | ||
List.of(task6, task1, task2, task5, task4, task3), | ||
Stream.of(task2, task4, task5, task6, task1, task3).sorted(new DepdendsOnComparator()).toList() | ||
); | ||
|
||
assertEquals( | ||
List.of(task6, task1, task5, task2, task3, task4), | ||
Stream.of(task3, task6, task1, task5, task2, task4).sorted(new DepdendsOnComparator()).toList() | ||
); | ||
} | ||
|
||
private static class Task1 extends MockVersionAwareTask {} | ||
private static class Task2 extends MockVersionAwareTask { | ||
@Override | ||
public Optional<VersionAwareTask> dependsOn() { | ||
return Optional.of(new Task1()); | ||
} | ||
} | ||
private static class Task3 extends MockVersionAwareTask { | ||
@Override | ||
public Optional<VersionAwareTask> dependsOn() { | ||
return Optional.of(new Task2()); | ||
} | ||
} | ||
private static class Task4 extends MockVersionAwareTask { | ||
@Override | ||
public Optional<VersionAwareTask> dependsOn() { | ||
return Optional.of(new Task2()); | ||
} | ||
} | ||
private static class Task5 extends MockVersionAwareTask { | ||
@Override | ||
public Optional<VersionAwareTask> dependsOn() { | ||
return Optional.of(new Task1()); | ||
} | ||
} | ||
|
||
private static abstract class MockVersionAwareTask extends MockTask implements VersionAwareTask {} | ||
|
||
private static class MockTask implements Task { | ||
@Override | ||
public String getName() { | ||
return getClass().getSimpleName(); | ||
} | ||
@Override | ||
public String getDescription() { | ||
return getClass().getSimpleName()+"_description"; | ||
} | ||
@Override | ||
public void execute(final InstallContext installContext) {} | ||
@Override | ||
public String toString() { | ||
return getName(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>com.merkle.oss.magnolia</groupId> | ||
<artifactId>magnolia-setup-task</artifactId> | ||
<packaging>pom</packaging> | ||
<version>0.0.1-SNAPSHOT</version> | ||
|
||
<name>${project.artifactId}</name> | ||
<url>https://github.com/merkle-open/magnolia-setup-task</url> | ||
<description>Setup task to help bootstrap magnolia</description> | ||
|
||
<licenses> | ||
<license> | ||
<name>MIT License</name> | ||
<url>https://opensource.org/licenses/MIT</url> | ||
<distribution>repo</distribution> | ||
</license> | ||
</licenses> | ||
|
||
<developers> | ||
<developer> | ||
<name>Merkle Magnolia</name> | ||
<email>magnolia@merkle.com</email> | ||
<organization>Merkle DACH</organization> | ||
<organizationUrl>https://merkleinc.ch</organizationUrl> | ||
</developer> | ||
</developers> | ||
|
||
<scm> | ||
<url>https://github.com/merkle-open/magnolia-setup-task</url> | ||
<connection>scm:git:git@github.com:merkle-open/magnolia-setup-task.git</connection> | ||
<developerConnection>scm:git:git@github.com:merkle-open/magnolia-setup-task.git</developerConnection> | ||
</scm> | ||
|
||
<modules> | ||
<module>common-task</module> | ||
<module>core</module> | ||
</modules> | ||
|
||
<properties> | ||
<!-- check for new versions: mvn versions:display-property-updates --> | ||
<magnolia.version>6.3.0</magnolia.version> | ||
<jsr305.nullable.version>3.0.2</jsr305.nullable.version> | ||
<namics.oss.powernode.version>2.1.1</namics.oss.powernode.version> | ||
|
||
<!-- Maven Plugins --> | ||
<mvn.compiler.plugin.version>3.11.0</mvn.compiler.plugin.version> | ||
<mvn.source.plugin.version>3.3.0</mvn.source.plugin.version> | ||
<mvn.javadoc.version>3.8.0</mvn.javadoc.version> | ||
<mvn.gpg.plugin.version>3.2.5</mvn.gpg.plugin.version> | ||
<mvn.sonatype.publishing.plugin.version>0.5.0</mvn.sonatype.publishing.plugin.version> | ||
<mvn.surefire.plugin.version>3.5.0</mvn.surefire.plugin.version> | ||
|
||
<!--Test dependency versions--> | ||
<junit.version>5.11.0</junit.version> | ||
<mockito.version>5.13.0</mockito.version> | ||
|
||
<javaVersion>17</javaVersion> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>info.magnolia.bundle</groupId> | ||
<artifactId>magnolia-bundle-parent</artifactId> | ||
<version>${magnolia.version}</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.merkle.oss.magnolia</groupId> | ||
<artifactId>magnolia-setup-task-core</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.namics.oss.magnolia</groupId> | ||
<artifactId>magnolia-powernode</artifactId> | ||
<version>${namics.oss.powernode.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.code.findbugs</groupId> | ||
<artifactId>jsr305</artifactId> | ||
<version>${jsr305.nullable.version}</version> | ||
</dependency> | ||
|
||
<!-- TESTING DEPENDENCIES --> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter</artifactId> | ||
<version>${junit.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
<version>${mockito.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</dependencyManagement> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>${mvn.compiler.plugin.version}</version> | ||
<configuration> | ||
<release>${javaVersion}</release> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-source-plugin</artifactId> | ||
<version>${mvn.source.plugin.version}</version> | ||
<executions> | ||
<execution> | ||
<id>attach-sources</id> | ||
<goals> | ||
<goal>jar-no-fork</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-javadoc-plugin</artifactId> | ||
<version>${mvn.javadoc.version}</version> | ||
<configuration> | ||
<failOnError>false</failOnError> | ||
</configuration> | ||
<executions> | ||
<execution> | ||
<id>attach-javadocs</id> | ||
<goals> | ||
<goal>jar</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-surefire-plugin</artifactId> | ||
<version>${mvn.surefire.plugin.version}</version> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<repositories> | ||
<!-- Magnolia --> | ||
<repository> | ||
<id>magnolia.public.group</id> | ||
<url>https://nexus.magnolia-cms.com/content/groups/public</url> | ||
<snapshots> | ||
<enabled>true</enabled> | ||
</snapshots> | ||
</repository> | ||
<repository> | ||
<id>magnolia.enterprise.group</id> | ||
<url>https://nexus.magnolia-cms.com/content/groups/enterprise</url> | ||
<snapshots> | ||
<enabled>false</enabled> | ||
</snapshots> | ||
</repository> | ||
</repositories> | ||
|
||
<distributionManagement> | ||
<!-- central portal doesn't support SNAPSHOT versions: https://central.sonatype.org/faq/snapshot-releases --> | ||
<repository> | ||
<id>central</id> | ||
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url> | ||
</repository> | ||
</distributionManagement> | ||
|
||
<profiles> | ||
<profile> | ||
<id>deploy</id> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-gpg-plugin</artifactId> | ||
<version>${mvn.gpg.plugin.version}</version> | ||
<executions> | ||
<execution> | ||
<id>sign-artifacts</id> | ||
<phase>verify</phase> | ||
<goals> | ||
<goal>sign</goal> | ||
</goals> | ||
<configuration> | ||
<!-- Prevent `gpg` from using pinentry programs --> | ||
<gpgArguments> | ||
<arg>--pinentry-mode</arg> | ||
<arg>loopback</arg> | ||
</gpgArguments> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.sonatype.central</groupId> | ||
<artifactId>central-publishing-maven-plugin</artifactId> | ||
<version>${mvn.sonatype.publishing.plugin.version}</version> | ||
<extensions>true</extensions> | ||
<configuration> | ||
<publishingServerId>central</publishingServerId> | ||
<autoPublish>true</autoPublish> | ||
<waitUntil>published</waitUntil> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
</profiles> | ||
</project> |