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

nfilotto pushed a commit to branch camel-karaf-4.8.x
in repository https://gitbox.apache.org/repos/asf/camel-karaf.git


The following commit(s) were added to refs/heads/camel-karaf-4.8.x by this push:
     new 3e8a241bb Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped 
bundles (#591)
3e8a241bb is described below

commit 3e8a241bbb60c64b26b6110bc327bc03d7a3cb19
Author: François de Parscau <116000379+f2p...@users.noreply.github.com>
AuthorDate: Thu Jan 30 14:15:52 2025 +0100

    Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles (#591)
    
    Motivation
    Very long names in karaf console when listing bundles by names or symbolic 
names
    
    Modifications:
    Add Bundle-Name= and Bundle-SymbolicName= to the wrapped bundles
---
 features/pom.xml                                   |   1 +
 features/src/main/feature/camel-features.xml       |   2 +-
 .../feature/maven/EnsureWrapBundleNameMojo.java    | 142 +++++++++++++++++++++
 .../maven/EnsureWrapBundleNameMojoTest.java        |  77 +++++++++++
 4 files changed, 221 insertions(+), 1 deletion(-)

diff --git a/features/pom.xml b/features/pom.xml
index c1a926148..0d947d994 100644
--- a/features/pom.xml
+++ b/features/pom.xml
@@ -76,6 +76,7 @@
                         <goals>
                             <goal>auto-detect-version</goal>
                             <goal>ensure-wrap-bundle-version</goal>
+                            <goal>ensure-wrap-bundle-name</goal>
                             <goal>configure-wrap-spi-provider</goal>
                         </goals>
                         <configuration>
diff --git a/features/src/main/feature/camel-features.xml 
b/features/src/main/feature/camel-features.xml
index 362aa0117..b05258290 100644
--- a/features/src/main/feature/camel-features.xml
+++ b/features/src/main/feature/camel-features.xml
@@ -1128,7 +1128,7 @@
         <feature version='${camel-osgi-version-range}'>camel-core</feature>
         <bundle 
dependency='true'>wrap:mvn:com.alibaba/fastjson/${fastjson-version}</bundle>
         <bundle 
dependency='true'>wrap:mvn:com.alibaba.fastjson2/fastjson2/${auto-detect-version}</bundle>
-        <bundle 
dependency='true'>wrap:mvn:com.alibaba.fastjson2/fastjson2-extension/${auto-detect-version}</bundle>
+        <bundle 
dependency='true'>wrap:mvn:com.alibaba.fastjson2/fastjson2-extension/${auto-detect-version}$Fragment-Host=wrap_com.alibaba.fastjson2.fastjson2</bundle>
         
<bundle>mvn:org.apache.camel.karaf/camel-fastjson/${project.version}</bundle>
     </feature>
     <feature name='camel-fhir' version='${project.version}' start-level='50'>
diff --git 
a/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java
 
b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java
new file mode 100644
index 000000000..714e42d21
--- /dev/null
+++ 
b/tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java
@@ -0,0 +1,142 @@
+/*
+ * 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.camel.karaf.feature.maven;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.karaf.features.internal.model.Bundle;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+
+@Mojo(name = "ensure-wrap-bundle-name", defaultPhase = 
LifecyclePhase.PROCESS_RESOURCES)
+public class EnsureWrapBundleNameMojo extends AbstractWrapBundleMojo {
+
+    private static final List<String> HEADERS_AFTER_BUNDLE_NAME = 
Arrays.asList(
+            "Bundle-Version",
+            "DynamicImport-Package",
+            "Export-Package",
+            "Export-Service",
+            "Fragment-Host",
+            "Import-Package",
+            "Import-Service",
+            "Provide-Capability",
+            "Require-Bundle",
+            "Require-Capability");
+    
+    private static final String BUNDLE_NAME = "Bundle-Name";
+    private static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+
+    private static String toPascalCase(String kebabCase) {
+        // Handle null or empty string
+        if (kebabCase == null || kebabCase.isEmpty()) {
+            return kebabCase;
+        }
+
+        // Split by hyphen
+        String[] words = kebabCase.split("-");
+        StringBuilder result = new StringBuilder();
+
+        // Capitalize first letter of each word
+        for (int i = 0; i < words.length; i++) {
+            String word = words[i];
+            if (word.isEmpty()) {
+                continue;
+            }
+            result.append(Character.toUpperCase(word.charAt(0)));
+            if (word.length() > 1) {
+                result.append(word.substring(1).toLowerCase());
+            }
+            // Only add %20 if it's not the last word
+            if (i < words.length - 1) {
+                result.append("%20");
+            }
+        }
+        return result.toString();
+    }
+
+    @Override
+    protected boolean processWrappedBundle(WrappedBundle wrappedBundle) {
+        Bundle bundle = wrappedBundle.getBundle();
+        String location = bundle.getLocation();
+        try {
+            bundle.setLocation(processLocation(wrappedBundle));
+        } catch (Exception e) {
+            getLog().error("Could not process the Bundle location '%s': 
%s".formatted(location, e.getMessage()), e);
+        }
+        return false;
+    }
+
+    String processLocation(WrappedBundle wrappedBundle) throws Exception {
+        String location = wrappedBundle.getBundle().getLocation();
+        String instructions = wrappedBundle.getInstructions();
+        boolean dollarNeeded = instructions == null || 
!instructions.contains("$");
+
+        String bundleNameHeader = "%s=Wrap%%20of%%20%s".formatted(BUNDLE_NAME, 
toPascalCase(wrappedBundle.getArtifactId()));
+        String bundleSymbolicNameHeader = 
"%s=wrap_%s.%s".formatted(BUNDLE_SYMBOLIC_NAME, wrappedBundle.getGroupId(), 
wrappedBundle.getArtifactId());
+        Map<String, String> headers = new TreeMap<>(); //sorted by key
+        headers.put(BUNDLE_NAME, bundleNameHeader);
+        headers.put(BUNDLE_SYMBOLIC_NAME, bundleSymbolicNameHeader);
+
+        return insertHeaderIfNeeded(dollarNeeded, location, headers);
+    }
+
+
+    private String insertHeaderIfNeeded(boolean dollarNeeded, String location, 
Map<String, String> headers) {
+
+        StringBuilder sb = new StringBuilder(location);
+        for (Map.Entry<String, String> entry : headers.entrySet()) {
+            if (location.contains(entry.getKey())) {
+                continue;
+            }
+            boolean hasChanged = false;
+            // insert before existing headers header
+            for (String header : HEADERS_AFTER_BUNDLE_NAME) {
+                // add Bundle-Version before
+                if (location.contains(header)) {
+                    int versionHeaderStartIndex = location.indexOf(header);
+                    if (dollarNeeded) {
+                        // "amp;" is automatically added
+                        dollarNeeded = false;
+                        location = sb.insert(versionHeaderStartIndex, 
"$%s&".formatted(entry.getValue())).toString();
+                    } else {
+                        // "amp;" is automatically added
+                        location = sb.insert(versionHeaderStartIndex, 
"%s&".formatted(entry.getValue())).toString();
+                    }
+                    hasChanged = true;
+                    break;
+                }
+            }
+            if (hasChanged) {
+                //header already handled, go to next
+                continue;
+            }
+
+            // insert at the end
+            if (dollarNeeded) {
+                dollarNeeded = false;
+                location = sb.insert(location.length(), 
"$%s".formatted(entry.getValue())).toString();
+            } else {
+                // "amp;" is automatically added
+                location = sb.insert(location.length(), 
"&%s".formatted(entry.getValue())).toString();
+            }
+        }
+        return location;
+    }
+}
\ No newline at end of file
diff --git 
a/tooling/camel-karaf-feature-maven-plugin/src/test/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojoTest.java
 
b/tooling/camel-karaf-feature-maven-plugin/src/test/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojoTest.java
new file mode 100644
index 000000000..2e9730af3
--- /dev/null
+++ 
b/tooling/camel-karaf-feature-maven-plugin/src/test/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojoTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.camel.karaf.feature.maven;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.apache.karaf.features.internal.model.Bundle;
+import org.junit.jupiter.api.Test;
+
+public class EnsureWrapBundleNameMojoTest {
+
+    private final EnsureWrapBundleNameMojo ensureNameMojo = new 
EnsureWrapBundleNameMojo();
+
+    @Test
+    void modifyLocationTest() throws Exception {
+        Bundle bundle = new Bundle();
+        // add bundle name at the end as first wrap protocol option
+        
bundle.setLocation("wrap:mvn:org.apache.olingo/odata-server-core/5.0.0");
+        String expected = 
"wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$Bundle-Name=Wrap%20of%20Odata%20Server%20Core&Bundle-SymbolicName=wrap_org.apache.olingo.odata-server-core";
+        WrappedBundle wrappedBundle = WrappedBundle.fromBundle(bundle);
+        assertNotNull(wrappedBundle);
+        assertEquals(expected, ensureNameMojo.processLocation(wrappedBundle));
+
+        // add bundle name at the end but not as first wrap protocol option
+        
bundle.setLocation("wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$overwrite=merge");
+        expected = 
"wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$overwrite=merge&Bundle-Name=Wrap%20of%20Odata%20Server%20Core&Bundle-SymbolicName=wrap_org.apache.olingo.odata-server-core";
+        wrappedBundle = WrappedBundle.fromBundle(bundle);
+        assertNotNull(wrappedBundle);
+        assertEquals(expected, ensureNameMojo.processLocation(wrappedBundle));
+
+        // add bundle name before existing wrap protocol header that should be 
declared after
+        
bundle.setLocation("wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$overwrite=merge&Export-Package=org.apache.olingo.*;version=5.0.0");
+        expected = 
"wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$overwrite=merge&Bundle-Name=Wrap%20of%20Odata%20Server%20Core&Bundle-SymbolicName=wrap_org.apache.olingo.odata-server-core&Export-Package=org.apache.olingo.*;version=5.0.0";
+        wrappedBundle = WrappedBundle.fromBundle(bundle);
+        assertNotNull(wrappedBundle);
+        assertEquals(expected, ensureNameMojo.processLocation(wrappedBundle));
+
+        // add bundle name before existing wrap protocol header that should be 
declared after
+        
bundle.setLocation("wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$overwrite=merge&Bundle-Version=5.0.0&Export-Package=org.apache.olingo.*;version=5.0.0");
+        expected = 
"wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$overwrite=merge&Bundle-Name=Wrap%20of%20Odata%20Server%20Core&Bundle-SymbolicName=wrap_org.apache.olingo.odata-server-core&Bundle-Version=5.0.0&Export-Package=org.apache.olingo.*;version=5.0.0";
+        wrappedBundle = WrappedBundle.fromBundle(bundle);
+        assertNotNull(wrappedBundle);
+        assertEquals(expected, ensureNameMojo.processLocation(wrappedBundle));
+
+        // don't override the Bundle-Name if present
+        
bundle.setLocation("wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$Bundle-Name=MyName");
+        expected = 
"wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$Bundle-Name=MyName&Bundle-SymbolicName=wrap_org.apache.olingo.odata-server-core";
+        wrappedBundle = WrappedBundle.fromBundle(bundle);
+        assertNotNull(wrappedBundle);
+        assertEquals(expected, ensureNameMojo.processLocation(wrappedBundle));
+
+        // don't override the Bundle-SymbolicName if present
+        
bundle.setLocation("wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$Bundle-SymbolicName=MyName");
+        expected = 
"wrap:mvn:org.apache.olingo/odata-server-core/5.0.0$Bundle-SymbolicName=MyName&Bundle-Name=Wrap%20of%20Odata%20Server%20Core";
+        wrappedBundle = WrappedBundle.fromBundle(bundle);
+        assertNotNull(wrappedBundle);
+        assertEquals(expected, ensureNameMojo.processLocation(wrappedBundle));
+
+    }
+
+
+}
\ No newline at end of file

Reply via email to