Skip to content

Commit

Permalink
Merge pull request #12 from justinedelson/issue/custom-install-hook-f…
Browse files Browse the repository at this point in the history
…actory

allow suppression of install hooks via new builder option. fixes #11
  • Loading branch information
adamcin committed Jul 3, 2019
2 parents f876632 + 99dfba4 commit 1325f0b
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
language: java
jdk: oraclejdk8
dist: trusty
script:
- mvn -B verify
after_success:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2019 Mark Adamcin
*
* Licensed 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 net.adamcin.oakpal.core;

import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.packaging.InstallHookProcessor;
import org.apache.jackrabbit.vault.packaging.InstallHookProcessorFactory;

class ImportOptionsWithInstallHookProcessorFactory extends ImportOptions implements InstallHookProcessorFactory {

private final ImportOptions optionsDelegate;
private final InstallHookProcessorFactory factoryDelegate;

ImportOptionsWithInstallHookProcessorFactory(ImportOptions optionsDelegate, InstallHookProcessorFactory factoryDelegate) {
this.optionsDelegate = optionsDelegate;
this.factoryDelegate = factoryDelegate;
}

@Override
public InstallHookProcessor createInstallHookProcessor() {
return factoryDelegate.createInstallHookProcessor();
}

@Override
public ImportOptions copy() {
return new ImportOptionsWithInstallHookProcessorFactory(optionsDelegate.copy(), factoryDelegate);
}
}
58 changes: 56 additions & 2 deletions core/src/main/java/net/adamcin/oakpal/core/OakMachine.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,13 @@
import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
import org.apache.jackrabbit.vault.fs.api.VaultInputSource;
import org.apache.jackrabbit.vault.fs.io.Archive;
import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.packaging.DependencyHandling;
import org.apache.jackrabbit.vault.packaging.InstallContext;
import org.apache.jackrabbit.vault.packaging.InstallHookProcessor;
import org.apache.jackrabbit.vault.packaging.InstallHookProcessorFactory;
import org.apache.jackrabbit.vault.packaging.JcrPackage;
import org.apache.jackrabbit.vault.packaging.JcrPackageManager;
import org.apache.jackrabbit.vault.packaging.PackageException;
Expand Down Expand Up @@ -94,18 +99,22 @@ public final class OakMachine {

private final JcrCustomizer jcrCustomizer;

private final InstallHookProcessorFactory installHookProcessorFactory;

private OakMachine(final Packaging packagingService,
final List<ProgressCheck> progressChecks,
final ErrorListener errorListener,
final List<File> preInstallPackages,
final List<InitStage> initStages,
final JcrCustomizer jcrCustomizer) {
final JcrCustomizer jcrCustomizer,
final InstallHookProcessorFactory installHookProcessorFactory) {
this.packagingService = packagingService != null ? packagingService : new DefaultPackagingService();
this.progressChecks = progressChecks;
this.errorListener = errorListener;
this.preInstallPackages = preInstallPackages;
this.initStages = initStages;
this.jcrCustomizer = jcrCustomizer;
this.installHookProcessorFactory = installHookProcessorFactory;
}

/**
Expand All @@ -124,6 +133,8 @@ public static class Builder {

private JcrCustomizer jcrCustomizer;

private InstallHookProcessorFactory installHookProcessorFactory;

/**
* Provide a {@link Packaging} service for use in retrieving a {@link JcrPackageManager} for an admin session.
* <p>
Expand Down Expand Up @@ -248,6 +259,17 @@ public Builder withJcrCustomizer(final JcrCustomizer jcrCustomizer) {
return this;
}

/**
* Provide an {@link InstallHookProcessorFactory}.
*
* @param installHookProcessorFactory the factory
* @return my builder self
*/
public Builder withInstallHookProcessorFactory(final InstallHookProcessorFactory installHookProcessorFactory) {
this.installHookProcessorFactory = installHookProcessorFactory;
return this;
}

/**
* Construct a {@link OakMachine} from the {@link Builder} state.
*
Expand All @@ -259,10 +281,38 @@ public OakMachine build() {
errorListener,
preInstallPackages,
initStages,
jcrCustomizer);
jcrCustomizer,
installHookProcessorFactory);
}
}

public static final InstallHookProcessorFactory NOOP_INSTALL_HOOK_PROCESSOR_FACTORY = new InstallHookProcessorFactory() {
@Override
public InstallHookProcessor createInstallHookProcessor() {
return NOOP_INSTALL_HOOK_PROCESSOR;
}
};

private static final InstallHookProcessor NOOP_INSTALL_HOOK_PROCESSOR = new InstallHookProcessor() {
@Override
public void registerHooks(Archive archive, ClassLoader classLoader) {
}

@Override
public void registerHook(VaultInputSource vaultInputSource, ClassLoader classLoader) {
}

@Override
public boolean hasHooks() {
return false;
}

@Override
public boolean execute(InstallContext installContext) {
return true;
}
};

public List<ProgressCheck> getProgressChecks() {
return progressChecks;
}
Expand Down Expand Up @@ -471,6 +521,10 @@ private void processPackage(Session admin, JcrPackageManager manager, JcrPackage
options.setDependencyHandling(DependencyHandling.IGNORE);
options.setListener(tracker);

if (installHookProcessorFactory != null) {
options = new ImportOptionsWithInstallHookProcessorFactory(options, installHookProcessorFactory);
}

List<PackageId> subpacks = Arrays.asList(jcrPackage.extractSubpackages(options));

final VaultPackage vaultPackage = jcrPackage.getPackage();
Expand Down
42 changes: 42 additions & 0 deletions core/src/test/java/net/adamcin/oakpal/core/BadInstallHookTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2018 Mark Adamcin
*
* Licensed 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 net.adamcin.oakpal.core;

import net.adamcin.oakpal.testing.TestPackageUtil;
import org.junit.Test;

import java.io.File;

public class BadInstallHookTest {

@Test(expected = NoClassDefFoundError.class)
public void testBadInstallHook() throws Exception {
File badInstallHookPackage = TestPackageUtil.prepareTestPackageFromFolder("bad-install-hook.zip",
new File("src/test/resources/package_with_bad_installhook"));

new OakMachine.Builder().build().scanPackage(badInstallHookPackage);
}

@Test()
public void testBadInstallHookNoOpProcessor() throws Exception {
File badInstallHookPackage = TestPackageUtil.prepareTestPackageFromFolder("bad-install-hook.zip",
new File("src/test/resources/package_with_bad_installhook"));

new OakMachine.Builder().withInstallHookProcessorFactory(OakMachine.NOOP_INSTALL_HOOK_PROCESSOR_FACTORY)
.build().scanPackage(badInstallHookPackage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<!--
Copyright 2012 Adobe Systems Incorporated
Licensed 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.
-->
<vaultfs version="1.1">
<!--
Defines the content aggregation. The order of the defined aggregates
is important for finding the correct aggregator.
-->
<aggregates>
<!--
Defines an aggregate that handles nt:file and nt:resource nodes.
-->
<aggregate type="file" title="File Aggregate"/>

<!--
Defines an aggregate that handles file/folder like nodes. It matches
all nt:hierarchyNode nodes that have or define a jcr:content
child node and excludes child nodes that are nt:hierarchyNodes.
-->
<aggregate type="filefolder" title="File/Folder Aggregate"/>

<!--
Defines an aggregate that handles nt:nodeType nodes and serializes
them into .cnd notation.
-->
<aggregate type="nodetype" title="Node Type Aggregate" />

<!--
Defines an aggregate that defines full coverage for certain node
types that cannot be covered by the default aggregator.
-->
<aggregate type="full" title="Full Coverage Aggregate">
<matches>
<include nodeType="rep:AccessControl" respectSupertype="true" />
<include nodeType="cq:Widget" respectSupertype="true" />
<include nodeType="cq:WidgetCollection" respectSupertype="true" />
<include nodeType="cq:EditConfig" respectSupertype="true" />
<include nodeType="cq:WorkflowModel" respectSupertype="true" />
<include nodeType="vlt:FullCoverage" respectSupertype="true" />
<include nodeType="mix:language" respectSupertype="true" />
<include nodeType="sling:OsgiConfig" respectSupertype="true" />
</matches>
</aggregate>

<!--
Defines an aggregate that handles nt:folder like nodes.
-->
<aggregate type="generic" title="Folder Aggregate">
<matches>
<include nodeType="nt:folder" respectSupertype="true" />
</matches>
<contains>
<exclude isNode="true" />
</contains>
</aggregate>

<!--
Defines the default aggregate
-->
<aggregate type="generic" title="Default Aggregator" isDefault="true">
<contains>
<exclude nodeType="nt:hierarchyNode" respectSupertype="true" />
</contains>
<matches>
<!-- all -->
</matches>
</aggregate>

</aggregates>

<!--
defines the input handlers
-->
<handlers>
<handler type="folder"/>
<handler type="file"/>
<handler type="nodetype"/>
<handler type="generic"/>
</handlers>
</vaultfs>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<workspaceFilter version="1.0">
</workspaceFilter>
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>OakPAL Testing - Hook Test Content Package</comment>
<entry key="createdBy">jedelson</entry>
<entry key="name">oakpal-testing-hooktest.ui.apps</entry>
<entry key="acHandling">merge_preserve</entry>
<entry key="created">2019-06-24T20:25:50.546-0400</entry>
<entry key="groupId">com.myco.testing</entry>
<entry key="version">0.0.1-SNAPSHOT</entry>
<entry key="requiresRoot">false</entry>
<entry key="group">my-co</entry>
<entry key="description">Maven Multimodule project for OakPAL Testing - HookTest.</entry>
<entry key="artifactId">oakpal-testing-hooktest.ui.apps</entry>
<entry key="path">/etc/packages/my-co/oakpal-testing-hooktest.ui.apps.zip</entry>
</properties>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2012 Adobe Systems Incorporated
Licensed 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.
-->
<vault version="1.0">
<ignore name=".svn"/>
<ignore name=".DS_Store"/>
</vault>
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,14 @@ abstract class AbstractScanMojo extends AbstractMojo {
@Parameter
protected boolean deferBuildFailure;

/**
* If this is set to true, InstallHooks in scanned packages will be ignored.
*
* @since 1.4.0
*/
@Parameter
protected boolean skipInstallHooks;

/**
* Construct an init stage purely from the relevant mojo parameters.
*
Expand Down Expand Up @@ -382,6 +390,10 @@ protected OakMachine.Builder getBuilder() throws MojoExecutionException {
.withInitStages(checklistPlanner.getInitStages())
.withPreInstallPackages(preInstall);

if (skipInstallHooks) {
machineBuilder.withInstallHookProcessorFactory(OakMachine.NOOP_INSTALL_HOOK_PROCESSOR_FACTORY);
}

return machineBuilder;
}
}

0 comments on commit 1325f0b

Please sign in to comment.