/**
   * Returns the remote proxy to a discovery manager for a given IP / port
   *
   * @param ip
   * @param port
   * @return
   */
  @SuppressWarnings("unchecked")
  DiscoveryManager getRemoteProxy(String ip, int port) {
    try {

      final String address = ip + ":" + port;
      final int timeout = 500; // 500 ms RemoteAPIImpl if need detailed
      // version...

      final DiscoveryManager newClient =
          Proxies.newClient(
              EXPORT_NAME,
              address,
              RemoteDiscoveryImpl.class.getClassLoader(),
              DiscoveryManager.class);

      /*
       * TODO: With this one we still get the message:
       *
       * "org.freshvanilla.net.VanillaDataSocket allocateBuffer
       * INFO: DiscoveryManager: Running low on memory, pausing..."
       *
       * but, there is no TimeoutException....
       *
       * @sa DiscoveredPluginTest.testMultiplePlugins()
       */
      @SuppressWarnings("unused")
      int pingRes = newClient.ping(123321);

      // Execute collection asynchronously (TODO: cache pool usage could be
      // improved)
      final ExecutorService cachePool = Executors.newCachedThreadPool();
      final ExecutorCompletionService<String> ecs = new ExecutorCompletionService(cachePool);
      final Future<String> future =
          ecs.submit(
              new Callable<String>() {

                public String call() throws Exception {
                  return AccessController.doPrivileged(
                      new PrivilegedAction<String>() {
                        public String run() {
                          return newClient.toString();
                        }
                      });
                }
              });

      // Wait at most half a second (TODO: Make this configurable)
      try {
        final String string = future.get(timeout, TimeUnit.MILLISECONDS);
        /*
         * TODO: Probably it is possible to put here some conversion routines... Because it looks like that
         * only the ExportInfo makes trouble.... Or just make the ExportInfo much better, ie downwards compatible
         */
        if (string == null || newClient.getVersion() != this.localManager.getVersion()) {
          return null;
        }

        return newClient;
      } catch (final InterruptedException e) {
        // TODO: This one is not an error anymore.
        // Interruption is called because we are running cache thread.
        //				System.err
        //						.println("Error while waiting for a getRemoteProxy() result");
        //				e.printStackTrace();
      } catch (final ExecutionException e) {
        e.printStackTrace();
      } catch (final TimeoutException e) {
        e.printStackTrace();
      } catch (final SecurityException e) {
        e.printStackTrace();
      } finally {
        AccessController.doPrivileged(
            new PrivilegedAction<Object>() {
              public Object run() {
                future.cancel(true);
                cachePool.shutdownNow();
                return null;
              }
            });
      }
      return null;
    } finally {
    }
  }
  @SuppressWarnings({"unchecked", "boxing", "rawtypes"})
  private DiscoveryManager getRemoteProxyToDiscoveryManager(final String ip, final int port) {

    final String address = ip + ":" + port;
    final int timeout = 500; // 500 ms RemoteAPIImpl if need detailed version...

    this.logger.status("remoteproxytodiscovery/start", "ip", ip, "port", port);

    final DiscoveryManager newClient =
        Proxies.newClient(
            EXPORT_NAME, address, getClass().getClassLoader(), DiscoveryManager.class);

    // Execute collection asynchronously (TODO: cache pool usage could be improved)
    final ExecutorService cachePool =
        Executors.newCachedThreadPool(RemoteDiscoveryImpl.threadFactory);
    final ExecutorCompletionService<String> ecs = new ExecutorCompletionService(cachePool);
    final Future<String> future =
        ecs.submit(
            new Callable<String>() {

              public String call() throws Exception {
                return AccessController.doPrivileged(
                    new PrivilegedAction<String>() {
                      public String run() {
                        return newClient.ping(667) == 667 ? "OK" : null;
                      }
                    });
              }
            });

    // Wait at most half a second (TODO: Make this configurable)
    try {
      final String string = future.get(timeout, TimeUnit.MILLISECONDS);
      if (string == null) return null;

      return newClient;
    } catch (final InterruptedException e) {
      this.logger.status("remoteproxytodiscovery/exception/interrupted", "message", e.getMessage());
      e.printStackTrace();
    } catch (final ExecutionException e) {
      this.logger.status(
          "remoteproxytodiscovery/exception/executionexception", "message", e.getMessage());
    } catch (final TimeoutException e) {
      this.logger.status(
          "remoteproxytodiscovery/exception/timeoutexception", "message", e.getMessage());
    } catch (final SecurityException e) {
      this.logger.status(
          "remoteproxytodiscovery/exception/securityexception", "message", e.getMessage());
      e.printStackTrace();
    } finally {
      AccessController.doPrivileged(
          new PrivilegedAction<Object>() {
            public Object run() {
              future.cancel(true);
              cachePool.shutdownNow();
              return null;
            }
          });

      this.logger.status("remoteproxytodiscovery/end");
    }

    this.logger.status("remoteproxytodiscovery/end");
    return null;
  }