You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2020/04/29 10:44:21 UTC
[sling-org-apache-sling-installer-factory-feature] 02/08: Update to
support multiple feature files per archive
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 677a88f0a982d04ad9da817e9b4d785d4976191d
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Sat Feb 22 11:16:10 2020 +0100
Update to support multiple feature files per archive
---
.../model/impl/FeatureModelInstallerPlugin.java | 230 +++++++++++++++++++++
.../model/impl/FeatureModelTaskFactory.java | 109 ----------
.../model/impl/FeatureModelTransformer.java | 126 -----------
.../model/impl/InstallFeatureModelTask.java | 8 +-
.../model/impl/UninstallFeatureModelTask.java | 7 +-
5 files changed, 238 insertions(+), 242 deletions(-)
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
new file mode 100644
index 0000000..69df21f
--- /dev/null
+++ b/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelInstallerPlugin.java
@@ -0,0 +1,230 @@
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.io.archive.ArchiveReader;
+import org.apache.sling.feature.io.artifacts.ArtifactManager;
+import org.apache.sling.feature.io.artifacts.ArtifactManagerConfig;
+import org.apache.sling.feature.io.json.FeatureJSONReader;
+import org.apache.sling.feature.io.json.FeatureJSONWriter;
+import org.apache.sling.installer.api.InstallableResource;
+import org.apache.sling.installer.api.tasks.InstallTask;
+import org.apache.sling.installer.api.tasks.InstallTaskFactory;
+import org.apache.sling.installer.api.tasks.RegisteredResource;
+import org.apache.sling.installer.api.tasks.ResourceState;
+import org.apache.sling.installer.api.tasks.ResourceTransformer;
+import org.apache.sling.installer.api.tasks.TaskResource;
+import org.apache.sling.installer.api.tasks.TaskResourceGroup;
+import org.apache.sling.installer.api.tasks.TransformationResult;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.repoinit.JcrRepoInitOpsProcessor;
+import org.apache.sling.repoinit.parser.RepoInitParser;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This task factory processes model resources detected by
+ * the {@link FeatureModelTransformer}.
+ */
+@Component(service = { InstallTaskFactory.class, ResourceTransformer.class })
+@Designate(ocd = FeatureModelInstallerPlugin.Config.class)
+public class FeatureModelInstallerPlugin implements InstallTaskFactory, ResourceTransformer {
+
+ @ObjectClassDefinition(name = "Apache Sling Feature Model Installer",
+ description = "This component provides support for feature models to the OSGi installer")
+ public @interface Config {
+
+ @AttributeDefinition(name = "Use Apache Maven",
+ description = "If enabled, missing artifacts from a feature are tried by invoking the mvn command")
+ boolean useMvn() default true;
+
+ @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.")
+ String[] classifierPatterns();
+ }
+
+ public static final String FILE_EXTENSION = ".json";
+
+ public static final String TYPE_FEATURE_MODEL = "featuremodel";
+
+ public static final String ATTR_MODEL = "feature";
+
+ public static final String ATTR_BASE_PATH = "path";
+
+ public static final String ATTR_ID = "featureId";
+
+ /** Logger. */
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Reference
+ private SlingRepository repository;
+
+ @Reference
+ private JcrRepoInitOpsProcessor repoInitProcessor;
+
+ @Reference
+ private RepoInitParser repoInitParser;
+
+ private final BundleContext bundleContext;
+
+ private final ArtifactManager artifactManager;
+
+ private final List<String> classifierPatterns = new ArrayList<>();
+
+ @Activate
+ public FeatureModelInstallerPlugin(final BundleContext ctx, final Config config) throws IOException {
+ this.bundleContext = ctx;
+ final ArtifactManagerConfig amCfg = new ArtifactManagerConfig();
+ amCfg.setUseMvn(config.useMvn());
+ 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()]));
+ }
+ 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());
+ }
+ }
+ }
+ }
+
+ @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()));
+ } catch (final IOException ioe) {
+ logger.info("Unable to read feature model from " + resource.getURL(), ioe);
+ }
+ }
+ 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) {
+ logger.info("Unable to read feature model from " + resource.getURL(), ioe);
+ }
+ }
+ 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;
+ }
+ }
+ }
+
+ if (!select) {
+ continue;
+ }
+
+ String featureJson = null;
+ try (final StringWriter sw = new StringWriter()) {
+ FeatureJSONWriter.write(sw, feature);
+ featureJson = sw.toString();
+ } catch (final IOException ioe) {
+ logger.info("Unable to read feature model from " + resource.getURL(), ioe);
+ }
+
+ if (featureJson != null) {
+ final TransformationResult tr = new TransformationResult();
+ tr.setResourceType(TYPE_FEATURE_MODEL);
+ tr.setId(feature.getId().toMvnId());
+ tr.setVersion(feature.getId().getOSGiVersion());
+
+ 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);
+ } else {
+ error = true;
+ break;
+ }
+ }
+ if (!error) {
+ return result.toArray(new TransformationResult[result.size()]);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public InstallTask createTask(final TaskResourceGroup group) {
+ final TaskResource rsrc = group.getActiveResource();
+ if (!TYPE_FEATURE_MODEL.equals(rsrc.getType())) {
+ return null;
+ }
+ if (rsrc.getState() == ResourceState.UNINSTALL ) {
+ return new UninstallFeatureModelTask(group, bundleContext);
+ }
+ return new InstallFeatureModelTask(group,
+ this.repository,
+ this.repoInitProcessor,
+ this.repoInitParser,
+ this.bundleContext, this.artifactManager);
+ }
+}
diff --git a/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelTaskFactory.java b/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelTaskFactory.java
deleted file mode 100644
index 60c1e76..0000000
--- a/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelTaskFactory.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.sling.feature.io.artifacts.ArtifactManager;
-import org.apache.sling.feature.io.artifacts.ArtifactManagerConfig;
-import org.apache.sling.installer.api.tasks.InstallTask;
-import org.apache.sling.installer.api.tasks.InstallTaskFactory;
-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.osgi.framework.BundleContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.metatype.annotations.AttributeDefinition;
-import org.osgi.service.metatype.annotations.Designate;
-import org.osgi.service.metatype.annotations.ObjectClassDefinition;
-
-/**
- * This task factory processes model resources detected by
- * the {@link FeatureModelTransformer}.
- */
-@Component(service = InstallTaskFactory.class)
-@Designate(ocd = FeatureModelTaskFactory.Config.class)
-public class FeatureModelTaskFactory implements InstallTaskFactory {
-
- @ObjectClassDefinition(name = "Apache Sling Feature Model Installer",
- description = "This component provides support for feature models to the OSGi installer")
- public @interface Config {
-
- @AttributeDefinition(name = "Use Apache Maven",
- description = "If enabled, missing artifacts from a feature are tried by invoking the mvn command")
- boolean useMvn() default true;
-
- @AttributeDefinition(name = "Repository URLs", description = "Additional repository URLs to fetch artifacts")
- String[] repositories();
- }
-
- @Reference
- private SlingRepository repository;
-
- @Reference
- private JcrRepoInitOpsProcessor repoInitProcessor;
-
- @Reference
- private RepoInitParser repoInitParser;
-
- private final BundleContext bundleContext;
-
- private final ArtifactManager artifactManager;
-
- @Activate
- public FeatureModelTaskFactory(final BundleContext ctx, final Config config) throws IOException {
- this.bundleContext = ctx;
- final ArtifactManagerConfig amCfg = new ArtifactManagerConfig();
- amCfg.setUseMvn(config.useMvn());
- 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()]));
- }
- this.artifactManager = ArtifactManager.getArtifactManager(amCfg);
- }
-
- @Override
- public InstallTask createTask(final TaskResourceGroup group) {
- final TaskResource rsrc = group.getActiveResource();
- if (!FeatureModelTransformer.TYPE_FEATURE_MODEL.equals(rsrc.getType())) {
- return null;
- }
- if (rsrc.getState() == ResourceState.UNINSTALL ) {
- return new UninstallFeatureModelTask(group, bundleContext);
- }
- return new InstallFeatureModelTask(group,
- this.repository,
- this.repoInitProcessor,
- this.repoInitParser,
- this.bundleContext, this.artifactManager);
- }
-}
diff --git a/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelTransformer.java b/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelTransformer.java
deleted file mode 100644
index 57b6b99..0000000
--- a/src/main/java/org/apache/sling/installer/factory/model/impl/FeatureModelTransformer.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.apache.sling.installer.factory.model.impl;/*
- * 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.
- */
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.io.archive.ArchiveReader;
-import org.apache.sling.feature.io.json.FeatureJSONReader;
-import org.apache.sling.feature.io.json.FeatureJSONWriter;
-import org.apache.sling.installer.api.InstallableResource;
-import org.apache.sling.installer.api.tasks.RegisteredResource;
-import org.apache.sling.installer.api.tasks.ResourceTransformer;
-import org.apache.sling.installer.api.tasks.TransformationResult;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This transformer detects a file with the ending ".feature" containing a
- * feature model or a feature model archive ending in ".far"
- */
-@Component(service = ResourceTransformer.class)
-public class FeatureModelTransformer implements ResourceTransformer {
-
- public static final String FILE_EXTENSION = ".json";
-
- public static final String TYPE_FEATURE_MODEL = "featuremodel";
-
- public static final String ATTR_MODEL = "feature";
-
- public static final String ATTR_BASE_PATH = "path";
-
- public static final String ATTR_ID = "featureId";
-
- /** Logger. */
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- private final BundleContext bundleContext;
-
- @Activate
- public FeatureModelTransformer(final BundleContext bc) {
- this.bundleContext = bc;
- }
-
- @Override
- public TransformationResult[] transform(final RegisteredResource resource) {
- Feature feature = null;
- 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") ) {
- feature = FeatureJSONReader.read(reader, resource.getURL());
- } catch ( final IOException ioe) {
- logger.info("Unable to read feature model from " + resource.getURL(), ioe);
- }
- }
- if (resource.getType().equals(InstallableResource.TYPE_FILE)
- && resource.getURL().endsWith(".zip")) {
- baseDir = this.bundleContext.getDataFile("");
- try ( final InputStream is = resource.getInputStream() ) {
-
- feature = ArchiveReader.read(is, new ArchiveReader.ArtifactConsumer() {
- @Override
- public void consume(final ArtifactId artifact, final InputStream is) throws IOException {
- // nothing to do, install task does extraction
- }
- });
- } catch ( final IOException ioe) {
- logger.info("Unable to read feature model from " + resource.getURL(), ioe);
- }
- }
- if (feature != null) {
- String featureJson = null;
- try (final StringWriter sw = new StringWriter()) {
- FeatureJSONWriter.write(sw, feature);
- featureJson = sw.toString();
- } catch (final IOException ioe) {
- logger.info("Unable to read feature model from " + resource.getURL(), ioe);
- }
-
- if (featureJson != null) {
- final TransformationResult tr = new TransformationResult();
- tr.setResourceType(TYPE_FEATURE_MODEL);
- tr.setId(feature.getId().toMvnId());
- tr.setVersion(feature.getId().getOSGiVersion());
-
- 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);
-
- return new TransformationResult[] { tr };
- }
- }
- return null;
- }
-}
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 55f3f5c..3dde406 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
@@ -89,12 +89,12 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
try {
final TaskResource resource = this.getResource();
ctx.log("Installing {}", resource.getEntityId());
- final String featureJson = (String) resource.getAttribute(FeatureModelTransformer.ATTR_MODEL);
+ final String featureJson = (String) resource.getAttribute(FeatureModelInstallerPlugin.ATTR_MODEL);
if (featureJson == null) {
ctx.log("Unable to install feature model resource {} : no model found", resource);
this.getResourceGroup().setFinishState(ResourceState.IGNORED);
} else {
- final String path = (String) resource.getAttribute(FeatureModelTransformer.ATTR_BASE_PATH);
+ final String path = (String) resource.getAttribute(FeatureModelInstallerPlugin.ATTR_BASE_PATH);
final File baseDir = (path == null ? null : new File(path));
boolean success = false;
@@ -140,7 +140,7 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
final OsgiInstaller installer = this.getService(OsgiInstaller.class);
if ( installer != null ) {
installer.registerResources(
- "model-" + resource.getAttribute(FeatureModelTransformer.ATTR_ID),
+ "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",
@@ -285,6 +285,6 @@ public class InstallFeatureModelTask extends AbstractFeatureModelTask {
@Override
public String getSortKey() {
- return "30-" + getResource().getAttribute(FeatureModelTransformer.ATTR_ID);
+ return "30-" + getResource().getAttribute(FeatureModelInstallerPlugin.ATTR_ID);
}
}
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 ed437de..b584e6d 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
@@ -46,8 +46,9 @@ public class UninstallFeatureModelTask extends AbstractFeatureModelTask {
} else {
final TaskResource resource = this.getResource();
ctx.log("Uninstalling {}", resource.getEntityId());
- installer.registerResources("model-" + resource.getAttribute(FeatureModelTransformer.ATTR_ID), null);
- final String path = (String)resource.getAttribute(FeatureModelTransformer.ATTR_BASE_PATH);
+ 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);
@@ -62,6 +63,6 @@ public class UninstallFeatureModelTask extends AbstractFeatureModelTask {
@Override
public String getSortKey() {
- return "31-" + getResource().getAttribute(FeatureModelTransformer.ATTR_ID);
+ return "31-" + getResource().getAttribute(FeatureModelInstallerPlugin.ATTR_ID);
}
}