You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by da...@apache.org on 2020/09/01 16:32:54 UTC
[sling-org-apache-sling-installer-factory-feature] 03/32: Support
multiple features per archive and allow for selection through pattern
This is an automated email from the ASF dual-hosted git repository.
davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-factory-feature.git
commit fed02f0bd831f2bb44b2b3641da21d47b4f985d6
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Sun Feb 23 17:34:30 2020 +0100
Support multiple features per archive and allow for selection through pattern
---
pom.xml | 11 ++
.../model/impl/FeatureModelInstallerPlugin.java | 121 +++++++++++++-----
.../factory/model/impl/InstallContext.java | 50 ++++++++
.../model/impl/InstallFeatureModelTask.java | 141 +++++++++------------
.../model/impl/UninstallFeatureModelTask.java | 7 -
.../impl/FeatureModelInstallerPluginTest.java | 70 ++++++++++
6 files changed, 278 insertions(+), 122 deletions(-)
diff --git a/pom.xml b/pom.xml
index 815d242..5991eae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -115,6 +115,17 @@
<version>1.3.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
+ <!-- Testing -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>2.15.0</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelInstallerPlugin.java b/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelInstallerPlugin.java
index 69df21f..3023feb 100644
--- a/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelInstallerPlugin.java
+++ b/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelInstallerPlugin.java
@@ -19,11 +19,13 @@
package org.apache.sling.installer.factory.model.impl;
import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
+import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -32,6 +34,8 @@ import java.util.Map;
import java.util.regex.Pattern;
import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.BuilderContext;
+import org.apache.sling.feature.builder.FeatureBuilder;
import org.apache.sling.feature.io.archive.ArchiveReader;
import org.apache.sling.feature.io.artifacts.ArtifactManager;
import org.apache.sling.feature.io.artifacts.ArtifactManagerConfig;
@@ -78,7 +82,8 @@ public class FeatureModelInstallerPlugin implements InstallTaskFactory, Resource
@AttributeDefinition(name = "Repository URLs", description = "Additional repository URLs to fetch artifacts")
String[] repositories();
- @AttributeDefinition(name = "Classifier Patterns", description = "Patterns for selecting the features to handle based on the classifier. Without a configuration all features are handled.")
+ @AttributeDefinition(name = "Classifier Patterns", description = "Patterns for selecting the features to handle based on the classifier. Without a configuration all features are handled."
+ + " The patterns can use an asteriks to match any characters in the classifier. The special token ':' can be used to match the empty classifier.")
String[] classifierPatterns();
}
@@ -88,8 +93,6 @@ public class FeatureModelInstallerPlugin implements InstallTaskFactory, Resource
public static final String ATTR_MODEL = "feature";
- public static final String ATTR_BASE_PATH = "path";
-
public static final String ATTR_ID = "featureId";
/** Logger. */
@@ -108,27 +111,38 @@ public class FeatureModelInstallerPlugin implements InstallTaskFactory, Resource
private final ArtifactManager artifactManager;
- private final List<String> classifierPatterns = new ArrayList<>();
+ private final List<Pattern> classifierPatterns = new ArrayList<>();
+
+ private final File storageDirectory;
@Activate
public FeatureModelInstallerPlugin(final BundleContext ctx, final Config config) throws IOException {
this.bundleContext = ctx;
+ this.storageDirectory = this.bundleContext.getDataFile("repository");
final ArtifactManagerConfig amCfg = new ArtifactManagerConfig();
amCfg.setUseMvn(config.useMvn());
+ final List<String> repos = new ArrayList<>(Arrays.asList(amCfg.getRepositoryUrls()));
+ if (this.storageDirectory != null) {
+ repos.add(this.storageDirectory.toURI().toURL().toExternalForm());
+ }
if (config.repositories() != null && config.repositories().length > 0) {
- final List<String> repos = new ArrayList<>(Arrays.asList(amCfg.getRepositoryUrls()));
for (final String r : config.repositories()) {
if (!r.trim().isEmpty()) {
repos.add(r);
}
}
- amCfg.setRepositoryUrls(repos.toArray(new String[repos.size()]));
}
+ amCfg.setRepositoryUrls(repos.toArray(new String[repos.size()]));
+
this.artifactManager = ArtifactManager.getArtifactManager(amCfg);
if (config.classifierPatterns() != null) {
for (final String text : config.classifierPatterns()) {
if (text != null && !text.trim().isEmpty()) {
- classifierPatterns.add(text.trim());
+ if (":".equals(text.trim())) {
+ classifierPatterns.add(Pattern.compile("^$"));
+ } else {
+ classifierPatterns.add(Pattern.compile(toRegexPattern(text.trim())));
+ }
}
}
}
@@ -137,7 +151,6 @@ public class FeatureModelInstallerPlugin implements InstallTaskFactory, Resource
@Override
public TransformationResult[] transform(final RegisteredResource resource) {
final List<Feature> features = new ArrayList<>();
- File baseDir = null;
if (resource.getType().equals(InstallableResource.TYPE_FILE) && resource.getURL().endsWith(FILE_EXTENSION)) {
try (final Reader reader = new InputStreamReader(resource.getInputStream(), "UTF-8")) {
features.add(FeatureJSONReader.read(reader, resource.getURL()));
@@ -146,7 +159,6 @@ public class FeatureModelInstallerPlugin implements InstallTaskFactory, Resource
}
}
if (resource.getType().equals(InstallableResource.TYPE_FILE) && resource.getURL().endsWith(".zip")) {
- baseDir = this.bundleContext.getDataFile("");
try (final InputStream is = resource.getInputStream()) {
features.addAll(ArchiveReader.read(is, null));
} catch (final IOException ioe) {
@@ -154,28 +166,36 @@ public class FeatureModelInstallerPlugin implements InstallTaskFactory, Resource
}
}
if (!features.isEmpty()) {
- boolean error = false;
- final List<TransformationResult> result = new ArrayList<>();
- for (final Feature feature : features) {
- boolean select = this.classifierPatterns.isEmpty();
- if (!select) {
- for (final String pattern : this.classifierPatterns) {
- if (":".equals(pattern)) {
- select = feature.getId().getClassifier() == null;
- } else if (feature.getId().getClassifier() != null) {
- select = Pattern.compile(pattern).matcher(feature.getId().getClassifier()).matches();
- }
-
- if (select) {
- break;
+ // persist all features to the file system
+ if (this.storageDirectory != null) {
+ for (Feature feature : features) {
+ final File featureFile = new File(this.storageDirectory,
+ feature.getId().toMvnPath().replace('/', File.separatorChar));
+ if (!featureFile.exists()) {
+ featureFile.getParentFile().mkdirs();
+ try (final Writer writer = new FileWriter(featureFile)) {
+ FeatureJSONWriter.write(writer, feature);
+ } catch (final IOException ioe) {
+ logger.error("Unable to write feature to " + featureFile + ":" + ioe.getMessage(), ioe);
}
}
}
+ }
- if (!select) {
+ boolean error = false;
+ final List<TransformationResult> result = new ArrayList<>();
+ for (Feature feature : features) {
+ if (!classifierMatches(feature.getId().getClassifier())) {
continue;
}
+ // assemble feature now
+ if (!feature.isAssembled()) {
+ final BuilderContext ctx = new BuilderContext(this.artifactManager.toFeatureProvider());
+ ctx.setArtifactProvider(this.artifactManager);
+ feature = FeatureBuilder.assemble(feature, ctx);
+ }
+
String featureJson = null;
try (final StringWriter sw = new StringWriter()) {
FeatureJSONWriter.write(sw, feature);
@@ -193,10 +213,7 @@ public class FeatureModelInstallerPlugin implements InstallTaskFactory, Resource
final Map<String, Object> attributes = new HashMap<>();
attributes.put(ATTR_MODEL, featureJson);
attributes.put(ATTR_ID, feature.getId().toMvnId());
- if (baseDir != null) {
- final File dir = new File(baseDir, feature.getId().toMvnName());
- attributes.put(ATTR_BASE_PATH, dir.getAbsolutePath());
- }
+
tr.setAttributes(attributes);
result.add(tr);
@@ -221,10 +238,50 @@ public class FeatureModelInstallerPlugin implements InstallTaskFactory, Resource
if (rsrc.getState() == ResourceState.UNINSTALL ) {
return new UninstallFeatureModelTask(group, bundleContext);
}
+ final InstallContext ctx = new InstallContext(this.repository, this.repoInitProcessor, this.repoInitParser,
+ this.artifactManager, this.storageDirectory);
return new InstallFeatureModelTask(group,
- this.repository,
- this.repoInitProcessor,
- this.repoInitParser,
- this.bundleContext, this.artifactManager);
+ ctx, this.bundleContext);
+ }
+
+ boolean classifierMatches(String classifier) {
+ boolean select = this.classifierPatterns.isEmpty();
+ if (!select) {
+ if (classifier == null) {
+ classifier = "";
+ }
+ for (final Pattern pattern : this.classifierPatterns) {
+ select = pattern.matcher(classifier).matches();
+
+ if (select) {
+ break;
+ }
+ }
+ }
+ return select;
+ }
+
+ private static String toRegexPattern(String pattern) {
+ StringBuilder stringBuilder = new StringBuilder("^");
+ int index = 0;
+ while (index < pattern.length()) {
+ char currentChar = pattern.charAt(index++);
+ switch (currentChar) {
+ case '*':
+ stringBuilder.append("[^/]*");
+ break;
+ default:
+ if (isRegexMeta(currentChar)) {
+ stringBuilder.append(Pattern.quote(Character.toString(currentChar)));
+ } else {
+ stringBuilder.append(currentChar);
+ }
+ }
+ }
+ return stringBuilder.append('$').toString();
+ }
+
+ private static boolean isRegexMeta(char character) {
+ return "<([{\\^-=$!|]})?*+.>".indexOf(character) != -1;
}
}
diff --git a/src/main/java/org/apache/sling/installer/factory/model/impl/InstallContext.java b/src/main/java/org/apache/sling/installer/factory/model/impl/InstallContext.java
new file mode 100644
index 0000000..0af42fa
--- /dev/null
+++ b/src/main/java/org/apache/sling/installer/factory/model/impl/InstallContext.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.installer.factory.model.impl;
+
+import java.io.File;
+
+import org.apache.sling.feature.io.artifacts.ArtifactManager;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.repoinit.JcrRepoInitOpsProcessor;
+import org.apache.sling.repoinit.parser.RepoInitParser;
+
+public class InstallContext {
+
+ public final SlingRepository repository;
+
+ public final JcrRepoInitOpsProcessor repoInitProcessor;
+
+ public final RepoInitParser repoInitParser;
+
+ public final ArtifactManager artifactManager;
+
+ public final File storageDirectory;
+
+ public InstallContext(final SlingRepository repository,
+ final JcrRepoInitOpsProcessor repoInitProcessor,
+ final RepoInitParser repoInitParser,
+ final ArtifactManager artifactManager, final File storageDirectory) {
+ this.repository = repository;
+ this.repoInitProcessor = repoInitProcessor;
+ this.repoInitParser = repoInitParser;
+ this.artifactManager = artifactManager;
+ this.storageDirectory = storageDirectory;
+ }
+}
diff --git a/src/main/java/org/apache/sling/installer/factory/model/impl/InstallFeatureModelTask.java b/src/main/java/org/apache/sling/installer/factory/model/impl/InstallFeatureModelTask.java
index 3dde406..34572c4 100644
--- a/src/main/java/org/apache/sling/installer/factory/model/impl/InstallFeatureModelTask.java
+++ b/src/main/java/org/apache/sling/installer/factory/model/impl/InstallFeatureModelTask.java
@@ -43,7 +43,6 @@ import org.apache.sling.feature.ExtensionType;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.io.archive.ArchiveReader;
import org.apache.sling.feature.io.artifacts.ArtifactHandler;
-import org.apache.sling.feature.io.artifacts.ArtifactManager;
import org.apache.sling.feature.io.json.FeatureJSONReader;
import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.OsgiInstaller;
@@ -51,9 +50,6 @@ import org.apache.sling.installer.api.tasks.InstallationContext;
import org.apache.sling.installer.api.tasks.ResourceState;
import org.apache.sling.installer.api.tasks.TaskResource;
import org.apache.sling.installer.api.tasks.TaskResourceGroup;
-import org.apache.sling.jcr.api.SlingRepository;
-import org.apache.sling.jcr.repoinit.JcrRepoInitOpsProcessor;
-import org.apache.sling.repoinit.parser.RepoInitParser;
import org.apache.sling.repoinit.parser.RepoInitParsingException;
import org.apache.sling.repoinit.parser.operations.Operation;
import org.osgi.framework.BundleContext;
@@ -63,24 +59,12 @@ import org.osgi.framework.BundleContext;
*/
public class InstallFeatureModelTask extends AbstractFeatureModelTask {
- private final SlingRepository repository;
-
- private final JcrRepoInitOpsProcessor repoInitProcessor;
-
- private final RepoInitParser repoInitParser;
-
- private final ArtifactManager artifactManager;
+ private final InstallContext installContext;
public InstallFeatureModelTask(final TaskResourceGroup group,
- final SlingRepository repository,
- final JcrRepoInitOpsProcessor repoInitProcessor,
- final RepoInitParser repoInitParser,
- final BundleContext bundleContext, final ArtifactManager artifactManager) {
+ final InstallContext installContext, final BundleContext bundleContext) {
super(group, bundleContext);
- this.repository = repository;
- this.repoInitProcessor = repoInitProcessor;
- this.repoInitParser = repoInitParser;
- this.artifactManager = artifactManager;
+ this.installContext = installContext;
}
@SuppressWarnings("deprecation")
@@ -94,68 +78,59 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
ctx.log("Unable to install feature model resource {} : no model found", resource);
this.getResourceGroup().setFinishState(ResourceState.IGNORED);
} else {
- final String path = (String) resource.getAttribute(FeatureModelInstallerPlugin.ATTR_BASE_PATH);
- final File baseDir = (path == null ? null : new File(path));
-
boolean success = false;
- try {
- final Result result = this.transform(featureJson, resource, baseDir);
- if ( result == null ) {
- ctx.log("Unable to install feature model resource {} : unable to create resources", resource);
- this.getResourceGroup().setFinishState(ResourceState.IGNORED);
- } else {
- // repo init first
- if ( result.repoinit != null ) {
- List<Operation> ops = null;
- try ( final Reader r = new StringReader(result.repoinit) ) {
- ops = this.repoInitParser.parse(r);
- } catch (final IOException | RepoInitParsingException e) {
- logger.error("Unable to parse repoinit text.", e);
- ctx.log("Unable to install feature model resource {} : unable parse repoinit text.",
- resource);
- this.getResourceGroup().setFinishState(ResourceState.IGNORED);
- return;
- }
+ final Result result = this.transform(featureJson, resource);
+ if (result == null) {
+ ctx.log("Unable to install feature model resource {} : unable to create resources", resource);
+ this.getResourceGroup().setFinishState(ResourceState.IGNORED);
+ } else {
+ // repo init first
+ if (result.repoinit != null) {
+ List<Operation> ops = null;
+ try (final Reader r = new StringReader(result.repoinit)) {
+ ops = this.installContext.repoInitParser.parse(r);
+ } catch (final IOException | RepoInitParsingException e) {
+ logger.error("Unable to parse repoinit text.", e);
+ ctx.log("Unable to install feature model resource {} : unable parse repoinit text.",
+ resource);
+ this.getResourceGroup().setFinishState(ResourceState.IGNORED);
+ return;
+ }
- // login admin is required for repo init
- Session session = null;
- try {
- session = this.repository.loginAdministrative(null);
- this.repoInitProcessor.apply(session, ops);
- session.save();
- } catch ( final RepositoryException re) {
- logger.error("Unable to process repoinit text.", re);
- ctx.log("Unable to install feature model resource {} : unable to process repoinit text.",
- resource);
- this.getResourceGroup().setFinishState(ResourceState.IGNORED);
- return;
+ // login admin is required for repo init
+ Session session = null;
+ try {
+ session = this.installContext.repository.loginAdministrative(null);
+ this.installContext.repoInitProcessor.apply(session, ops);
+ session.save();
+ } catch (final RepositoryException re) {
+ logger.error("Unable to process repoinit text.", re);
+ ctx.log("Unable to install feature model resource {} : unable to process repoinit text.",
+ resource);
+ this.getResourceGroup().setFinishState(ResourceState.IGNORED);
+ return;
- } finally {
- if ( session != null ) {
- session.logout();
- }
+ } finally {
+ if (session != null) {
+ session.logout();
}
}
- if ( !result.resources.isEmpty() ) {
- final OsgiInstaller installer = this.getService(OsgiInstaller.class);
- if ( installer != null ) {
- installer.registerResources(
- "model-" + resource.getAttribute(FeatureModelInstallerPlugin.ATTR_ID),
- result.resources.toArray(new InstallableResource[result.resources.size()]));
- } else {
- ctx.log("Unable to install feature model resource {} : unable to get OSGi installer",
- resource);
- this.getResourceGroup().setFinishState(ResourceState.IGNORED);
- return;
- }
- }
- this.getResourceGroup().setFinishState(ResourceState.INSTALLED);
- success = true;
}
- } finally {
- if ( !success && baseDir != null ) {
- this.deleteDirectory(baseDir);
+ if (!result.resources.isEmpty()) {
+ final OsgiInstaller installer = this.getService(OsgiInstaller.class);
+ if (installer != null) {
+ installer.registerResources(
+ "model-" + resource.getAttribute(FeatureModelInstallerPlugin.ATTR_ID),
+ result.resources.toArray(new InstallableResource[result.resources.size()]));
+ } else {
+ ctx.log("Unable to install feature model resource {} : unable to get OSGi installer",
+ resource);
+ this.getResourceGroup().setFinishState(ResourceState.IGNORED);
+ return;
+ }
}
+ this.getResourceGroup().setFinishState(ResourceState.INSTALLED);
+ success = true;
}
if ( success ) {
ctx.log("Installed {}", resource.getEntityId());
@@ -176,8 +151,7 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
}
private Result transform(final String featureJson,
- final TaskResource rsrc,
- final File baseDir) {
+ final TaskResource rsrc) {
Feature feature = null;
try (final Reader reader = new StringReader(featureJson)) {
feature = FeatureJSONReader.read(reader, null);
@@ -188,7 +162,7 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
return null;
}
- if ( baseDir != null ) {
+ if (this.installContext.storageDirectory != null) {
// extract artifacts
final byte[] buffer = new byte[1024*1024*256];
@@ -197,7 +171,7 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
@Override
public void consume(final ArtifactId id, final InputStream is) throws IOException {
- final File artifactFile = getArtifactFile(baseDir, id);
+ final File artifactFile = getArtifactFile(installContext.storageDirectory, id);
if (!artifactFile.exists()) {
artifactFile.getParentFile().mkdirs();
try (final OutputStream os = new FileOutputStream(artifactFile)) {
@@ -218,14 +192,14 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
final Result result = new Result();
for (final Artifact bundle : feature.getBundles()) {
- if (!addArtifact(baseDir, bundle, result)) {
+ if (!addArtifact(bundle, result)) {
return null;
}
}
final Extension ext = feature.getExtensions().getByName(Extension.EXTENSION_NAME_CONTENT_PACKAGES);
if (ext != null && ext.getType() == ExtensionType.ARTIFACTS) {
for (final Artifact artifact : ext.getArtifacts()) {
- addArtifact(baseDir, artifact, result);
+ addArtifact(artifact, result);
}
}
@@ -241,13 +215,14 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
return result;
}
- private boolean addArtifact(final File baseDir, final Artifact artifact,
+ private boolean addArtifact(final Artifact artifact,
final Result result) {
- File artifactFile = (baseDir == null ? null : getArtifactFile(baseDir, artifact.getId()));
+ File artifactFile = (this.installContext.storageDirectory == null ? null
+ : getArtifactFile(this.installContext.storageDirectory, artifact.getId()));
ArtifactHandler handler;
if (artifactFile == null || !artifactFile.exists()) {
try {
- handler = this.artifactManager.getArtifactHandler(artifact.getId().toMvnUrl());
+ handler = this.installContext.artifactManager.getArtifactHandler(artifact.getId().toMvnUrl());
} catch (final IOException ignore) {
return false;
}
diff --git a/src/main/java/org/apache/sling/installer/factory/model/impl/UninstallFeatureModelTask.java b/src/main/java/org/apache/sling/installer/factory/model/impl/UninstallFeatureModelTask.java
index b584e6d..d734e4a 100644
--- a/src/main/java/org/apache/sling/installer/factory/model/impl/UninstallFeatureModelTask.java
+++ b/src/main/java/org/apache/sling/installer/factory/model/impl/UninstallFeatureModelTask.java
@@ -18,8 +18,6 @@
*/
package org.apache.sling.installer.factory.model.impl;
-import java.io.File;
-
import org.apache.sling.installer.api.OsgiInstaller;
import org.apache.sling.installer.api.tasks.InstallationContext;
import org.apache.sling.installer.api.tasks.ResourceState;
@@ -48,11 +46,6 @@ public class UninstallFeatureModelTask extends AbstractFeatureModelTask {
ctx.log("Uninstalling {}", resource.getEntityId());
installer.registerResources("model-" + resource.getAttribute(FeatureModelInstallerPlugin.ATTR_ID),
null);
- final String path = (String) resource.getAttribute(FeatureModelInstallerPlugin.ATTR_BASE_PATH);
- if ( path != null ) {
- final File dir = new File(path);
- deleteDirectory(dir);
- }
this.getResourceGroup().setFinishState(ResourceState.UNINSTALLED);
ctx.log("Uninstalled {}", resource.getEntityId());
}
diff --git a/src/test/java/org/apache/sling/installer/factory/model/impl/FeatureModelInstallerPluginTest.java b/src/test/java/org/apache/sling/installer/factory/model/impl/FeatureModelInstallerPluginTest.java
new file mode 100644
index 0000000..04c7eda
--- /dev/null
+++ b/src/test/java/org/apache/sling/installer/factory/model/impl/FeatureModelInstallerPluginTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.installer.factory.model.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
+
+public class FeatureModelInstallerPluginTest {
+
+ @Test
+ public void testNoPatterns() throws Exception {
+ final FeatureModelInstallerPlugin.Config config = Mockito.mock(FeatureModelInstallerPlugin.Config.class);
+ Mockito.when(config.classifierPatterns()).thenReturn(null);
+
+ final FeatureModelInstallerPlugin plugin = new FeatureModelInstallerPlugin(Mockito.mock(BundleContext.class),
+ config);
+ assertTrue(plugin.classifierMatches("foo"));
+ assertTrue(plugin.classifierMatches(null));
+ }
+
+ @Test
+ public void testNoClassifierPattern() throws Exception {
+ final FeatureModelInstallerPlugin.Config config = Mockito.mock(FeatureModelInstallerPlugin.Config.class);
+ Mockito.when(config.classifierPatterns()).thenReturn(new String[] { ":" });
+
+ final FeatureModelInstallerPlugin plugin = new FeatureModelInstallerPlugin(Mockito.mock(BundleContext.class),
+ config);
+ assertFalse(plugin.classifierMatches("foo"));
+ assertTrue(plugin.classifierMatches(null));
+ }
+
+ @Test
+ public void tesClassifierPatterns() throws Exception {
+ final FeatureModelInstallerPlugin.Config config = Mockito.mock(FeatureModelInstallerPlugin.Config.class);
+ Mockito.when(config.classifierPatterns()).thenReturn(new String[] { ":", "*devfar", "*prodfar", "*special*" });
+
+ final FeatureModelInstallerPlugin plugin = new FeatureModelInstallerPlugin(Mockito.mock(BundleContext.class),
+ config);
+
+ assertTrue(plugin.classifierMatches(null));
+ assertTrue(plugin.classifierMatches("mydevfar"));
+ assertTrue(plugin.classifierMatches("myprodfar"));
+ assertTrue(plugin.classifierMatches("superspecialfar"));
+ assertTrue(plugin.classifierMatches("evenmorespecial"));
+
+ assertFalse(plugin.classifierMatches("foo"));
+ assertFalse(plugin.classifierMatches("devmyfar"));
+ assertFalse(plugin.classifierMatches("prodmfar"));
+ }
+}