You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gg...@apache.org on 2017/12/04 10:12:41 UTC

[karaf] 07/12: [KARAF-5468] Add comments to generated target/assembly/etc/profile.cfg

This is an automated email from the ASF dual-hosted git repository.

ggrzybek pushed a commit to branch KARAF-5376-overrides_v2
in repository https://gitbox.apache.org/repos/asf/karaf.git

commit 9abc1109714628e6d624b38b813dc4b78ec9a48b
Author: Grzegorz Grzybek <gr...@gmail.com>
AuthorDate: Fri Nov 17 12:58:20 2017 +0100

    [KARAF-5468] Add comments to generated target/assembly/etc/profile.cfg
---
 .../org/apache/karaf/profile/ProfileConstants.java |   5 +
 .../org/apache/karaf/profile/assembly/Builder.java |   2 -
 .../karaf/profile/impl/ProfileBuilderImpl.java     | 187 ++++++++++++++++++---
 .../apache/karaf/profile/impl/PropertiesTest.java  |  41 +++++
 4 files changed, 211 insertions(+), 24 deletions(-)

diff --git a/profile/src/main/java/org/apache/karaf/profile/ProfileConstants.java b/profile/src/main/java/org/apache/karaf/profile/ProfileConstants.java
index fe9417d..8df688b 100644
--- a/profile/src/main/java/org/apache/karaf/profile/ProfileConstants.java
+++ b/profile/src/main/java/org/apache/karaf/profile/ProfileConstants.java
@@ -46,6 +46,11 @@ public interface ProfileConstants {
     String HIDDEN = "hidden";
 
     /**
+     * The attribute key for the <em>overlay</em> flag meaning the parents are already included/merged in the profile.
+     */
+    String OVERLAY = "overlay";
+
+    /**
      * <p>Key indicating a deletion.</p>
      * <p>This value can appear as the value of a key in a configuration
      * or as a key itself.  If used as a key, the whole configuration
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
index 6df4243..672d166 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
@@ -788,7 +788,6 @@ public class Builder {
         // Unzip KARs
         //
         LOGGER.info("Unzipping kars");
-//        Map<String, RepositoryInfo> repositories = new LinkedHashMap<>(this.repositories);
         Downloader downloader = manager.createDownloader();
         for (String kar : kars.keySet()) {
             downloader.download(kar, null);
@@ -811,7 +810,6 @@ public class Builder {
         // Propagate feature installation from repositories
         //
         LOGGER.info("Loading repositories");
-//        Map<String, Stage> features = new LinkedHashMap<>(this.features);
         Map<String, Features> karRepositories = loadRepositories(manager, repositories.keySet(), false);
         for (String repo : repositories.keySet()) {
             RepositoryInfo info = repositories.get(repo);
diff --git a/profile/src/main/java/org/apache/karaf/profile/impl/ProfileBuilderImpl.java b/profile/src/main/java/org/apache/karaf/profile/impl/ProfileBuilderImpl.java
index 10331bd..24dbe98 100644
--- a/profile/src/main/java/org/apache/karaf/profile/impl/ProfileBuilderImpl.java
+++ b/profile/src/main/java/org/apache/karaf/profile/impl/ProfileBuilderImpl.java
@@ -22,15 +22,18 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
+import org.apache.felix.utils.properties.TypedProperties;
 import org.apache.karaf.profile.Profile;
 import org.apache.karaf.profile.ProfileBuilder;
 
+import static org.apache.karaf.profile.ProfileConstants.*;
 import static org.apache.karaf.profile.impl.ProfileImpl.ConfigListType;
 
 /**
@@ -39,7 +42,7 @@ import static org.apache.karaf.profile.impl.ProfileImpl.ConfigListType;
 public final class ProfileBuilderImpl implements ProfileBuilder {
 
 	private String profileId;
-	private Map<String, byte[]> fileMapping = new HashMap<>();
+	private Map<String, FileContent> fileMapping = new HashMap<>();
 	private boolean isOverlay;
 	
 	@Override
@@ -58,7 +61,7 @@ public final class ProfileBuilderImpl implements ProfileBuilder {
 	@Override
     public List<String> getParents() {
         Map<String, Object> config = getConfigurationInternal(Profile.INTERNAL_PID);
-        String pspec = (String) config.get(Profile.PARENTS);
+        String pspec = (String) config.get(PARENTS);
         String[] parentIds = pspec != null ? pspec.split(" ") : new String[0];
         return Arrays.asList(parentIds);
     }
@@ -100,9 +103,9 @@ public final class ProfileBuilderImpl implements ProfileBuilder {
 
     private void updateParentsAttribute(Collection<String> parentIds) {
         Map<String, Object> config = getConfigurationInternal(Profile.INTERNAL_PID);
-        config.remove(Profile.PARENTS);
+        config.remove(PARENTS);
         if (parentIds.size() > 0) {
-            config.put(Profile.PARENTS, parentsAttributeValue(parentIds));
+            config.put(PARENTS, parentsAttributeValue(parentIds));
         }
         addConfiguration(Profile.INTERNAL_PID, config);
     }
@@ -118,18 +121,19 @@ public final class ProfileBuilderImpl implements ProfileBuilder {
 
     @Override
     public byte[] getFileConfiguration(String key) {
-        return fileMapping.get(key);
+        return fileMapping.get(key) == null ? null : fileMapping.get(key).bytes;
     }
 
-	@Override
-	public ProfileBuilder setFileConfigurations(Map<String, byte[]> configurations) {
-		fileMapping = new HashMap<>(configurations);
-		return this;
-	}
+    @Override
+    public ProfileBuilder setFileConfigurations(Map<String, byte[]> configurations) {
+        fileMapping = new HashMap<>();
+        configurations.forEach((name, bytes) -> fileMapping.put(name, new FileContent(bytes, false)));
+        return this;
+    }
 
     @Override
     public ProfileBuilder addFileConfiguration(String fileName, byte[] data) {
-        fileMapping.put(fileName, data);
+        fileMapping.put(fileName, new FileContent(data, false));
         return this;
     }
 
@@ -152,7 +156,7 @@ public final class ProfileBuilderImpl implements ProfileBuilder {
 
     @Override
     public ProfileBuilder addConfiguration(String pid, Map<String, Object> config) {
-        fileMapping.put(pid + Profile.PROPERTIES_SUFFIX, Utils.toBytes(config));
+        fileMapping.put(pid + Profile.PROPERTIES_SUFFIX, new FileContent(Utils.toBytes(config), true));
         return this;
     }
 
@@ -181,8 +185,8 @@ public final class ProfileBuilderImpl implements ProfileBuilder {
     }
 
     private Map<String, Object> getConfigurationInternal(String pid) {
-        byte[] bytes = fileMapping.get(pid + Profile.PROPERTIES_SUFFIX);
-        return Utils.toProperties(bytes);
+        FileContent content = fileMapping.get(pid + Profile.PROPERTIES_SUFFIX);
+        return Utils.toProperties(content == null ? null : content.bytes);
     }
     
     @Override
@@ -239,10 +243,11 @@ public final class ProfileBuilderImpl implements ProfileBuilder {
         return this;
     }
 
-	public ProfileBuilder setOverlay(boolean overlay) {
-		this.isOverlay = overlay;
-		return this;
-	}
+    public ProfileBuilder setOverlay(boolean overlay) {
+        this.isOverlay = overlay;
+        addConfiguration(Profile.INTERNAL_PID, Profile.ATTRIBUTE_PREFIX + Profile.OVERLAY, Boolean.toString(overlay));
+        return this;
+    }
 
 	@Override
     public ProfileBuilder addAttribute(String key, String value) {
@@ -286,10 +291,148 @@ public final class ProfileBuilderImpl implements ProfileBuilder {
         addConfiguration(Profile.INTERNAL_PID, config);
     }
 
-
+    /**
+     * Returns an immutable implementation of {@link Profile}
+     * @return
+     */
     @Override
-	public Profile getProfile() {
-		return new ProfileImpl(profileId, getParents(), fileMapping, isOverlay);
-	}
+    public Profile getProfile() {
+        // reformatting all generated files.
+        Map<String, byte[]> files = new LinkedHashMap<>();
+        fileMapping.forEach((k, v) -> files.put(k, reformat(k, v)));
+        return new ProfileImpl(profileId, getParents(), files, isOverlay);
+    }
+
+    /**
+     * If some properties file has been marked as {@link FileContent#generated}, then we can add some comment hints.
+     * @param name
+     * @param fileContent
+     * @return
+     */
+    private byte[] reformat(String name, FileContent fileContent) {
+        if (!fileContent.generated && !(isOverlay && name.equals(INTERNAL_PID + PROPERTIES_SUFFIX))) {
+            return fileContent.bytes;
+        }
+
+        TypedProperties properties = Utils.toProperties(fileContent.bytes);
+        TypedProperties result = Utils.toProperties((byte[])null);
+
+        String parents = null;
+        Map<String, Object> attributes = new LinkedHashMap<>();
+        Map<String, Object> repositories = new LinkedHashMap<>();
+        Map<String, Object> features = new LinkedHashMap<>();
+        Map<String, Object> bundles = new LinkedHashMap<>();
+        Map<String, Object> libraries = new LinkedHashMap<>();
+        Map<String, Object> bootLibraries = new LinkedHashMap<>();
+        Map<String, Object> endorsedLibraries = new LinkedHashMap<>();
+        Map<String, Object> extLibraries = new LinkedHashMap<>();
+        Map<String, Object> config = new LinkedHashMap<>();
+        Map<String, Object> system = new LinkedHashMap<>();
+        Map<String, Object> overrides = new LinkedHashMap<>();
+        Map<String, Object> optionals = new LinkedHashMap<>();
+        for (String key : properties.keySet()) {
+            Object v = properties.get(key);
+            if (key.equals(PARENTS)) {
+                parents = (String) v;
+            } else if (key.startsWith(ATTRIBUTE_PREFIX)) {
+                attributes.put(key, v);
+            } else if (key.startsWith(REPOSITORY_PREFIX)) {
+                repositories.put(key, v);
+            } else if (key.startsWith(FEATURE_PREFIX)) {
+                features.put(key, v);
+            } else if (key.startsWith(BUNDLE_PREFIX)) {
+                bundles.put(key, v);
+            } else if (key.startsWith(LIB_PREFIX)) {
+                libraries.put(key, v);
+            } else if (key.startsWith(BOOT_PREFIX)) {
+                bootLibraries.put(key, v);
+            } else if (key.startsWith(ENDORSED_PREFIX)) {
+                endorsedLibraries.put(key, v);
+            } else if (key.startsWith(EXT_PREFIX)) {
+                extLibraries.put(key, v);
+            } else if (key.startsWith(CONFIG_PREFIX)) {
+                config.put(key, v);
+            } else if (key.startsWith(SYSTEM_PREFIX)) {
+                system.put(key, v);
+            } else if (key.startsWith(OVERRIDE_PREFIX)) {
+                overrides.put(key, v);
+            } else if (key.startsWith(OPTIONAL_PREFIX)) {
+                optionals.put(key, v);
+            }
+        }
+
+        result.setHeader(Arrays.asList("#", "# Profile generated by Karaf Assembly Builder", "#"));
+        if (parents != null) {
+            result.put(PARENTS, comment("Parent profiles"), parents);
+        }
+        addGroupOfProperties("Attributes", result, attributes);
+        addGroupOfProperties("Feature XML repositories", result, repositories);
+        addGroupOfProperties("Features", result, features);
+        addGroupOfProperties("Bundles", result, bundles);
+        addGroupOfProperties("Libraries", result, libraries);
+        addGroupOfProperties("Boot libraries", result, bootLibraries);
+        addGroupOfProperties("Endorsed libraries", result, endorsedLibraries);
+        addGroupOfProperties("Extension libraries", result, extLibraries);
+        addGroupOfProperties("Configuration properties for etc/config.properties", result, config);
+        addGroupOfProperties("Configuration properties for etc/system.properties", result, system);
+        addGroupOfProperties("Bundle overrides (deprecated)", result, overrides);
+        addGroupOfProperties("Optional resources for resolution", result, optionals);
+
+        return Utils.toBytes(result);
+    }
+
+    /**
+     * Puts properties under single comment.
+     * @param comment
+     * @param properties
+     * @param values
+     */
+    private void addGroupOfProperties(String comment, TypedProperties properties, Map<String, Object> values) {
+        boolean first = true;
+        for (Entry<String, Object> entry : values.entrySet()) {
+            if (first) {
+                first = false;
+                properties.put(entry.getKey(), comment(comment), entry.getValue());
+            } else {
+                properties.put(entry.getKey(), entry.getValue());
+            }
+        }
+    }
+
+    /**
+     * Helper method to generate comments above property groups in {@link TypedProperties}
+     * @param comment
+     * @return
+     */
+    private List<String> comment(String comment) {
+        return Arrays.asList("", "# " + comment);
+    }
+
+    /**
+     * We can distinguish between bytes read from external file and bytes from serialized
+     * {@link org.apache.felix.utils.properties.TypedProperties}
+     */
+    static class FileContent {
+        byte[] bytes;
+        boolean generated;
+
+        public FileContent(byte[] bytes, boolean generated) {
+            this.bytes = bytes;
+            this.generated = generated;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            FileContent that = (FileContent) o;
+            return Arrays.equals(bytes, that.bytes);
+        }
+
+        @Override
+        public int hashCode() {
+            return Arrays.hashCode(bytes);
+        }
+    }
 
 }
diff --git a/profile/src/test/java/org/apache/karaf/profile/impl/PropertiesTest.java b/profile/src/test/java/org/apache/karaf/profile/impl/PropertiesTest.java
new file mode 100644
index 0000000..a8a0edc
--- /dev/null
+++ b/profile/src/test/java/org/apache/karaf/profile/impl/PropertiesTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.profile.impl;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.felix.utils.properties.TypedProperties;
+import org.junit.Test;
+
+public class PropertiesTest {
+
+    @Test
+    public void typedProperties() throws IOException {
+        TypedProperties tp = new TypedProperties();
+        tp.put("commented-key", "# commented-key comment", "value");
+        tp.put("commented-key2", Arrays.asList("# ca", "# cb"), "value");
+        tp.put("normal-key", "value");
+        tp.put("listed-key", Arrays.asList("# ca", "# cb"), Arrays.asList("va", "vb"));
+        tp.setHeader(Arrays.asList("#", "# ASF License 2.0", "#"));
+        tp.setFooter(Arrays.asList("#", "# bye!", "#"));
+        tp.save(System.out);
+    }
+
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@karaf.apache.org" <co...@karaf.apache.org>.