// Path: src/main/java/me/itzg/mccy/types/MccyConstants.java
// public class MccyConstants {
// 
// 
//     public static final String MCCY_LABEL_PREFIX = MccySwarmApplication.class.getPackage().getName();
//     public static final String MCCY_LABEL = MCCY_LABEL_PREFIX;
//     public static final String MCCY_LABEL_MODPACK_URL = MCCY_LABEL_PREFIX+".modpack-url";
//     public static final String MCCY_LABEL_NAME = MCCY_LABEL_PREFIX+".name";
//     public static final String MCCY_LABEL_PUBLIC = MCCY_LABEL_PREFIX+".public";
//     public static final String MCCY_LABEL_OWNER = MCCY_LABEL_PREFIX+".owner";
// 
//     public static final int SERVER_CONTAINER_PORT_INT = 25565;
//     public static final String SERVER_CONTAINER_PORT = String.valueOf(SERVER_CONTAINER_PORT_INT)+ "/tcp";
//     public static final String IP_ADDR_ALL_IF = "0.0.0.0";
// 
//     public static final String X_XSRF_TOKEN = "X-XSRF-TOKEN";
// 
//     public static final String FILE_MOD_INFO = "mod.info";
//     public static final String FILE_MCMOD_INFO = "mcmod.info";
//     public static final String FILE_PLUGIN_META = "plugin.yml";
// 
//     public static final String TEMP_PREFIX = "temp-";
// 
//     public static final String CATEGORY_WORLDS = "worlds";
//     public static final String CATEGORY_MODS = "mods";
// 
//     public static final ComparableVersion[] FORGE_VERSIONS_SQUASHED = new ComparableVersion[]{
//             ComparableVersion.of("1.8"),
//             ComparableVersion.of("1.8.8")
//     };
//     public static final int FORGE_VERSIONS_SQUASHED_SIZE = 2;
// 
//     public static final String EXT_WORLDS = ".zip";
//     public static final String EXT_MODS = ".jar";
//     public static final String EXT_MOD_PACK = ".zip";
// 
//     public static final String ENV_ICON = "ICON";
//     public static final String ENV_VERSION = "VERSION";
//     public static final String ENV_FORGEVERSION = "FORGEVERSION";
//     public static final String ENV_WORLD = "WORLD";
//     public static final String ENV_MODPACK = "MODPACK";
//     public static final String ENV_TYPE = "TYPE";
//     public static final String ENV_DIFFICULTY = "DIFFICULTY";
//     public static final String ENV_WHITELIST = "WHITELIST";
//     public static final String ENV_OPS = "OPS";
//     public static final String ENV_SEED = "SEED";
//     public static final String ENV_MODE = "MODE";
//     public static final String ENV_MOTD = "MOTD";
//     public static final String ENV_PVP = "PVP";
//     public static final String ENV_LEVEL_TYPE = "LEVEL_TYPE";
//     public static final String ENV_GENERATOR_SETTINGS = "GENERATOR_SETTINGS";
//     public static final String ENV_LEVEL = "LEVEL";
// 
//     public static final String LINK_MCCY = "mccy";
//     public static final String SNAPSHOT_VER_PATTERN = "(?<nYear>\\d+)w(?<nWeek>\\d+)(?<sRel>[a-z]+)";
// 
//     public static final String PROFILE_BASIC_AUTH = "basicAuth";
//     public static final String PROFILE_DEV = "dev";
//     public static final String MF_ATTR_FML_CORE_PLUGIN = "FMLCorePlugin";
// }
// 
// Path: src/main/java/me/itzg/mccy/types/MccyNotFoundException.java
// public class MccyNotFoundException extends MccyClientException {
//     public MccyNotFoundException() {
//     }
// 
//     public MccyNotFoundException(String message) {
//         super(message);
//     }
// 
//     public MccyNotFoundException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public MccyNotFoundException(Throwable cause) {
//         super(cause);
//     }
// }


import me.itzg.mccy.config.MccyFilesSettings;
import me.itzg.mccy.types.MccyConstants;
import me.itzg.mccy.types.MccyNotFoundException;
import me.itzg.mccy.types.ReleasingFileSystemResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

    public String save(String category, String filename, boolean temporary, MultipartFile src) throws IOException {
        final Path categoryPath = resolveCategoryPath(category);

        final Path outFile = categoryPath.resolve(
                (temporary ? MccyConstants.TEMP_PREFIX : "") + filename
        );

        Files.copy(src.getInputStream(), outFile);

        return outFile.getFileName().toString();
    }

    public void delete(String category, String filename) {
        final Path resolved = repoPath.resolve(category);

        try {
            Files.delete(resolved.resolve(filename));
        } catch (IOException e) {
            LOG.warn("Failed to delete {} file named {}", e, category, filename);
        }
    }

    /**
     *
     * @param category the file storage category
     * @param filename the name of the file within the category
     * @param out where the content of the file will be written. NOTE: this stream will NOT be closed by this
     *            method
     */
// Path: src/main/java/me/itzg/mccy/types/MccyConstants.java
// public class MccyConstants {
// 
// 
//     public static final String MCCY_LABEL_PREFIX = MccySwarmApplication.class.getPackage().getName();
//     public static final String MCCY_LABEL = MCCY_LABEL_PREFIX;
//     public static final String MCCY_LABEL_MODPACK_URL = MCCY_LABEL_PREFIX+".modpack-url";
//     public static final String MCCY_LABEL_NAME = MCCY_LABEL_PREFIX+".name";
//     public static final String MCCY_LABEL_PUBLIC = MCCY_LABEL_PREFIX+".public";
//     public static final String MCCY_LABEL_OWNER = MCCY_LABEL_PREFIX+".owner";
// 
//     public static final int SERVER_CONTAINER_PORT_INT = 25565;
//     public static final String SERVER_CONTAINER_PORT = String.valueOf(SERVER_CONTAINER_PORT_INT)+ "/tcp";
//     public static final String IP_ADDR_ALL_IF = "0.0.0.0";
// 
//     public static final String X_XSRF_TOKEN = "X-XSRF-TOKEN";
// 
//     public static final String FILE_MOD_INFO = "mod.info";
//     public static final String FILE_MCMOD_INFO = "mcmod.info";
//     public static final String FILE_PLUGIN_META = "plugin.yml";
// 
//     public static final String TEMP_PREFIX = "temp-";
// 
//     public static final String CATEGORY_WORLDS = "worlds";
//     public static final String CATEGORY_MODS = "mods";
// 
//     public static final ComparableVersion[] FORGE_VERSIONS_SQUASHED = new ComparableVersion[]{
//             ComparableVersion.of("1.8"),
//             ComparableVersion.of("1.8.8")
//     };
//     public static final int FORGE_VERSIONS_SQUASHED_SIZE = 2;
// 
//     public static final String EXT_WORLDS = ".zip";
//     public static final String EXT_MODS = ".jar";
//     public static final String EXT_MOD_PACK = ".zip";
// 
//     public static final String ENV_ICON = "ICON";
//     public static final String ENV_VERSION = "VERSION";
//     public static final String ENV_FORGEVERSION = "FORGEVERSION";
//     public static final String ENV_WORLD = "WORLD";
//     public static final String ENV_MODPACK = "MODPACK";
//     public static final String ENV_TYPE = "TYPE";
//     public static final String ENV_DIFFICULTY = "DIFFICULTY";
//     public static final String ENV_WHITELIST = "WHITELIST";
//     public static final String ENV_OPS = "OPS";
//     public static final String ENV_SEED = "SEED";
//     public static final String ENV_MODE = "MODE";
//     public static final String ENV_MOTD = "MOTD";
//     public static final String ENV_PVP = "PVP";
//     public static final String ENV_LEVEL_TYPE = "LEVEL_TYPE";
//     public static final String ENV_GENERATOR_SETTINGS = "GENERATOR_SETTINGS";
//     public static final String ENV_LEVEL = "LEVEL";
// 
//     public static final String LINK_MCCY = "mccy";
//     public static final String SNAPSHOT_VER_PATTERN = "(?<nYear>\\d+)w(?<nWeek>\\d+)(?<sRel>[a-z]+)";
// 
//     public static final String PROFILE_BASIC_AUTH = "basicAuth";
//     public static final String PROFILE_DEV = "dev";
//     public static final String MF_ATTR_FML_CORE_PLUGIN = "FMLCorePlugin";
// }
// 
// Path: src/main/java/me/itzg/mccy/types/MccyNotFoundException.java
// public class MccyNotFoundException extends MccyClientException {
//     public MccyNotFoundException() {
//     }
// 
//     public MccyNotFoundException(String message) {
//         super(message);
//     }
// 
//     public MccyNotFoundException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public MccyNotFoundException(Throwable cause) {
//         super(cause);
//     }
// }


// Path: src/main/java/me/itzg/mccy/services/FileStorageService.java
import me.itzg.mccy.config.MccyFilesSettings;
import me.itzg.mccy.types.MccyConstants;
import me.itzg.mccy.types.MccyNotFoundException;
import me.itzg.mccy.types.ReleasingFileSystemResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;


    public String save(String category, String filename, boolean temporary, MultipartFile src) throws IOException {
        final Path categoryPath = resolveCategoryPath(category);

        final Path outFile = categoryPath.resolve(
                (temporary ? MccyConstants.TEMP_PREFIX : "") + filename
        );

        Files.copy(src.getInputStream(), outFile);

        return outFile.getFileName().toString();
    }

    public void delete(String category, String filename) {
        final Path resolved = repoPath.resolve(category);

        try {
            Files.delete(resolved.resolve(filename));
        } catch (IOException e) {
            LOG.warn("Failed to delete {} file named {}", e, category, filename);
        }
    }

    /**
     *
     * @param category the file storage category
     * @param filename the name of the file within the category
     * @param out where the content of the file will be written. NOTE: this stream will NOT be closed by this
     *            method
     */
    public void copyTo(String category, String filename, OutputStream out) throws IOException, MccyNotFoundException {