public void load(String filename) {
    Map data = FileUtil.readResilientConfigFile(filename, false);

    // horrendous recursive loading going on here due to logger + config depedencies. If already
    // loaded
    // then use the existing data as it might have already been written to...

    if (propertiesMap == null) {

      ConcurrentHashMapWrapper<String, Object> c_map =
          new ConcurrentHashMapWrapper<String, Object>(data.size() + 256, 0.75f, 8);

      c_map.putAll(data);

      propertiesMap = c_map;
    }

    /*
     * Can't do this yet.  Sometimes, there's a default set to x, but the code
     * calls get..Parameter(..., y).  y != x.  When the user sets the the parameter
     * to x, we remove it from the list.  Later, the get..Parameter(.., y) returns
     * y because there is no entry.
     *
     * The solution is to not allow get..Parameter(.., y) when there's a default
     * value.  Another reason to not allow it is that having two defaults confuses
     * coders.
     *
      	// Remove entries that are default.  Saves memory, reduces
      	// file size when saved again
        ConfigurationDefaults def = ConfigurationDefaults.getInstance();
      	Iterator it = new TreeSet(propertiesMap.keySet()).iterator();

    		while (it.hasNext()) {
    			String key = (String)it.next();
    			Object defValue = def.getDefaultValueAsObject(key);
    			if (defValue == null)
    				continue;

    			if (defValue instanceof Long) {
    				int iDefValue = ((Long)defValue).intValue();
    				int iValue = getIntParameter(key, iDefValue);
    				if (iValue == iDefValue)
    					propertiesMap.remove(key);
    			}
    			if (defValue instanceof String) {
    				String sDefValue = defValue.toString();
    				String sValue = getStringParameter(key, sDefValue);
    				if (sValue.compareTo(sDefValue) == 0)
    					propertiesMap.remove(key);
    			}
    		}
    */
  }
  public void resetToDefaults() {
    ConfigurationDefaults def = ConfigurationDefaults.getInstance();

    List<String> def_names = new ArrayList<String>((Set<String>) def.getAllowedParameters());

    for (String s : def_names) {

      if (propertiesMap.remove(s) != null) {

        notifyParameterListeners(s);
      }
    }

    List<ResetToDefaultsListener> listeners;

    synchronized (reset_to_def_listeners) {
      listeners = new ArrayList<ResetToDefaultsListener>(reset_to_def_listeners);
    }

    for (ResetToDefaultsListener l : listeners) {

      try {
        l.reset();

      } catch (Throwable e) {

        Debug.out(e);
      }
    }

    save();
  }
 private Long getLongParameterRaw(String parameter) {
   try {
     return (Long) propertiesMap.get(parameter);
   } catch (Exception e) {
     Debug.out("Parameter '" + parameter + "' has incorrect type", e);
     return null;
   }
 }
 public List getListParameter(String parameter, List def) {
   try {
     List rawList = (List) propertiesMap.get(parameter);
     if (rawList == null) return def;
     return rawList;
   } catch (Exception e) {
     Debug.out("Parameter '" + parameter + "' has incorrect type", e);
     return def;
   }
 }
 public Map getMapParameter(String parameter, Map def) {
   try {
     Map map = (Map) propertiesMap.get(parameter);
     if (map == null) return def;
     return map;
   } catch (Exception e) {
     Debug.out("Parameter '" + parameter + "' has incorrect type", e);
     return def;
   }
 }
  public Object getParameter(String name) {
    Object value = propertiesMap.get(name);

    if (value == null) {

      value = ConfigurationDefaults.getInstance().getParameter(name);
    }

    return (value);
  }
 public boolean setParameter(String parameter, Map value) {
   try {
     propertiesMap.put(parameter, value);
     notifyParameterListeners(parameter);
   } catch (Exception e) {
     Debug.printStackTrace(e);
     return false;
   }
   return true;
 }
 public StringList getStringListParameter(String parameter) {
   try {
     List rawList = (List) propertiesMap.get(parameter);
     if (rawList == null) return new StringListImpl();
     return new StringListImpl(rawList);
   } catch (Exception e) {
     Debug.out("Parameter '" + parameter + "' has incorrect type", e);
     return new StringListImpl();
   }
 }
 public boolean setParameter(String parameter, byte[] defaultValue) {
   try {
     byte[] oldValue = (byte[]) propertiesMap.put(parameter, defaultValue);
     return notifyParameterListenersIfChanged(parameter, defaultValue, oldValue);
   } catch (ClassCastException e) {
     // Issuing a warning here would be nice, but both logging and config stuff
     // at startup create potential deadlocks or stack overflows
     notifyParameterListeners(parameter);
     return true;
   }
 }
  public void save(String filename) {
    if (propertiesMap == null) {

      // nothing to save, initialisation not complete

      return;
    }

    /**
     * Note - propertiesMap isn't synchronised! We'll clone the map now, because we need to modify
     * it. The BEncoding code will create a new map object (TreeMap) because it needs to be sorted,
     * so we might as well do it here too.
     */
    TreeMap<String, Object> properties_clone = propertiesMap.toTreeMap();

    // Remove any transient parameters.
    if (!this.transient_properties.isEmpty()) {
      properties_clone.keySet().removeAll(this.transient_properties);
    }

    FileUtil.writeResilientConfigFile(filename, properties_clone);

    List<COConfigurationListener> listeners_copy;

    synchronized (listenerz) {
      listeners_copy = new ArrayList<COConfigurationListener>(listenerz);
    }

    for (int i = 0; i < listeners_copy.size(); i++) {

      COConfigurationListener l = (COConfigurationListener) listeners_copy.get(i);

      if (l != null) {

        try {
          l.configurationSaved();

        } catch (Throwable e) {

          Debug.printStackTrace(e);
        }
      } else {

        Debug.out("COConfigurationListener is null");
      }
    }

    if (exported_parameters_dirty) {

      exportParameters();
    }
  }
  /**
   * Returns true if a parameter with the given name exists.
   *
   * @param key The name of the parameter to check.
   * @param explicit If <tt>true</tt>, we only check for a value which is definitely stored
   *     explicitly, <tt>false</tt> means that we'll also check against configuration defaults too.
   */
  public boolean hasParameter(String key, boolean explicit) {

    // We have an explicit value set.
    if (propertiesMap.containsKey(key)) {
      return true;
    }

    // We have a default value set.
    if ((!explicit) && ConfigurationDefaults.getInstance().hasParameter(key)) {
      return true;
    }

    return false;
  }
  public boolean setParameter(String parameter, StringList value) {
    try {
      List encoded = new ArrayList();

      List l = ((StringListImpl) value).getList();

      for (int i = 0; i < l.size(); i++) {

        encoded.add(stringToBytes((String) l.get(i)));
      }
      propertiesMap.put(parameter, encoded);
      notifyParameterListeners(parameter);
    } catch (Exception e) {
      Debug.printStackTrace(e);
      return false;
    }
    return true;
  }
  public void load() {
    load("azureus.config");

    try {
      String[] keys = propertiesMap.keySet().toArray(new String[0]);
      for (String key : keys) {
        if (key == null) {
          continue;
        }
        if (key.startsWith("SideBar.Expanded.Category.")
            || key.startsWith("NameColumn.wrapText.")) {
          removeParameter(key);
        }
      }
    } catch (Exception e) {
      // not sure if I can do Debug.out here.. could be in that evil
      // preinitialization loop of dooom
      e.printStackTrace();
    }
  }
  public float getFloatParameter(String parameter, float def_val) {
    ConfigurationDefaults def = ConfigurationDefaults.getInstance();
    try {
      Object o = propertiesMap.get(parameter);
      if (o instanceof Number) {
        return ((Number) o).floatValue();
      }

      String s = getStringParameter(parameter);

      if (!s.equals(ConfigurationDefaults.def_String)) return Float.parseFloat(s);
    } catch (Exception e) {
      Debug.out("Parameter '" + parameter + "' has incorrect type", e);
    }

    try {
      return def.getFloatParameter(parameter);
    } catch (Exception e2) {
      return def_val;
    }
  }
  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();
    }
  }
 /**
  * Does the given parameter exist.
  *
  * @param parameter to check
  * @return true if exists, false if not present
  */
 public boolean doesParameterNonDefaultExist(String parameter) {
   return propertiesMap.containsKey(parameter);
 }
 /**
  * Remove the given configuration parameter completely.
  *
  * @param parameter to remove
  * @return true if found and removed, false if not
  */
 public boolean removeParameter(String parameter) {
   boolean removed = propertiesMap.remove(parameter) != null;
   if (removed) notifyParameterListeners(parameter);
   return removed;
 }
  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]");
            }
          }
        }
      }
    }
  }
 private byte[] getByteParameterRaw(String parameter) {
   return (byte[]) propertiesMap.get(parameter);
 }
 public Set<String> getDefinedParameters() {
   return (new HashSet<String>(propertiesMap.keySet()));
 }