You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by "f2par0 (via GitHub)" <gi...@apache.org> on 2025/01/29 16:20:52 UTC

[PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

f2par0 opened a new pull request, #591:
URL: https://github.com/apache/camel-karaf/pull/591

   Fixes #590 
   
   **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


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "essobedo (via GitHub)" <gi...@apache.org>.
essobedo commented on PR #591:
URL: https://github.com/apache/camel-karaf/pull/591#issuecomment-2623919888

   It looks like it causes a regression in the IT of camel-fastjson


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "essobedo (via GitHub)" <gi...@apache.org>.
essobedo commented on code in PR #591:
URL: https://github.com/apache/camel-karaf/pull/591#discussion_r1935100294


##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,144 @@
+/*
+ * 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";
+
+    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("$"));

Review Comment:
   ```suggestion
           boolean dollarNeeded = instructions == null || !instructions.contains("$");
   ```
   Is-it easier to read like this, don't you agree?



##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,144 @@
+/*
+ * 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";
+
+    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();
+                        hasChanged = true;
+                        break;

Review Comment:
   You seem to repeat the exact same lines in both cases (if and else blocks) so I think that you can move them after the if/else block



##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * 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.concurrent.atomic.AtomicBoolean;
+
+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");
+    
+    static final String BUNDLE_NAME = "Bundle-Name";
+    static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+
+    static String toPascalCase(String kebabCase) {

Review Comment:
   You did not change anything here, does it mean that it cannot be private, or you forgot to change it?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "essobedo (via GitHub)" <gi...@apache.org>.
essobedo commented on code in PR #591:
URL: https://github.com/apache/camel-karaf/pull/591#discussion_r1934293070


##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * 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.concurrent.atomic.AtomicBoolean;
+
+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");
+    
+    static final String BUNDLE_NAME = "Bundle-Name";
+    static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+
+    static String toPascalCase(String kebabCase) {

Review Comment:
   can be private?



##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * 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.concurrent.atomic.AtomicBoolean;
+
+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");
+    
+    static final String BUNDLE_NAME = "Bundle-Name";
+    static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+
+    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()) {

Review Comment:
   To improve a little bit the readability, you could instead check if isEmpty and if so continue the iteration



##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * 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.concurrent.atomic.AtomicBoolean;
+
+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");
+    
+    static final String BUNDLE_NAME = "Bundle-Name";
+    static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+
+    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()) {
+                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();
+        AtomicBoolean dollarNeeded = new AtomicBoolean(!(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());
+
+        location = insertHeaderIfNeeded(dollarNeeded, location, BUNDLE_NAME, bundleNameHeader);
+        return insertHeaderIfNeeded(dollarNeeded, location, BUNDLE_SYMBOLIC_NAME, bundleSymbolicNameHeader);
+    }
+
+    private String insertHeaderIfNeeded(AtomicBoolean dollarNeeded, String location, String headerName, String fullHeader) {

Review Comment:
   Would it be possible to get rid of the AtomicBoolean by providing a list of header names and replace it by a simple boolean?



##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * 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.concurrent.atomic.AtomicBoolean;
+
+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");
+    
+    static final String BUNDLE_NAME = "Bundle-Name";
+    static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+
+    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()) {
+                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();
+        AtomicBoolean dollarNeeded = new AtomicBoolean(!(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());
+
+        location = insertHeaderIfNeeded(dollarNeeded, location, BUNDLE_NAME, bundleNameHeader);
+        return insertHeaderIfNeeded(dollarNeeded, location, BUNDLE_SYMBOLIC_NAME, bundleSymbolicNameHeader);
+    }
+
+    private String insertHeaderIfNeeded(AtomicBoolean dollarNeeded, String location, String headerName, String fullHeader) {
+        if (location.contains(headerName)) {
+            return location;
+        }
+        StringBuilder sb = new StringBuilder(location);
+
+        // 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.get()) {
+                    // "amp;" is automatically added
+                    return sb.insert(versionHeaderStartIndex, "%s&".formatted(fullHeader)).toString();
+                } else {
+                    // "amp;" is automatically added
+                    dollarNeeded.set(false);
+                    return sb.insert(versionHeaderStartIndex, "$%s&".formatted(fullHeader)).toString();
+                }

Review Comment:
   For a better readibility, I would keep the same order as below https://github.com/apache/camel-karaf/pull/591/files#diff-ab619fa88de63d711e3925a32a40a68831b014167fe830aad41c777daa7d823aR120-R126. I mean if dollarNeeded.get() ... else



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "f2par0 (via GitHub)" <gi...@apache.org>.
f2par0 commented on code in PR #591:
URL: https://github.com/apache/camel-karaf/pull/591#discussion_r1934711938


##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * 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.concurrent.atomic.AtomicBoolean;
+
+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");
+    
+    static final String BUNDLE_NAME = "Bundle-Name";
+    static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+
+    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()) {
+                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();
+        AtomicBoolean dollarNeeded = new AtomicBoolean(!(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());
+
+        location = insertHeaderIfNeeded(dollarNeeded, location, BUNDLE_NAME, bundleNameHeader);
+        return insertHeaderIfNeeded(dollarNeeded, location, BUNDLE_SYMBOLIC_NAME, bundleSymbolicNameHeader);
+    }
+
+    private String insertHeaderIfNeeded(AtomicBoolean dollarNeeded, String location, String headerName, String fullHeader) {

Review Comment:
   yes, done with a Map



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "f2par0 (via GitHub)" <gi...@apache.org>.
f2par0 commented on PR #591:
URL: https://github.com/apache/camel-karaf/pull/591#issuecomment-2624227362

   > It looks good to me. I just wonder for the "existing" features: can we re-run the plugin or is it coupled with an update ?
   
   The plugin is executed at build time, so it's coupled to an update of the feature repository


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "jbonofre (via GitHub)" <gi...@apache.org>.
jbonofre commented on PR #591:
URL: https://github.com/apache/camel-karaf/pull/591#issuecomment-2624072629

   It looks good to me. I just wonder for the "existing" features: can we re-run the plugin or is it coupled with an update ?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "essobedo (via GitHub)" <gi...@apache.org>.
essobedo commented on code in PR #591:
URL: https://github.com/apache/camel-karaf/pull/591#discussion_r1935100294


##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,144 @@
+/*
+ * 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";
+
+    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("$"));

Review Comment:
   ```suggestion
           boolean dollarNeeded = instructions == null || !instructions.contains("$");
   ```
   It is easier to read like this, don't you agree?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "f2par0 (via GitHub)" <gi...@apache.org>.
f2par0 commented on code in PR #591:
URL: https://github.com/apache/camel-karaf/pull/591#discussion_r1935198422


##########
tooling/camel-karaf-feature-maven-plugin/src/main/java/org/apache/camel/karaf/feature/maven/EnsureWrapBundleNameMojo.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * 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.concurrent.atomic.AtomicBoolean;
+
+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");
+    
+    static final String BUNDLE_NAME = "Bundle-Name";
+    static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+
+    static String toPascalCase(String kebabCase) {

Review Comment:
   I had changed the constants to private but not the method, it's fixed now



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] Ref #590 Add Bundle-Name and Bundle-SymbolicName to wrapped bundles [camel-karaf]

Posted by "essobedo (via GitHub)" <gi...@apache.org>.
essobedo merged PR #591:
URL: https://github.com/apache/camel-karaf/pull/591


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org