1

根据http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2Fua_help_war.htm我设置了一个运行多个 eclipse-help- 的专用 Tomcat 服务器插件。

服务器和帮助都启动并运行良好。但现在我意识到停止服务器尤其是 OSGi 框架似乎是一个问题。如果部署了帮助战,我总是必须终止服务器进程,并且我相信我必须优雅地关闭 OSGi 框架。

经过一番调查,我想出了以下 ServletContextListener 的实现,它通过调用 bundleContext.getBundle(0).stop() 来停止系统捆绑:

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;

public class OsgiShutdownListener implements ServletContextListener {

    /** {@inheritDoc} */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        Bundle bundle = FrameworkUtil.getBundle(org.eclipse.core.runtime.adaptor.EclipseStarter.class);
        BundleContext bundleContext = bundle.getBundleContext();
        try {
            bundleContext.getBundle(0).stop();
        } catch (BundleException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /** {@inheritDoc} */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("starting");

    }
}

但是 FrameworkUtil.getBundle(org.eclipse.core.runtime.adaptor.EclipseStarter.class) 总是返回 null,所以我从来没有得到对 BundleContext 的引用来停止框架。

编辑: 我在 contextDestroyed() 和 contextInitialized() 中也将代码更改为 sce.getServletContext().getAttribute("osgi-bundlecontext") ,但在这两种情况下我都没有引用包上下文。捆绑上下文始终为空。

public class OsgiShutdownListener implements ServletContextListener {

    private BundleContext bundleContext;

    /** {@inheritDoc} */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // Bundle bundle =
        // FrameworkUtil.getBundle(org.eclipse.core.runtime.adaptor.EclipseStarter.class);
        // this.bundleContext = bundle.getBundleContext();

        ServletContext context = sce.getServletContext();
        this.bundleContext = (BundleContext) context
                .getAttribute("osgi-bundlecontext");
        try {
            this.bundleContext.getBundle(0).stop();
        } catch (BundleException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /** {@inheritDoc} */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext context = sce.getServletContext();
        this.bundleContext = (BundleContext) context
                .getAttribute("osgi-bundlecontext");
    }
}

在这种情况下如何获取 bundleContext 来停止系统捆绑?或者当服务器关闭时如何优雅地停止 OSGi 框架?

4

2 回答 2

1

EclipseStarter是启动器应用程序的一部分,因此它是“外部”OSGi,因此它不会被捆绑类加载器加载......因此(终于!)它从 FrameworkUtil.getBundle() 返回 null。

您需要掌握系统捆绑上下文......在过去的某个时候,您一定有过这种情况,因为您成功地启动了 OSGi。那么为什么不在一个字段中记住它,或者以其他方式安排它在停止时仍然可见呢?

于 2013-06-27T15:23:22.280 回答
0

查看帮助战,您应该能够修改 web.xml 以覆盖桥 servlet。

http://grepcode.com/file/repository.grepcode.com/java/eclipse.org/3.5/org.eclipse.help/webapp/3.4.0/web-archive/help/WEB-INF/web.xml? av=f

http://eclipsesrc.appspot.com/jsrcs/org.eclipse.equinox.servletbridge/src/org/eclipse/equinox/servletbridge/BridgeServlet.java.html

由于 BridgeServlet 最终负责通过 FrameworkLauncher 启动和停止 OSGI 运行时,因此您应该能够覆盖 BridgeServlet 并获取 FrameworkLauncher 实例。FrameworkLauncher 不提供标准的“框架”,而是将其包装在它自己的类加载器和反射魔法周围。

也就是说:BridgeServlet 已经负责关闭 OSGI 框架。除非它被窃听,否则在调用 tomcat 关闭时,事情可能会自行停止。

BridgeServlet 没有设置 osgi-context,我相信这可能只是一个“白板”的东西,整个 servlet 都包含在一个 OSGI 容器中,而不是像这里那样反过来。

于 2013-06-28T14:40:45.220 回答