You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by "kwin (via GitHub)" <gi...@apache.org> on 2026/05/09 10:08:22 UTC

[PR] Register all transitive interfaces as services as well [sling-whiteboard]

kwin opened a new pull request, #120:
URL: https://github.com/apache/sling-whiteboard/pull/120

   (no comment)


-- 
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: dev-unsubscribe@sling.apache.org

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


Re: [PR] Register all transitive interfaces as services as well [sling-whiteboard]

Posted by "kwin (via GitHub)" <gi...@apache.org>.
kwin commented on code in PR #120:
URL: https://github.com/apache/sling-whiteboard/pull/120#discussion_r3212976306


##########
skills/osgi-scr-migrator/scripts/migrate_annotations.py:
##########
@@ -746,9 +749,121 @@ def _find_service_class_for_component(self, component_idx: int) -> Optional[str]
                 service_match = re.search(r'@Service\s*\(\s*(?:value\s*=\s*)?([^)]+)\)', line)
                 if service_match:
                     return service_match.group(1).strip()
-                # If no explicit class, return empty to signal service registration
-                return ""
+                # If @Service is present but no class specified, we will infer from interfaces
+                else:
+                    return self._get_transitive_interfaces_from_class(component_idx)
+        
+        # No @Service annotation found don't auto register as service
         return None
+    
+    def _get_transitive_interfaces_from_class(self, component_idx: int) -> Optional[str]:
+        """Extract all transitive interfaces from the class declaration.
+        
+        Looks for the class declaration after the @Component annotation and extracts
+        all interfaces it implements. Also resolves transitive interfaces (interfaces
+        that the declared interfaces extend).
+        
+        Returns:
+            - A single interface name if exactly one interface is found
+            - A list of interfaces formatted as "{ Interface1.class, Interface2.class, ... }"
+            - Empty string "" if interfaces are found but unable to resolve
+            - None if no class declaration or interfaces are found
+        """
+        # Find the class declaration after @Component
+        class_line = None
+        for i in range(component_idx + 1, min(component_idx + 10, len(self.lines))):
+            line = self.lines[i]
+            if re.search(r'(public|private|protected)?\s*(abstract\s+)?class\s+\w+', line):
+                class_line = i
+                break
+        
+        if class_line is None:
+            return None
+        
+        # Extract the class declaration line(s) - may span multiple lines
+        class_decl = self.lines[class_line]
+        paren_count = class_decl.count('(') - class_decl.count(')')
+        j = class_line + 1
+        
+        # Collect until we find opening brace or complete the declaration
+        while j < len(self.lines) and paren_count >= 0 and '{' not in class_decl:
+            class_decl += ' ' + self.lines[j].strip()
+            paren_count += self.lines[j].count('(') - self.lines[j].count(')')
+            j += 1
+        
+        # Extract interfaces from "implements Interface1, Interface2, ..."

Review Comment:
   Maybe instead of checking the source code one can instead evaluate the generated component descriptors generated by Felix SCR plugin.



-- 
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: dev-unsubscribe@sling.apache.org

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


Re: [PR] Register all transitive interfaces as services as well [sling-whiteboard]

Posted by "kwin (via GitHub)" <gi...@apache.org>.
kwin commented on code in PR #120:
URL: https://github.com/apache/sling-whiteboard/pull/120#discussion_r3281146003


##########
skills/osgi-scr-migrator/scripts/migrate_annotations.py:
##########
@@ -746,9 +749,121 @@ def _find_service_class_for_component(self, component_idx: int) -> Optional[str]
                 service_match = re.search(r'@Service\s*\(\s*(?:value\s*=\s*)?([^)]+)\)', line)
                 if service_match:
                     return service_match.group(1).strip()
-                # If no explicit class, return empty to signal service registration
-                return ""
+                # If @Service is present but no class specified, we will infer from interfaces
+                else:
+                    return self._get_transitive_interfaces_from_class(component_idx)
+        
+        # No @Service annotation found don't auto register as service
         return None
+    
+    def _get_transitive_interfaces_from_class(self, component_idx: int) -> Optional[str]:
+        """Extract all transitive interfaces from the class declaration.
+        
+        Looks for the class declaration after the @Component annotation and extracts
+        all interfaces it implements. Also resolves transitive interfaces (interfaces
+        that the declared interfaces extend).
+        
+        Returns:
+            - A single interface name if exactly one interface is found
+            - A list of interfaces formatted as "{ Interface1.class, Interface2.class, ... }"
+            - Empty string "" if interfaces are found but unable to resolve
+            - None if no class declaration or interfaces are found
+        """
+        # Find the class declaration after @Component
+        class_line = None
+        for i in range(component_idx + 1, min(component_idx + 10, len(self.lines))):
+            line = self.lines[i]
+            if re.search(r'(public|private|protected)?\s*(abstract\s+)?class\s+\w+', line):
+                class_line = i
+                break
+        
+        if class_line is None:
+            return None
+        
+        # Extract the class declaration line(s) - may span multiple lines
+        class_decl = self.lines[class_line]
+        paren_count = class_decl.count('(') - class_decl.count(')')
+        j = class_line + 1
+        
+        # Collect until we find opening brace or complete the declaration
+        while j < len(self.lines) and paren_count >= 0 and '{' not in class_decl:
+            class_decl += ' ' + self.lines[j].strip()
+            paren_count += self.lines[j].count('(') - self.lines[j].count(')')
+            j += 1
+        
+        # Extract interfaces from "implements Interface1, Interface2, ..."

Review Comment:
   https://github.com/jsedding/osgi-ds-metatype-diff/issues/19



-- 
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: dev-unsubscribe@sling.apache.org

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


Re: [PR] Register all transitive interfaces as services as well [sling-whiteboard]

Posted by "rombert (via GitHub)" <gi...@apache.org>.
rombert commented on code in PR #120:
URL: https://github.com/apache/sling-whiteboard/pull/120#discussion_r3281044857


##########
skills/osgi-scr-migrator/scripts/migrate_annotations.py:
##########
@@ -746,9 +749,121 @@ def _find_service_class_for_component(self, component_idx: int) -> Optional[str]
                 service_match = re.search(r'@Service\s*\(\s*(?:value\s*=\s*)?([^)]+)\)', line)
                 if service_match:
                     return service_match.group(1).strip()
-                # If no explicit class, return empty to signal service registration
-                return ""
+                # If @Service is present but no class specified, we will infer from interfaces
+                else:
+                    return self._get_transitive_interfaces_from_class(component_idx)
+        
+        # No @Service annotation found don't auto register as service
         return None
+    
+    def _get_transitive_interfaces_from_class(self, component_idx: int) -> Optional[str]:
+        """Extract all transitive interfaces from the class declaration.
+        
+        Looks for the class declaration after the @Component annotation and extracts
+        all interfaces it implements. Also resolves transitive interfaces (interfaces
+        that the declared interfaces extend).
+        
+        Returns:
+            - A single interface name if exactly one interface is found
+            - A list of interfaces formatted as "{ Interface1.class, Interface2.class, ... }"
+            - Empty string "" if interfaces are found but unable to resolve
+            - None if no class declaration or interfaces are found
+        """
+        # Find the class declaration after @Component
+        class_line = None
+        for i in range(component_idx + 1, min(component_idx + 10, len(self.lines))):
+            line = self.lines[i]
+            if re.search(r'(public|private|protected)?\s*(abstract\s+)?class\s+\w+', line):
+                class_line = i
+                break
+        
+        if class_line is None:
+            return None
+        
+        # Extract the class declaration line(s) - may span multiple lines
+        class_decl = self.lines[class_line]
+        paren_count = class_decl.count('(') - class_decl.count(')')
+        j = class_line + 1
+        
+        # Collect until we find opening brace or complete the declaration
+        while j < len(self.lines) and paren_count >= 0 and '{' not in class_decl:
+            class_decl += ' ' + self.lines[j].strip()
+            paren_count += self.lines[j].count('(') - self.lines[j].count(')')
+            j += 1
+        
+        # Extract interfaces from "implements Interface1, Interface2, ..."

Review Comment:
   I have some notes about comparing the new and old descriptors in https://github.com/apache/sling-whiteboard/blob/master/skills/update-sling-parent-pom/references/osgi-annotations.md#validation , they might be useful here.
   
   Maybe we can convince @jsedding to release that tool to Maven Central :-) 



-- 
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: dev-unsubscribe@sling.apache.org

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


Re: [PR] Register all transitive interfaces as services as well [sling-whiteboard]

Posted by "jsedding (via GitHub)" <gi...@apache.org>.
jsedding commented on code in PR #120:
URL: https://github.com/apache/sling-whiteboard/pull/120#discussion_r3286281538


##########
skills/osgi-scr-migrator/scripts/migrate_annotations.py:
##########
@@ -746,9 +749,121 @@ def _find_service_class_for_component(self, component_idx: int) -> Optional[str]
                 service_match = re.search(r'@Service\s*\(\s*(?:value\s*=\s*)?([^)]+)\)', line)
                 if service_match:
                     return service_match.group(1).strip()
-                # If no explicit class, return empty to signal service registration
-                return ""
+                # If @Service is present but no class specified, we will infer from interfaces
+                else:
+                    return self._get_transitive_interfaces_from_class(component_idx)
+        
+        # No @Service annotation found don't auto register as service
         return None
+    
+    def _get_transitive_interfaces_from_class(self, component_idx: int) -> Optional[str]:
+        """Extract all transitive interfaces from the class declaration.
+        
+        Looks for the class declaration after the @Component annotation and extracts
+        all interfaces it implements. Also resolves transitive interfaces (interfaces
+        that the declared interfaces extend).
+        
+        Returns:
+            - A single interface name if exactly one interface is found
+            - A list of interfaces formatted as "{ Interface1.class, Interface2.class, ... }"
+            - Empty string "" if interfaces are found but unable to resolve
+            - None if no class declaration or interfaces are found
+        """
+        # Find the class declaration after @Component
+        class_line = None
+        for i in range(component_idx + 1, min(component_idx + 10, len(self.lines))):
+            line = self.lines[i]
+            if re.search(r'(public|private|protected)?\s*(abstract\s+)?class\s+\w+', line):
+                class_line = i
+                break
+        
+        if class_line is None:
+            return None
+        
+        # Extract the class declaration line(s) - may span multiple lines
+        class_decl = self.lines[class_line]
+        paren_count = class_decl.count('(') - class_decl.count(')')
+        j = class_line + 1
+        
+        # Collect until we find opening brace or complete the declaration
+        while j < len(self.lines) and paren_count >= 0 and '{' not in class_decl:
+            class_decl += ' ' + self.lines[j].strip()
+            paren_count += self.lines[j].count('(') - self.lines[j].count(')')
+            j += 1
+        
+        # Extract interfaces from "implements Interface1, Interface2, ..."

Review Comment:
   @kwin I hear he is working on 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: dev-unsubscribe@sling.apache.org

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


Re: [PR] Register all transitive interfaces as services as well [sling-whiteboard]

Posted by "kwin (via GitHub)" <gi...@apache.org>.
kwin commented on code in PR #120:
URL: https://github.com/apache/sling-whiteboard/pull/120#discussion_r3212974513


##########
skills/osgi-scr-migrator/scripts/migrate_annotations.py:
##########
@@ -746,9 +749,121 @@ def _find_service_class_for_component(self, component_idx: int) -> Optional[str]
                 service_match = re.search(r'@Service\s*\(\s*(?:value\s*=\s*)?([^)]+)\)', line)
                 if service_match:
                     return service_match.group(1).strip()
-                # If no explicit class, return empty to signal service registration
-                return ""
+                # If @Service is present but no class specified, we will infer from interfaces
+                else:
+                    return self._get_transitive_interfaces_from_class(component_idx)
+        
+        # No @Service annotation found don't auto register as service
         return None
+    
+    def _get_transitive_interfaces_from_class(self, component_idx: int) -> Optional[str]:
+        """Extract all transitive interfaces from the class declaration.
+        
+        Looks for the class declaration after the @Component annotation and extracts
+        all interfaces it implements. Also resolves transitive interfaces (interfaces
+        that the declared interfaces extend).
+        
+        Returns:
+            - A single interface name if exactly one interface is found
+            - A list of interfaces formatted as "{ Interface1.class, Interface2.class, ... }"
+            - Empty string "" if interfaces are found but unable to resolve
+            - None if no class declaration or interfaces are found
+        """
+        # Find the class declaration after @Component
+        class_line = None
+        for i in range(component_idx + 1, min(component_idx + 10, len(self.lines))):
+            line = self.lines[i]
+            if re.search(r'(public|private|protected)?\s*(abstract\s+)?class\s+\w+', line):
+                class_line = i
+                break
+        
+        if class_line is None:
+            return None
+        
+        # Extract the class declaration line(s) - may span multiple lines
+        class_decl = self.lines[class_line]
+        paren_count = class_decl.count('(') - class_decl.count(')')
+        j = class_line + 1
+        
+        # Collect until we find opening brace or complete the declaration
+        while j < len(self.lines) and paren_count >= 0 and '{' not in class_decl:
+            class_decl += ' ' + self.lines[j].strip()
+            paren_count += self.lines[j].count('(') - self.lines[j].count(')')
+            j += 1
+        
+        # Extract interfaces from "implements Interface1, Interface2, ..."

Review Comment:
   Also needs a broader search for the base class/interface declaration (without necessarily evaluating the full Maven classpath....). Maybe some commons base classes can be added here like `SlingSafeMethodsServlet` or `javax.servlet.GenericServlet` with their implemented interfaces.



-- 
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: dev-unsubscribe@sling.apache.org

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


Re: [PR] Register all transitive interfaces as services as well [sling-whiteboard]

Posted by "cziegeler (via GitHub)" <gi...@apache.org>.
cziegeler commented on code in PR #120:
URL: https://github.com/apache/sling-whiteboard/pull/120#discussion_r3232964928


##########
skills/osgi-scr-migrator/scripts/migrate_annotations.py:
##########
@@ -746,9 +749,121 @@ def _find_service_class_for_component(self, component_idx: int) -> Optional[str]
                 service_match = re.search(r'@Service\s*\(\s*(?:value\s*=\s*)?([^)]+)\)', line)
                 if service_match:
                     return service_match.group(1).strip()
-                # If no explicit class, return empty to signal service registration
-                return ""
+                # If @Service is present but no class specified, we will infer from interfaces
+                else:
+                    return self._get_transitive_interfaces_from_class(component_idx)
+        
+        # No @Service annotation found don't auto register as service
         return None
+    
+    def _get_transitive_interfaces_from_class(self, component_idx: int) -> Optional[str]:
+        """Extract all transitive interfaces from the class declaration.
+        
+        Looks for the class declaration after the @Component annotation and extracts
+        all interfaces it implements. Also resolves transitive interfaces (interfaces
+        that the declared interfaces extend).
+        
+        Returns:
+            - A single interface name if exactly one interface is found
+            - A list of interfaces formatted as "{ Interface1.class, Interface2.class, ... }"
+            - Empty string "" if interfaces are found but unable to resolve
+            - None if no class declaration or interfaces are found
+        """
+        # Find the class declaration after @Component
+        class_line = None
+        for i in range(component_idx + 1, min(component_idx + 10, len(self.lines))):
+            line = self.lines[i]
+            if re.search(r'(public|private|protected)?\s*(abstract\s+)?class\s+\w+', line):
+                class_line = i
+                break
+        
+        if class_line is None:
+            return None
+        
+        # Extract the class declaration line(s) - may span multiple lines
+        class_decl = self.lines[class_line]
+        paren_count = class_decl.count('(') - class_decl.count(')')
+        j = class_line + 1
+        
+        # Collect until we find opening brace or complete the declaration
+        while j < len(self.lines) and paren_count >= 0 and '{' not in class_decl:
+            class_decl += ' ' + self.lines[j].strip()
+            paren_count += self.lines[j].count('(') - self.lines[j].count(')')
+            j += 1
+        
+        # Extract interfaces from "implements Interface1, Interface2, ..."

Review Comment:
   that's probably the better option, I guess this should be done anyway to compare old vs new



-- 
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: dev-unsubscribe@sling.apache.org

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


Re: [PR] Register all transitive interfaces as services as well [sling-whiteboard]

Posted by "kwin (via GitHub)" <gi...@apache.org>.
kwin commented on code in PR #120:
URL: https://github.com/apache/sling-whiteboard/pull/120#discussion_r3212969547


##########
skills/osgi-scr-migrator/scripts/migrate_annotations.py:
##########
@@ -746,9 +749,121 @@ def _find_service_class_for_component(self, component_idx: int) -> Optional[str]
                 service_match = re.search(r'@Service\s*\(\s*(?:value\s*=\s*)?([^)]+)\)', line)
                 if service_match:
                     return service_match.group(1).strip()
-                # If no explicit class, return empty to signal service registration
-                return ""
+                # If @Service is present but no class specified, we will infer from interfaces
+                else:
+                    return self._get_transitive_interfaces_from_class(component_idx)
+        
+        # No @Service annotation found don't auto register as service
         return None
+    
+    def _get_transitive_interfaces_from_class(self, component_idx: int) -> Optional[str]:
+        """Extract all transitive interfaces from the class declaration.
+        
+        Looks for the class declaration after the @Component annotation and extracts
+        all interfaces it implements. Also resolves transitive interfaces (interfaces
+        that the declared interfaces extend).
+        
+        Returns:
+            - A single interface name if exactly one interface is found
+            - A list of interfaces formatted as "{ Interface1.class, Interface2.class, ... }"
+            - Empty string "" if interfaces are found but unable to resolve
+            - None if no class declaration or interfaces are found
+        """
+        # Find the class declaration after @Component
+        class_line = None
+        for i in range(component_idx + 1, min(component_idx + 10, len(self.lines))):
+            line = self.lines[i]
+            if re.search(r'(public|private|protected)?\s*(abstract\s+)?class\s+\w+', line):
+                class_line = i
+                break
+        
+        if class_line is None:
+            return None
+        
+        # Extract the class declaration line(s) - may span multiple lines
+        class_decl = self.lines[class_line]
+        paren_count = class_decl.count('(') - class_decl.count(')')
+        j = class_line + 1
+        
+        # Collect until we find opening brace or complete the declaration
+        while j < len(self.lines) and paren_count >= 0 and '{' not in class_decl:
+            class_decl += ' ' + self.lines[j].strip()
+            paren_count += self.lines[j].count('(') - self.lines[j].count(')')
+            j += 1
+        
+        # Extract interfaces from "implements Interface1, Interface2, ..."

Review Comment:
   Also needs to consider interfaces implemented by base classes.



-- 
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: dev-unsubscribe@sling.apache.org

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


Re: [PR] Register all transitive interfaces as services as well [sling-whiteboard]

Posted by "kwin (via GitHub)" <gi...@apache.org>.
kwin commented on code in PR #120:
URL: https://github.com/apache/sling-whiteboard/pull/120#discussion_r3212974513


##########
skills/osgi-scr-migrator/scripts/migrate_annotations.py:
##########
@@ -746,9 +749,121 @@ def _find_service_class_for_component(self, component_idx: int) -> Optional[str]
                 service_match = re.search(r'@Service\s*\(\s*(?:value\s*=\s*)?([^)]+)\)', line)
                 if service_match:
                     return service_match.group(1).strip()
-                # If no explicit class, return empty to signal service registration
-                return ""
+                # If @Service is present but no class specified, we will infer from interfaces
+                else:
+                    return self._get_transitive_interfaces_from_class(component_idx)
+        
+        # No @Service annotation found don't auto register as service
         return None
+    
+    def _get_transitive_interfaces_from_class(self, component_idx: int) -> Optional[str]:
+        """Extract all transitive interfaces from the class declaration.
+        
+        Looks for the class declaration after the @Component annotation and extracts
+        all interfaces it implements. Also resolves transitive interfaces (interfaces
+        that the declared interfaces extend).
+        
+        Returns:
+            - A single interface name if exactly one interface is found
+            - A list of interfaces formatted as "{ Interface1.class, Interface2.class, ... }"
+            - Empty string "" if interfaces are found but unable to resolve
+            - None if no class declaration or interfaces are found
+        """
+        # Find the class declaration after @Component
+        class_line = None
+        for i in range(component_idx + 1, min(component_idx + 10, len(self.lines))):
+            line = self.lines[i]
+            if re.search(r'(public|private|protected)?\s*(abstract\s+)?class\s+\w+', line):
+                class_line = i
+                break
+        
+        if class_line is None:
+            return None
+        
+        # Extract the class declaration line(s) - may span multiple lines
+        class_decl = self.lines[class_line]
+        paren_count = class_decl.count('(') - class_decl.count(')')
+        j = class_line + 1
+        
+        # Collect until we find opening brace or complete the declaration
+        while j < len(self.lines) and paren_count >= 0 and '{' not in class_decl:
+            class_decl += ' ' + self.lines[j].strip()
+            paren_count += self.lines[j].count('(') - self.lines[j].count(')')
+            j += 1
+        
+        # Extract interfaces from "implements Interface1, Interface2, ..."

Review Comment:
   Also needs a broader search for the base class/interface declaration (without necessarily evaluating the full Maven classpath....). Maybe some commons base classes can be added here like `SlingSafeMethodsServlet`, `SlingAllMethodsServlet` or `javax.servlet.GenericServlet` with their implemented interfaces.



-- 
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: dev-unsubscribe@sling.apache.org

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