protected boolean configureURL(ApacheBinaryInfo binary, ConfigResponse config) {
    String port = null, address = null;
    if (binary.conf != null) {
      // XXX config parsing not complete
      Map cfg = ApacheBinaryInfo.parseConfig(binary.conf);
      String listen = (String) cfg.get("Listen");
      if (listen != null) {
        int ix = listen.lastIndexOf(':');
        if (ix == -1) {
          port = listen;
          address = (String) cfg.get("ServerName");
          if (address != null) {
            ix = address.indexOf(':');
            if (ix != -1) {
              address = address.substring(0, ix);
            }
          }
        } else {
          address = listen.substring(0, ix);
          port = listen.substring(ix + 1);
        }
      }
      setConfigTrack(config, binary.conf);
      String root = (String) cfg.get("ServerRoot");
      if (root != null) {
        binary.root = root;
      }
      String log = (String) cfg.get("ErrorLog");
      if (binary.serverRootRelative(log).exists()) {
        setLogTrack(config, log);
      }
      String pid = (String) cfg.get("PidFile");
      if (pid != null) {
        File pidFile = binary.serverRootRelative(pid);
        if (pidFile.exists()) {
          setPidFile(config, pidFile.getPath());
        }
      }
    }
    if (port == null) {
      port = getConfigProperty(Collector.PROP_PORT, "80");
    }
    if (address == null) {
      address = getListenAddress(port, this.defaultIp);
    }

    config.setValue(Collector.PROP_PROTOCOL, getConnectionProtocol(port));
    config.setValue(Collector.PROP_SSL, isSSL(port));
    config.setValue(Collector.PROP_HOSTNAME, address);
    config.setValue(Collector.PROP_PORT, port);
    config.setValue(Collector.PROP_PATH, getConfigProperty(Collector.PROP_PATH, "/server-status"));
    return true;
  }
  private void findServerProcess(List servers, String query, String version) {
    long[] pids = getPids(query);

    for (int i = 0; i < pids.length; i++) {
      String httpd;
      if ((httpd = getProcExe(pids[i])) == null) {
        httpd = getConfigProperty("exe");
      }

      if (httpd == null) {
        continue;
      }

      String[] args = getProcArgs(pids[i]);
      if (!new File(httpd).isAbsolute()) {
        String exe = findAbsoluteExe(httpd, args);
        if (exe == null) {
          log.warn(
              "Unable to get absolute path for pid="
                  + pids[i]
                  + ", args="
                  + java.util.Arrays.asList(args));
          if (!new File(httpd).exists()) {
            continue;
          } // else fallthru.. unlikely, but permit an ln -s workaround
        } else {
          httpd = exe;
        }
      }

      ApacheBinaryInfo info = ApacheBinaryInfo.getInfo(httpd, version);

      if (info == null) {
        continue;
      }

      info.pid = pids[i];
      getServerInfo(info, args);

      if (info.root == null) {
        continue;
      }

      servers.add(info);
    }
  }
  private void getServerInfo(ApacheBinaryInfo info, String[] args) {
    final String nameProp = "-Dhq.name=";
    String root = null;
    for (int i = 1; i < args.length; i++) {
      String arg = args[i];
      if (arg.startsWith("-d")) {
        root = arg.substring(2, arg.length());
        if (root.length() == 0) {
          root = args[i + 1];
        }
      } else if (arg.startsWith("-f")) {
        info.conf = arg.substring(2, arg.length());
        if (info.conf.length() == 0) {
          info.conf = args[i + 1];
        }
      } else if (arg.startsWith(nameProp)) {
        info.name = arg.substring(nameProp.length(), arg.length());
      }
    }

    if (root != null) {
      // -d overrides compiled in HTTPD_ROOT
      info.root = root;
    }

    if (info.conf != null) {
      // check that httpd.conf exists and is absolute
      File conf = new File(info.conf);
      if (!conf.isAbsolute() && (info.root != null)) {
        conf = new File(info.root, info.conf);
      }
      if (!conf.exists()) {
        info.conf = null; // use the defaults
      }
    } else {
      for (String conf : defaultConfs) {
        File cf = new File(info.root, conf);
        if (cf.exists() && cf.isFile()) {
          info.conf = cf.getAbsolutePath();
        }
      }
    }
    log.debug(
        "[getServerInfo] info.conf="
            + info.conf
            + ", info.root="
            + info.root
            + ", info.name="
            + info.name);
  }
  /**
   * The List returned from this method will either be null (if no servers were found), or it will
   * contain a single AIServerValue (if a server was found). Currently the DotOrgDetector does not
   * support detecting multiple instances of Apache in a single directory.
   */
  public List getServerResources(ConfigResponse platformConfig, String path)
      throws PluginException {
    String version = getTypeInfo().getVersion();
    ApacheBinaryInfo binary = ApacheBinaryInfo.getInfo(path, version);
    if (binary == null) {
      return null; // does not match our server type version
    }

    String fullVersion = binary.version;

    if (fullVersion == null) {
      log.debug("Apache version " + version + " not found in binary: " + path);
      return null;
    }

    // strip "bin/httpd"
    String installpath = getParentDir(path, 2);

    return getServerList(installpath, fullVersion, binary);
  }
  protected boolean configureServer(ServerResource server, ApacheBinaryInfo binary)
      throws PluginException {

    ConfigResponse metricConfig, productConfig, controlConfig;
    String installpath = server.getInstallPath();
    File snmpConfig = getSnmpdConf(installpath);
    boolean snmpConfigExists = snmpConfig.exists();

    controlConfig = getControlConfig(installpath);

    if (binary != null) {
      ConfigResponse cprops = new ConfigResponse(binary.toProperties());
      server.setCustomProperties(cprops);
    }

    getLog()
        .debug(
            "[configureServer] snmpConfigExists="
                + snmpConfigExists
                + " this.discoverModSnmp="
                + this.discoverModSnmp
                + " this.discoverModStatus="
                + this.discoverModStatus);

    if (snmpConfigExists || this.discoverModSnmp) {
      if (!snmpConfigExists) {
        log.debug(snmpConfig + " does not exist, cannot auto-configure " + server.getName());
      }
      metricConfig = getSnmpConfig(snmpConfig);

      productConfig = getProductConfig(metricConfig);
      populateListeningPorts(binary.pid, productConfig, true);

      if (binary.conf == null) {
        String cfgPath = installpath;
        if (snmpConfigExists) {
          cfgPath = snmpConfig.getParentFile().getParent();
        }
        for (String conf : defaultConfs) {
          File cf = new File(cfgPath, conf);
          getLog().debug("[configureServer] cf=" + cf + " (" + (cf.exists() && cf.isFile()) + ")");
          if (cf.exists() && cf.isFile()) {
            binary.conf = cf.getAbsolutePath();
          }
        }
      }

      if (productConfig != null) {
        if (binary.conf != null) {
          productConfig.setValue("ServerConf", binary.conf);
        }
        addTrackConfig(productConfig);
        setProductConfig(server, productConfig);
        setMeasurementConfig(server, metricConfig);
        if (controlConfig != null) {
          setControlConfig(server, controlConfig);
        }

        server.setConnectProperties(
            new String[] {
              SNMPClient.PROP_PORT,
              SNMPClient.PROP_VERSION, // only need to avoid udp port conflicts
            });
      }

      server.setDescription("mod_snmp monitor");

      return true;
    } else if (this.discoverModStatus) {
      log.debug(snmpConfig + " does not exist, discovering as type: " + TYPE_HTTPD);

      productConfig = new ConfigResponse();
      populateListeningPorts(binary.pid, productConfig, true);

      // meant for command-line testing: -Dhttpd.url=http://localhost:8080/
      if (configureURL(getManagerProperty("httpd.url"), productConfig)) {
        server.setMeasurementConfig();
      } else if (configureURL(binary, productConfig)) {
        server.setMeasurementConfig();
        if (binary.conf != null) {
          // ServerRoot location overrides compiled in HTTPD_ROOT
          ConfigResponse srControlConfig = getControlConfig(binary.root);
          if (srControlConfig != null) {
            controlConfig = srControlConfig;
          }
        }
      }
      addTrackConfig(productConfig);
      if (controlConfig != null) {
        String pidfile = productConfig.getValue(ApacheControlPlugin.PROP_PIDFILE);
        if (pidfile != null) {
          setPidFile(controlConfig, pidfile); // propagate from httpd.conf
        }
        setControlConfig(server, controlConfig);
      }
      server.setDescription("mod_status monitor");
      server.setType(TYPE_HTTPD);
      String path = binary.conf;
      if (path == null) {
        path = server.getInstallPath();
      } else {
        // use -f file for path and AIID
        // since binary installpath will be the same
        // for multiple instances
        server.setInstallPath(path);
      }
      // in the event that mod_snmp is added later,
      // we won't clash w/ the other types
      server.setIdentifier(TYPE_HTTPD + " " + path);
      server.setProductConfig(productConfig);

      return true;
    } else {
      log.debug("Ignoring " + server.getName() + " at " + server.getInstallPath());
      return false;
    }
  }