Skip to content

Commit

Permalink
config: Correctly parse tokens for config dir and plugin dir
Browse files Browse the repository at this point in the history
  • Loading branch information
zml2008 committed Aug 22, 2020
1 parent 68f0e7c commit 8772692
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 15 deletions.
3 changes: 2 additions & 1 deletion src/main/java/org/spongepowered/common/SpongeCommon.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

import javax.annotation.Nullable;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

@Singleton
Expand Down Expand Up @@ -106,7 +107,7 @@ public static Path getGameDirectory() {
}

public static Path getPluginConfigDirectory() {
return SpongeCommon.getGameDirectory().resolve(SpongeConfigs.getCommon().get().getGeneral().configDir());
return Paths.get(SpongeConfigs.getCommon().get().getGeneral().configDir());
}

public static Path getSpongeConfigDirectory() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,21 @@
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import org.spongepowered.common.config.core.SpongeConfigs;
import org.spongepowered.common.config.core.TokenHoldingString;
import org.spongepowered.plugin.Blackboard;
import org.spongepowered.plugin.PluginEnvironment;
import org.spongepowered.plugin.PluginKeys;

import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@ConfigSerializable
public class GeneralCategory {

Expand All @@ -42,7 +54,7 @@ public class GeneralCategory {
+ "is going to search for a plugins folder in the mods directory. \n"
+ "If you wish for the plugins folder to reside in the root game \n"
+ "directory, change the value to \"${CANONICAL_GAME_DIR}/plugins\".")
private String pluginsDir = "${CANONICAL_MODS_DIR}/plugins";
private TokenHoldingString pluginsDir = TokenHoldingString.of("${CANONICAL_MODS_DIR}/plugins");
@Setting(value = "config-dir", comment = "The directory for Sponge plugin configurations, relative to the \n"
+ "execution root or specified as an absolute path. \n"
+ "Note that the default: \"${CANONICAL_GAME_DIR}/config\" \n"
Expand All @@ -51,30 +63,26 @@ public class GeneralCategory {
+ "directory, change the value to, for example, \"${CANONICAL_CONFIG_DIR}/sponge/plugins\". \n"
+ "Note: It is not recommended to set this to \"${CANONICAL_CONFIG_DIR}/sponge\", as there is \n"
+ "a possibility that plugin configurations can conflict the Sponge core configurations. \n")
private String configDir = "${CANONICAL_GAME_DIR}/config";
private TokenHoldingString configDir = TokenHoldingString.of("${CANONICAL_GAME_DIR}/config");

public boolean getFileIoThreadSleep() {
return this.fileIOThreadSleep;
}

public String pluginsDir() {
return this.pluginsDir;
return this.pluginsDir.getParsed();
}

public void setPluginsDir(String pluginsDir) {
this.pluginsDir = pluginsDir;
public void setPluginsDir(final String pluginsDir) {
this.pluginsDir = TokenHoldingString.of(pluginsDir);
}

public String configDir() {
return this.configDir;
return this.configDir.getParsed();
}

public void setConfigDir(String configDir) {
this.configDir = configDir;
}
private static String parsePlaceholders(final String input) {
final PluginEnvironment env = SpongeConfigs.getPluginEnvironment();
env.getBlackboard().get(PluginKeys.PLUGIN_DIRECTORIES);
return input;
public void setConfigDir(final String configDir) {
this.configDir = TokenHoldingString.of(configDir);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ public class SpongeConfigs {

static final ConfigurationOptions OPTIONS = ConfigurationOptions.defaults()
.withHeader(HEADER)
.withShouldCopyDefaults(true);
.withShouldCopyDefaults(true)
.withSerializers(collection -> collection.register(TokenHoldingString.SERIALIZER));

static final Logger LOGGER = LogManager.getLogger();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.common.config.core;

import com.google.common.reflect.TypeToken;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import ninja.leaping.configurate.objectmapping.serialize.ScalarSerializer;
import ninja.leaping.configurate.objectmapping.serialize.TypeSerializer;
import org.spongepowered.plugin.Blackboard;
import org.spongepowered.plugin.PluginEnvironment;
import org.spongepowered.plugin.PluginKeys;

import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Holder for a string value that is parsed for environment variables.
*/
public class TokenHoldingString {

static final ScalarSerializer<TokenHoldingString> SERIALIZER = new Serializer();

private static final Pattern TOKEN_MATCH = Pattern.compile("\\$\\{([^}]+)}");

private static final Map<String, Function<PluginEnvironment, String>> TOKENS = new HashMap<>();

static {
TokenHoldingString.register("CANONICAL_GAME_DIR", PluginKeys.BASE_DIRECTORY);
TokenHoldingString.register("CANONICAL_MODS_DIR", env -> {
// TODO: this is wrong, need to decide what configurability will be provided.
final List<Path> directories = env.getBlackboard().get(PluginKeys.PLUGIN_DIRECTORIES).orElse(Collections.emptyList());
return directories.isEmpty() ? null : directories.get(0).toString();
});
}

/**
* Create and parse a string.
*
* @param input Input value maybe with tokens
* @return holder
*/
public static TokenHoldingString of(final String input) {
return new TokenHoldingString(input, TokenHoldingString.parsePlaceholders(input));
}

private static void register(final String token, final Blackboard.Key<?> getter) {
register(token, env -> {
final Object value = env.getBlackboard().get(getter).orElse(null);
return value == null ? null : value.toString();
});
}

private static void register(final String token, final Function<PluginEnvironment, String> getter) {
TOKENS.put(token.toLowerCase(Locale.ROOT), getter);
}

/**
* Parse an environment variable-style placeholder syntax.
*
* <p>Variable names are case-insensitive, and detected with the
* {@link #TOKEN_MATCH} expression.</p>
*
* @param input input string
* @return string with placeholders replaced
*/
private static String parsePlaceholders(final String input) {
final PluginEnvironment env = SpongeConfigs.getPluginEnvironment();
final Matcher matcher = TOKEN_MATCH.matcher(input);
if (!matcher.find()) {
return input;
}
final StringBuffer result = new StringBuffer();
do {
final String token = matcher.group(1);
final Function<PluginEnvironment, String> replacer = TOKENS.get(token.toLowerCase());
final String replaced = replacer == null ? "" : replacer.apply(env);
matcher.appendReplacement(result, replaced == null ? "" : replaced);
} while (matcher.find());
matcher.appendTail(result);
return result.toString();
}

private final String plainValue;
private final String parsedValue;

private TokenHoldingString(final String plain, final String parsed) {
this.plainValue = plain;
this.parsedValue = parsed;
}

public String getPlain() {
return this.plainValue;
}

public String getParsed() {
return this.parsedValue;
}

static class Serializer extends ScalarSerializer<TokenHoldingString> {

Serializer() {
super(TokenHoldingString.class);
}

@Override
public TokenHoldingString deserialize(TypeToken<?> type, Object obj) throws ObjectMappingException {
return TokenHoldingString.of(obj.toString());
}

@Override
public Object serialize(TokenHoldingString item, Predicate<Class<?>> typeSupported) {
return item.getPlain();
}

}

}

0 comments on commit 8772692

Please sign in to comment.