sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dav...@apache.org
Subject [sling-org-apache-sling-installer-factory-feature] 02/32: Update to support multiple feature files per archive
Date Tue, 01 Sep 2020 16:32:53 GMT
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 677a88f0a982d04ad9da817e9b4d785d4976191d
Author: Carsten Ziegeler <cziegeler@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);
     }
 }


Mime
View raw message