1

各位码农,

我目前正在尝试找到一种简单明了的方法来获取使用给定接口的服务/组件的列表。我正在使用正在运行的 Liferay 7.1.x 服务器的 gogo-shell,但似乎找不到一种简单直接的方法来解决这个问题。

我们想通过 OSGI-configuration覆盖对使用服务的引用,但首先需要找到所有使用它的组件。由于存在对服务组件的静态不情愿引用,因此简单地提供具有更高排名的替代方案不是可行的解决方案。

以下是我正在使用的 gogo 相关捆绑包:

   35|Active     |    6|Apache Felix Gogo Command (1.0.2)|1.0.2
   36|Active     |    6|Apache Felix Gogo Runtime (1.1.0.LIFERAY-PATCHED-2)|1.1.0.LIFERAY-PATCHED-2
   72|Active     |    6|Apache Felix Gogo Shell (1.1.0)|1.1.0
  542|Active     |   10|Liferay Foundation - Liferay Gogo Shell - Impl (1.0.13)|1.0.13
  543|Active     |   10|Liferay Gogo Shell Web (2.0.25)|2.0.25

到目前为止,我已经能够通过以下方式列出接口的所有提供者se (interface=com.liferay.saml.runtime.servlet.profile.WebSsoProfile)

{com.liferay.saml.runtime.profile.WebSsoProfile, com.liferay.saml.runtime.servlet.profile.WebSsoProfile}={service.id=6293, service.bundleid=79, service.scope=bundle, component.name=com.liferay.saml.opensaml.integration.internal.servlet.profile.WebSsoProfileImpl, component.id=3963}
  "Registered by bundle:" de.haufe.leong.com.liferay.saml.opensaml.integration [79]
  "Bundles using service"
    com.liferay.saml.web_2.0.11 [82]
    com.liferay.saml.impl_2.0.12 [78]

通过以下方式查看所有捆绑包要求inspect cap service

com.liferay.saml.impl_2.0.12 [78] requires:
...
service; com.liferay.saml.runtime.profile.WebSsoProfile, com.liferay.saml.runtime.servlet.profile.WebSsoProfile provided by:
   de.haufe.leong.com.liferay.saml.opensaml.integration [79]
...

但是到目前为止,从这些使用给定接口(或服务组件)的捆绑包中列出实际服务让我望而却步。

到目前为止,我看到的唯一解决方案是列出这些捆绑包的所有提供的服务,scr:list bid然后检查每个服务scr:info componentId是否使用 WebSsoProfile 服务。

你们知道使用 WebSsoProfile-service 找到服务的更快方法吗?


[编辑]:我们解决了这个问题,而不必为 WebSsoProfile 服务的所有使用者提供配置覆盖,而是通过在服务器启动时停用默认服务来确保使用我们的实现。您可以看到这里描述的方法

无论如何,出于调试目的,这种查找将非常有用。因此,如果有人知道检索接口所有使用者列表的方法,请发布您的解决方案!

4

1 回答 1

2

标准解决方案是使用inspect命令。它有一个特殊的服务命名空间。由于服务注册是一种能力,您可以使用inspect capability service

g! inspect c service
org.apache.felix.framework [0] provides:
----------------------------------------
service; org.osgi.service.resolver.Resolver with properties:
   service.bundleid = 0
   service.id = 1
   service.scope = singleton
service; org.osgi.service.packageadmin.PackageAdmin with properties:
   service.bundleid = 0
   service.id = 2
   service.scope = singleton
service; org.osgi.service.startlevel.StartLevel with properties:
   service.bundleid = 0
   service.id = 3
   service.scope = singleton

....

但是,我发现这个命令非常无用。该命令不灵活,输出很糟糕。

然而,Gogo 比人们所知道的要强大得多。一方面,您可以使用捆绑上下文中的所有方法。

g! servicereferences org.osgi.service.startlevel.StartLevel null
000003   0 StartLevel

如果要查看每个服务的属性:

g! each (servicereferences org.osgi.service.startlevel.StartLevel null) { $it properties }
[service.id=3, objectClass=[Ljava.lang.String;@4acd14d7, service.scope=singleton, service.bundleid=0]

你可以把它变成一个内置函数:

g! srv = { servicereferences $1 null }
servicereferences $1 null
g! srv org.osgi.service.startlevel.StartLevel
000003   0 StartLevel                               

不幸的是,OSGi 在 Bundle Context 中添加了一个重载方法,用于getServiceReferences()在使用 null 调用时抛出 NPE。Gogo 的重载方法很糟糕 :-(

但是,使用声明性服务组件添加您自己的命令是微不足道的。您可以使用以下内容:

@GogoCommand(scope="service", function="srv")
@Component(service=ServiceCommand.class)
public class ServiceCommand {

    @Activate
    BundleContext context;        

    @Descriptor("List all services")
    public ServiceReference<?>[] srv() throws InvalidSyntaxException {
        return context.getAllServiceReferences(null, null);
    }

    @Descriptor("List all services that match the name")
    public ServiceReference<?>[] srv(
            String... names)
            throws InvalidSyntaxException {
        ServiceReference<?>[] allServiceReferences = 
            context.getAllServiceReferences(null,null);
        if ( allServiceReferences==null)
            return new ServiceReference[0];
        return Stream.of(allServiceReferences)
                .filter(r -> {
                    String[] objectClass = (String[]) r.getProperty(Constants.OBJECTCLASS);
                    for (String oc : objectClass) {
                        for (String name : names)
                            if (oc.contains(name))
                                return true;
                    }
                    return names.length == 0;
                }).sorted().toArray(ServiceReference[]::new);
    }
}

这会将srv命令添加到 Gogo:

g! srv Help Basic
000004   1 Basic                                    
000005   1 Inspect   

更新如果您想查找哪些捆绑包正在使用特定服务,您可以使用:

g! each (srv X) { $it usingbundles }

确保您的类路径具有以下依赖项:

-buildpath: \
    org.osgi.service.component.annotations,\
    org.apache.felix.gogo.runtime, \
    org.osgi.framework
于 2020-02-13T13:28:24.833 回答