public void dumpConfigChanges(IndentWriter writer) {
    ConfigurationDefaults defaults = ConfigurationDefaults.getInstance();

    Set<String> keys =
        new TreeSet<String>(
            new Comparator<String>() {
              public int compare(String o1, String o2) {
                return (o1.compareToIgnoreCase(o2));
              }
            });

    keys.addAll(propertiesMap.keySet());

    Iterator<String> it = keys.iterator();

    while (it.hasNext()) {

      String key = it.next();

      // don't dump crypto stuff

      if (ignoreKeyForDump(key)) {

        continue;
      }

      Object value = propertiesMap.get(key);

      boolean bParamExists = defaults.doesParameterDefaultExist(key.toString());

      if (bParamExists) {

        Object def = defaults.getParameter(key);

        if (def != null && value != null) {

          if (!BEncoder.objectsAreIdentical(def, value)) {

            if (value instanceof Long) {

              writer.println(key + "=" + value);

            } else if (value instanceof List) {

              writer.println(
                  key + "=" + BDecoder.decodeStrings((List) BEncoder.clone(value)) + "[list]");

            } else if (value instanceof Map) {

              writer.println(
                  key + "=" + BDecoder.decodeStrings((Map) BEncoder.clone(value)) + "[map]");

            } else if (value instanceof byte[]) {

              byte[] b = (byte[]) value;

              boolean hex = false;

              for (int i = 0; i < b.length; i++) {

                char c = (char) b[i];

                if (!(Character.isLetterOrDigit(c)
                    || "\\ `¬\"£$%^&*()-_=+[{]};:'@#~,<.>/?'".indexOf(c) != -1)) {

                  hex = true;

                  break;
                }
              }
              writer.println(
                  key + "=" + (hex ? ByteFormatter.nicePrint(b) : bytesToString((byte[]) value)));

            } else {

              writer.println(key + "=" + value + "[unknown]");
            }
          }
        }
      }
    }
  }
  public void generate(IndentWriter writer) {
    writer.println("Configuration Details");

    try {
      writer.indent();

      writer.println(
          "version=" + Constants.AZUREUS_VERSION + ", subver=" + Constants.AZUREUS_SUBVER);

      writer.println("System Properties");

      try {
        writer.indent();

        Properties props = System.getProperties();

        Iterator it = new TreeSet(props.keySet()).iterator();

        while (it.hasNext()) {

          String key = (String) it.next();

          writer.println(key + "=" + props.get(key));
        }
      } finally {

        writer.exdent();
      }

      writer.println("Environment");

      try {
        writer.indent();

        Map<String, String> env = System.getenv();

        if (env == null) {

          writer.println("Not supported");

        } else {

          Iterator it = new TreeSet(env.keySet()).iterator();

          while (it.hasNext()) {

            String key = (String) it.next();

            writer.println(key + "=" + env.get(key));
          }
        }
      } finally {

        writer.exdent();
      }

      writer.println("Azureus Config");

      ConfigurationDefaults defaults = ConfigurationDefaults.getInstance();

      try {
        writer.indent();

        Set<String> keys =
            new TreeSet<String>(
                new Comparator<String>() {
                  public int compare(String o1, String o2) {
                    return (o1.compareToIgnoreCase(o2));
                  }
                });

        keys.addAll(propertiesMap.keySet());

        Iterator<String> it = keys.iterator();

        while (it.hasNext()) {

          String key = it.next();

          // don't dump crypto stuff

          if (ignoreKeyForDump(key)) {

            continue;
          }

          Object value = propertiesMap.get(key);

          boolean bParamExists = defaults.doesParameterDefaultExist(key.toString());

          if (!bParamExists) {

            key = "[NoDef] " + key;
          } else {

            Object def = defaults.getParameter(key);

            if (def != null && value != null) {

              if (!BEncoder.objectsAreIdentical(def, value)) {

                key = "-> " + key;
              }
            }
          }

          if (value instanceof Long) {

            writer.println(key + "=" + value);

          } else if (value instanceof List) {

            writer.println(
                key + "=" + BDecoder.decodeStrings((List) BEncoder.clone(value)) + "[list]");

          } else if (value instanceof Map) {

            writer.println(
                key + "=" + BDecoder.decodeStrings((Map) BEncoder.clone(value)) + "[map]");

          } else if (value instanceof byte[]) {

            byte[] b = (byte[]) value;

            boolean hex = false;

            for (int i = 0; i < b.length; i++) {

              char c = (char) b[i];

              if (!(Character.isLetterOrDigit(c)
                  || "\\ `¬\"£$%^&*()-_=+[{]};:'@#~,<.>/?'".indexOf(c) != -1)) {

                hex = true;

                break;
              }
            }
            writer.println(
                key + "=" + (hex ? ByteFormatter.nicePrint(b) : bytesToString((byte[]) value)));

          } else {

            writer.println(key + "=" + value + "[unknown]");
          }
        }
      } finally {

        writer.exdent();
      }
    } finally {

      writer.exdent();
    }
  }