final void doFilter(Collection<DiscoveredPlugin> plugins, DiscoverOption[] options) {
    final OptionUtils<DiscoverOption> ou = new OptionUtils<DiscoverOption>(options);

    DiscoveredPlugin best = plugins.iterator().next();

    if (ou.contains(OptionNearest.class)) {
      // Check all plugins
      for (DiscoveredPlugin p : plugins) {
        // If this one is closer, replace them
        if (p.getDistance() < best.getDistance()) {
          best = p;
        }
      }

      // Remove all other plugins
      plugins.clear();
      plugins.add(best);
    }

    if (ou.contains(OptionYoungest.class)) {
      // Check all plugins
      for (DiscoveredPlugin p : plugins) {
        // If this one is closer, replace them
        if (p.getTimeSinceExport() < best.getTimeSinceExport()) {
          best = p;
        }
      }

      // Remove all other plugins
      plugins.clear();
      plugins.add(best);
    }

    if (ou.contains(OptionOldest.class)) {
      // Check all plugins
      for (DiscoveredPlugin p : plugins) {
        // If this one is closer, replace them
        if (p.getTimeSinceExport() > best.getTimeSinceExport()) {
          best = p;
        }
      }

      // Remove all other plugins
      plugins.clear();
      plugins.add(best);
    }
  }
  /**
   * @throws URISyntaxException
   * @throws InterruptedException
   */
  @Test
  public void testDiscovery() throws URISyntaxException, InterruptedException {
    TestAnnotations p2 = this.pm.getPlugin(TestAnnotations.class);
    RemoteDiscovery p = this.pm.getPlugin(RemoteDiscovery.class);

    System.out.println(1);
    p.announcePlugin(p2, PublishMethod.ERMI, new URI("ermi://lala:123/Jojo"));
    System.out.println(2);
    Collection<DiscoveredPlugin> discover = p.discover(Plugin.class);
    System.out.println(3);
    for (DiscoveredPlugin dp : discover) {
      int distance = dp.getDistance();
      System.out.println(dp.getPublishURI() + " " + distance);
    }
  }
  /**
   * Checks all known service infos for matches to the given class, returns all matching entries.
   *
   * @param plugin
   * @param options
   * @return
   */
  @SuppressWarnings("boxing")
  private Collection<DiscoveredPlugin> resolve(
      final Class<? extends Plugin> plugin, final DiscoverOption[] options) {

    // Refreshes all known remote discovery managers.
    refreshKnownDiscoveryManagers();

    // The result we intend to return
    final Collection<DiscoveredPlugin> result = new ArrayList<DiscoveredPlugin>();
    final Collection<RemoteManagerEndpoint> endpoints = this.remoteManagersEndpoints;

    // Query all managers
    for (final RemoteManagerEndpoint endpoint : endpoints) {

      // The manager to use ...
      final DiscoveryManager mgr =
          getRemoteProxyToDiscoveryManager(endpoint.address.getHostAddress(), endpoint.port);

      // No matter what happens, close the manager
      try {
        if (mgr == null) {
          this.logger.status(
              "resolve/vanished",
              "address",
              endpoint.address.getHostAddress(),
              "port",
              endpoint.port);
          continue;
        }

        //
        final AtomicInteger pingTime = new AtomicInteger(Integer.MAX_VALUE);

        // Get ping time
        AccessController.doPrivileged(
            new PrivilegedAction<Object>() {
              public Object run() {
                try {
                  final long start = System.nanoTime();

                  // Perform the ping
                  mgr.ping(new Random().nextInt());

                  // Obtain the time
                  final long stop = System.nanoTime();
                  final long time = (stop - start) / 1000;

                  // And set it
                  NetworkProbe.this.logger.status("resolve/ping", "time", time);
                  pingTime.set((int) time);
                } catch (final Exception e) {
                  NetworkProbe.this.logger.status(
                      "resolve/exception/ping", "message", e.getMessage());
                }
                return null;
              }
            });

        // Query the information (needs to be inside a privileged block, otherwise applets might
        // complain.
        final ExportInfo exportInfo =
            AccessController.doPrivileged(
                new PrivilegedAction<ExportInfo>() {
                  public ExportInfo run() {
                    return mgr.getExportInfoFor(plugin.getCanonicalName());
                  }
                });

        // If the plugin in not exported, do nothing
        if (!exportInfo.isExported) {
          continue;
        }

        // If it is, construct required data.
        for (final ExportedPlugin p : exportInfo.allExported) {
          final PublishMethod method = PublishMethod.valueOf(p.exportMethod);
          final URI uri = p.exportURI;

          String _newURI = "";

          _newURI += uri.getScheme();
          _newURI += "://";

          if (endpoint.address != null) {
            _newURI += endpoint.address.getHostAddress();
          } else {
            _newURI += "127.0.0.1";
          }
          _newURI += ":";
          _newURI += uri.getPort();
          _newURI += uri.getPath();

          try {
            // TODO: Compute distance properly.
            result.add(
                new DiscoveredPluginImpl(
                    method, new URI(_newURI), pingTime.get(), p.timeSinceExport));
          } catch (final URISyntaxException e) {
            e.printStackTrace();
          }
        }
      } catch (final Exception e) {
        this.logger.status(
            "resolve/exception/versionmess", "address", endpoint.address, "port", endpoint.port);
        e.printStackTrace();
      } finally {
        // In case the manager is of the type simple resource (which it should be), try to close it.
        if (mgr instanceof SimpleResource) {
          try {

            // Try to close our device again
            AccessController.doPrivileged(
                new PrivilegedAction<Object>() {
                  public Object run() {
                    ((SimpleResource) mgr).close();
                    return null;
                  }
                });

          } catch (final Exception e) {
            e.printStackTrace();
            this.logger.status(
                "resolve/exception/close", "address", endpoint.address, "port", endpoint.port);
          }
        }
      }
    }

    // If we have no result there is nothing to do
    if (result.size() == 0) return result;

    // Prepapare filter options ...
    final OptionUtils<DiscoverOption> ou = new OptionUtils<DiscoverOption>(options);

    DiscoveredPlugin best = result.iterator().next();

    if (ou.contains(OptionNearest.class)) {
      // Check all plugins
      for (final DiscoveredPlugin p : result) {
        // If this one is closer, replace them
        if (p.getDistance() < best.getDistance()) {
          best = p;
        }
      }

      // Remove all other plugins
      result.clear();
      result.add(best);
    }

    if (ou.contains(OptionYoungest.class)) {
      // Check all plugins
      for (final DiscoveredPlugin p : result) {
        // If this one is closer, replace them
        if (p.getTimeSinceExport() < best.getTimeSinceExport()) {
          best = p;
        }
      }

      // Remove all other plugins
      result.clear();
      result.add(best);
    }

    if (ou.contains(OptionOldest.class)) {
      // Check all plugins
      for (final DiscoveredPlugin p : result) {
        // If this one is closer, replace them
        if (p.getTimeSinceExport() > best.getTimeSinceExport()) {
          best = p;
        }
      }

      // Remove all other plugins
      result.clear();
      result.add(best);
    }

    // Debug plugins
    for (final DiscoveredPlugin p : result) {
      this.logger.status("resolve/return/", "plugin", p.getPublishURI());
    }

    return result;
  }