This is an automated email from the ASF dual-hosted git repository. cziegeler 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 <[email protected]> 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")); + } +}
