@Test
  public void testPluginWithServletRefreshedAfterOtherPluginUpgraded() throws Exception {
    final PluginJarBuilder firstBuilder = new PluginJarBuilder("first");
    firstBuilder
        .addPluginInformation("first", "Some name", "1.0")
        .addFormattedJava("first.MyInterface", "package first;", "public interface MyInterface {}")
        .addFormattedResource(
            "META-INF/MANIFEST.MF",
            "Manifest-Version: 1.0",
            "Bundle-SymbolicName: first",
            "Bundle-Version: 1.0",
            "Export-Package: first",
            "")
        .build(pluginsDir);

    new PluginJarBuilder("asecond", firstBuilder.getClassLoader())
        .addFormattedResource(
            "maera-plugin.xml",
            "<maera-plugin name='Test' key='asecond' pluginsVersion='2'>",
            "    <plugin-info>",
            "        <version>1.0</version>",
            "    </plugin-info>",
            "    <servlet key='foo' class='second.MyServlet'>",
            "       <url-pattern>/foo</url-pattern>",
            "    </servlet>",
            "</maera-plugin>")
        .addFormattedJava(
            "second.MyServlet",
            "package second;",
            "import org.maera.plugin.osgi.Callable2;",
            "public class MyServlet extends javax.servlet.http.HttpServlet implements first.MyInterface {",
            "   private Callable2 callable;",
            "   public MyServlet(Callable2 cal) { this.callable = cal; }",
            "   public String getServletInfo() {",
            "       try {return callable.call() + ' bob';} catch (Exception ex) { throw new RuntimeException(ex);}",
            "   }",
            "}")
        .build(pluginsDir);

    HostComponentProvider prov =
        new HostComponentProvider() {

          public void provide(ComponentRegistrar registrar) {
            registrar
                .register(Callable2.class)
                .forInstance(
                    new Callable2() {

                      public String call() {
                        return "hi";
                      }
                    });
          }
        };

    ServletContext ctx = mock(ServletContext.class);
    when(ctx.getInitParameterNames()).thenReturn(Collections.enumeration(Collections.emptyList()));
    ServletConfig servletConfig = mock(ServletConfig.class);
    when(servletConfig.getServletContext()).thenReturn(ctx);

    ServletModuleManager mgr = new DefaultServletModuleManager(pluginEventManager);
    hostContainer =
        createHostContainer(
            Collections.<Class<?>, Object>singletonMap(ServletModuleManager.class, mgr));
    initPluginManager(
        prov,
        new SingleModuleDescriptorFactory(hostContainer, "servlet", ServletModuleDescriptor.class));

    assertEquals(2, pluginManager.getEnabledPlugins().size());
    assertTrue(pluginManager.getPlugin("first").getPluginState() == PluginState.ENABLED);
    assertNotNull(pluginManager.getPlugin("asecond").getPluginState() == PluginState.ENABLED);
    assertEquals("hi bob", mgr.getServlet("/foo", servletConfig).getServletInfo());

    final File updatedJar =
        new PluginJarBuilder("first-updated")
            .addPluginInformation("foo", "Some name", "1.0")
            .addFormattedJava(
                "first.MyInterface", "package first;", "public interface MyInterface {}")
            .addFormattedResource(
                "META-INF/MANIFEST.MF",
                "Manifest-Version: 1.0",
                "Bundle-SymbolicName: foo",
                "Bundle-Version: 1.0",
                "Export-Package: first",
                "")
            .build();
    pluginManager.installPlugin(new JarPluginArtifact(updatedJar));

    WaitUntil.invoke(
        new BasicWaitCondition() {

          public boolean isFinished() {
            return pluginManager.isPluginEnabled("asecond");
          }
        });

    assertEquals("hi bob", mgr.getServlet("/foo", servletConfig).getServletInfo());
  }
  @Test
  public void testPluginDependentOnPackageImport() throws Exception {
    HostComponentProvider prov =
        new HostComponentProvider() {

          public void provide(final ComponentRegistrar registrar) {
            registrar.register(ServletConfig.class).forInstance(new HttpServlet() {});
          }
        };
    File servletJar =
        new PluginJarBuilder("first")
            .addFormattedResource(
                "META-INF/MANIFEST.MF",
                "Export-Package: javax.servlet.http;version='4.0.0',javax.servlet;version='4.0.0'",
                "Import-Package: javax.servlet.http;version='4.0.0',javax.servlet;version='4.0.0'",
                "Bundle-SymbolicName: first",
                "Bundle-Version: 4.0.0",
                "Manifest-Version: 1.0",
                "")
            .addFormattedJava(
                "javax.servlet.Servlet", "package javax.servlet;", "public interface Servlet {}")
            .addFormattedJava(
                "javax.servlet.http.HttpServlet",
                "package javax.servlet.http;",
                "public abstract class HttpServlet implements javax.servlet.Servlet{}")
            .build();

    File pluginJar =
        new PluginJarBuilder("asecond")
            .addFormattedResource(
                "maera-plugin.xml",
                "<maera-plugin name='Test' key='second' pluginsVersion='2'>",
                "    <plugin-info>",
                "        <version>1.0</version>",
                "        <bundle-instructions><Import-Package>javax.servlet.http;version='[2.3,2.3]',javax.servlet;version='[2.3,2.3]',*</Import-Package></bundle-instructions>",
                "    </plugin-info>",
                "</maera-plugin>")
            .addFormattedJava(
                "second.MyImpl",
                "package second;",
                "public class MyImpl {",
                "    public MyImpl(javax.servlet.ServletConfig config) {",
                "    }",
                "}")
            .build();

    initPluginManager(prov);
    pluginManager.installPlugin(new JarPluginArtifact(servletJar));
    pluginManager.installPlugin(new JarPluginArtifact(pluginJar));
    WaitUntil.invoke(
        new BasicWaitCondition() {

          public boolean isFinished() {
            return pluginManager.getEnabledPlugins().size() == 2;
          }
        });

    assertEquals(2, pluginManager.getEnabledPlugins().size());
    assertNotNull(pluginManager.getPlugin("first-4.0.0"));
    assertNotNull(pluginManager.getPlugin("second"));
  }