/** * This file is part of git-as-svn. It is subject to the license terms * in the LICENSE file found in the top-level directory of this distribution * and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn, * including this file, may be copied, modified, propagated, or distributed * except according to the terms contained in the LICENSE file. */ package svnserver.config.serializer; import org.atteo.classindex.ClassIndex; import org.jetbrains.annotations.NotNull; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.introspector.BeanAccess; import org.yaml.snakeyaml.nodes.Tag; import org.yaml.snakeyaml.representer.Representer; import svnserver.config.Config; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Map; import java.util.TreeMap; /** * Helper for parse/serialize configuration files. * * @author Artem V. Navrotskiy <bozaro@users.noreply.github.com> */ public class ConfigSerializer { @NotNull private static final String TAG_PREFIX = "!"; @NotNull private final Yaml yaml; public ConfigSerializer(boolean unsafeConfig) { final DumperOptions options = new DumperOptions(); options.setPrettyFlow(true); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); yaml = new Yaml(new ConfigConstructor(unsafeConfig), new ConfigRepresenter(unsafeConfig), options); yaml.setBeanAccess(BeanAccess.FIELD); } @NotNull public String dump(Config config) { return yaml.dump(config); } @NotNull public Config load(@NotNull InputStream stream) { return yaml.loadAs(stream, Config.class); } @NotNull public Config load(@NotNull File file) throws IOException { try (InputStream stream = new FileInputStream(file)) { return load(stream); } } private static Map<String, Class<?>> configTypes(boolean unsafeConfig) { final Map<String, Class<?>> result = new TreeMap<>(); for (Class<?> type : ClassIndex.getAnnotated(ConfigType.class)) { ConfigType annotation = type.getAnnotation(ConfigType.class); if (unsafeConfig || !annotation.unsafe()) { final String name = annotation.value(); if (result.put(TAG_PREFIX + name, type) != null) { throw new IllegalStateException("Found duplicate type name: " + name); } } } return result; } public static class ConfigConstructor extends Constructor { public ConfigConstructor(boolean unsafeConfig) { for (Map.Entry<String, Class<?>> entry : configTypes(unsafeConfig).entrySet()) { addTypeDescription(new TypeDescription(entry.getValue(), entry.getKey())); } } } public static class ConfigRepresenter extends Representer { public ConfigRepresenter(boolean unsafeConfig) { for (Map.Entry<String, Class<?>> entry : configTypes(unsafeConfig).entrySet()) { addClassTag(entry.getValue(), new Tag(entry.getKey())); } } } }