Package fr.neatmonster.nocheatplus.config

Source Code of fr.neatmonster.nocheatplus.config.PathUtils

package fr.neatmonster.nocheatplus.config;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;

import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.MemoryConfiguration;

import fr.neatmonster.nocheatplus.logging.LogUtil;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.CharPrefixTree;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree;

public class PathUtils {
 
  // Deprecated paths.
  private static final Set<String> deprecatedFields = new LinkedHashSet<String>();
  private static final SimpleCharPrefixTree deprecatedPrefixes = new SimpleCharPrefixTree();
 
  // Paths only for the global config.
  private static final Set<String> globalOnlyFields = new HashSet<String>();
  private static final SimpleCharPrefixTree globalOnlyPrefixes = new SimpleCharPrefixTree();
 
  // Paths moved to other paths.
  private static final Map<String, String> movedPaths = new LinkedHashMap<String, String>();
 
  static{
    initPaths();
  }
 
    /**
     * Initialize annotation-based path properties.
     * @return
     */
    private static void initPaths(){
      deprecatedFields.clear();
      deprecatedPrefixes.clear();
      globalOnlyFields.clear();
      globalOnlyPrefixes.clear();
      movedPaths.clear();
      for (final Field field : ConfPaths.class.getDeclaredFields()){
        if (field.getType() != String.class){
          // Only process strings.
          continue;
        }
        final String fieldName = field.getName();
       
        checkAddPrefixes(field, fieldName, GlobalConfig.class, globalOnlyFields, globalOnlyPrefixes);
        checkAddPrefixes(field, fieldName, Deprecated.class, deprecatedFields, deprecatedPrefixes);
        if (field.isAnnotationPresent(Moved.class)){
          // TODO: Prefixes: Might later support relocating  entire sections with one annotation?
          addMoved(field, field.getAnnotation(Moved.class));
        }
      }
    }
   
    private static void checkAddPrefixes(Field field, String fieldName, Class<? extends Annotation> annotation, Set<String> fieldNames, SimpleCharPrefixTree pathPrefixes) {
      if (field.isAnnotationPresent(annotation)){
      fieldNames.add(fieldName);
      addPrefixesField(field, pathPrefixes);
    }
    else{
      for (final String refName : fieldNames){
        if (fieldName.startsWith(refName)){
          addPrefixesField(field, pathPrefixes);
        }
      }
    }
  }

  private static void addPrefixesField(Field field, SimpleCharPrefixTree pathPrefixes) {
    try {
      final String path = field.get(null).toString();
      if (path != null){
        pathPrefixes.feed(path);
      }
    } catch (IllegalArgumentException e) {
    } catch (IllegalAccessException e) {
    }
  }

  private static void addMoved(final Field field, final Moved rel) {
      try {
      final String path = field.get(null).toString();
      movedPaths.put(path, rel.newPath());
    } catch (IllegalArgumentException e) {
    } catch (IllegalAccessException e) {
    }
  }
   
  /**
     * Warn on the console if paths are used.
     * @param config
     * @param paths
     * @param msgHeader
     * @param warnedPaths Paths which were found, can be null.
     */
    protected static void warnPaths(final ConfigFile config, final CharPrefixTree<?, ?> paths, final String msgPrefix, final Set<String> warnedPaths){
      final Logger logger = Bukkit.getLogger();
      for (final String path : config.getKeys(true)){
        if (paths.hasPrefix(path)){
          logger.warning("[NoCheatPlus] Config path '" + path + "'" + msgPrefix);
          if (warnedPaths != null){
            warnedPaths.add(path);
          }
        } 
      }
    }
   
    /**
     * Run all warning checks and alter config if necessary (GlobalConfig, Deprecated, Moved).
     * @param file
     * @param configName
     */
    public static void processPaths(File file, String configName, boolean isWorldConfig){
      ConfigFile config = new ConfigFile();
      try {
      config.load(file);
      final Set<String> removePaths = new LinkedHashSet<String>();
      final Map<String, Object> addPaths = new LinkedHashMap<String, Object>();
      if (isWorldConfig){
        // TODO: might remove these [though some global only paths might actually work].
        processGlobalOnlyPaths(config, configName, null);
      }
      processDeprecatedPaths(config, configName, removePaths);
      processMovedPaths(config, configName, removePaths, addPaths);
      boolean changed = false;
      if (!removePaths.isEmpty()){
        config = removePaths(config, removePaths);
        changed = true;
      }
      if (!addPaths.isEmpty()){
        setPaths(config, addPaths);
        changed = true;
      }
      if (changed){
        try{
          config.save(file);
        }
        catch(Throwable t){
          // Do log this one.
          LogUtil.logSevere("[NoCheatPlus] Failed to save configuration (" + configName + ") with changes: " + t.getClass().getSimpleName());
          LogUtil.logSevere(t);
        }
      }
    } catch (FileNotFoundException e) {
    } catch (IOException e) {
    } catch (InvalidConfigurationException e) {
    }
    }
   
    /**
     * Set paths.
     * @param config
     * @param addPaths
     */
    public static void setPaths(final ConfigFile config, final Map<String, Object> setPaths) {
      for (final Entry<String, Object> entry : setPaths.entrySet()){
        config.set(entry.getKey(), entry.getValue());
      }
  }
   
    /**
     * Get a new ConfigFile instance with all paths removed (recursively by prefix).
     * @param config
     * @param removePaths
     * @return
     */
  public static ConfigFile removePaths(final ConfigFile config, final Collection<String> removePaths) {
      final SimpleCharPrefixTree prefixes = new SimpleCharPrefixTree();
      for (final String path : removePaths){
        prefixes.feed(path);
      }
      final ConfigFile newConfig = new ConfigFile();
      for (final Entry<String, Object> entry : config.getValues(true).entrySet()){
        final String path = entry.getKey();
        final Object value = entry.getValue();
        if (value instanceof ConfigurationSection){
          continue;
        }
        if (!prefixes.hasPrefix(path)){
          newConfig.set(path, value);
        }
      }
    return newConfig;
  }

  /**
     *
     * @param config
     * @param configName
     * @param removePaths
   * @param addPaths
     * @return If entries were added (paths to be removed are processed later).
     */
    protected static void processMovedPaths(final ConfigFile config, final String configName, final Set<String> removePaths, final Map<String, Object> addPaths) {
      final Logger logger = Bukkit.getLogger();
    for (final Entry<String, String> entry : movedPaths.entrySet()){
      final String path = entry.getKey();
      if (config.contains(path)){
        final String newPath = entry.getValue();
        final String to;
        if (newPath == null | newPath.isEmpty()){
          to = ".";
        }
        else{
          to = " to '" + newPath + "'.";
          final Object value = config.get(path);
          config.set(newPath, value);
          addPaths.put(newPath, value);
          removePaths.add(path);
        }
        logger.warning("[NoCheatPlus] Config path '" + path + "' (" + configName + ") has been moved" + to);
      }
    }
  }

  /**
     * Warn about paths that are deprecated (not in use).
     * @param config
     * @param paths
     * @param configName
     */
    protected static void processDeprecatedPaths(ConfigFile config, String configName, final Set<String> removePaths){
      warnPaths(config, deprecatedPrefixes, " (" + configName + ") is not in use anymore.", removePaths);
    }
   
    /**
     * Warn about paths that are only to be set in the global config.
     * @param config
     * @param paths
     * @param configName
     */
    protected static void processGlobalOnlyPaths(ConfigFile config, String configName, final Set<String> removePaths){
      warnPaths(config, globalOnlyPrefixes, " (" + configName + ") should only be set in the global configuration.", removePaths);
    }
   
    /**
     * A config file only containing the entries that are not set as global only.
     * @param defaultConfig
     * @return
     */
    public static MemoryConfiguration getWorldsDefaultConfig(final ConfigFile defaultConfig){
      final char sep = defaultConfig.options().pathSeparator();
      final MemoryConfiguration config = new ConfigFile();
      config.options().pathSeparator(sep);
      final Map<String, Object> defaults = defaultConfig.getValues(false);
      for (final Entry<String, Object> entry : defaults.entrySet()){
        final String part = entry.getKey();
        if (!part.isEmpty() && !mayBeInWorldConfig(part)) continue;
        final Object value = entry.getValue();
        if (value instanceof ConfigurationSection) addWorldConfigSection(config, (ConfigurationSection) value, part, sep);
        else config.set(part, value);
      }
      return config;
    }

  protected static void addWorldConfigSection(final MemoryConfiguration config, final ConfigurationSection section, final String path, final char sep) {
    final Map<String, Object> values = section.getValues(false);
    for (final Entry<String, Object> entry : values.entrySet()){
      final String fullPath = path + sep + entry.getKey();
      if (!mayBeInWorldConfig(fullPath)) continue;
        final Object value = entry.getValue();
        if (value instanceof ConfigurationSection) addWorldConfigSection(config, (ConfigurationSection) value, fullPath, sep);
        else config.set(fullPath, value);
      }
  }
 
  public static boolean mayBeInWorldConfig(final String path){
    if (globalOnlyPrefixes.hasPrefix(path)) return false;
    return mayBeInConfig(path);
  }
 
  public static boolean mayBeInConfig(final String path){
    if (deprecatedPrefixes.hasPrefix(path)) return false;
    if (movedPaths.containsKey(path)) return false;
    return true;
  }
 
}
TOP

Related Classes of fr.neatmonster.nocheatplus.config.PathUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.