All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.xpenatan.gdx.backends.teavm.config.AssetsCopy Maven / Gradle / Ivy

There is a newer version: 1.0.4
Show newest version
package com.github.xpenatan.gdx.backends.teavm.config;

import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.github.xpenatan.gdx.backends.teavm.TeaClassLoader;
import com.github.xpenatan.gdx.backends.teavm.assetloader.AssetType;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import com.badlogic.gdx.Files.FileType;

/**
 * @author xpenatan
 */
public class AssetsCopy {

    public static class Asset {
        FileHandle file;
        AssetType type;
        AssetFilterOption op;

        public Asset(FileHandle file, AssetType type, AssetFilterOption op) {
            this.file = file;
            this.type = type;
            this.op = op;
        }
    }

    public static ArrayList copyResources(TeaClassLoader classLoader, List classPathAssetsFiles, AssetFilter filter, FileHandle assetsOutputPath) {
        return copy(classLoader, classPathAssetsFiles, filter, assetsOutputPath);
    }

    public static ArrayList copyScripts(TeaClassLoader classLoader, List classPathAssetsFiles, FileHandle assetsOutputPath) {
        return copy(classLoader, classPathAssetsFiles, null, assetsOutputPath);
    }

    public static ArrayList copyAssets(AssetFileHandle fileHandle, AssetFilter filter, FileHandle assetsOutputPath) {
        return copy(fileHandle, filter, assetsOutputPath);
    }

    /**
     * Copy assets
     */
    private static ArrayList copy(AssetFileHandle assetsPath, AssetFilter filter, FileHandle target) {
        String assetsOutputPath = target.path();
        ArrayList assets = new ArrayList();
        if(assetsPath.filter != null) {
            //Override global filter with the handle filter
            filter = assetsPath.filter;
        }
        AssetFilter defaultAssetFilter = filter != null ? filter : new DefaultAssetFilter();
        if(assetsPath != null && assetsPath.exists() && assetsPath.isDirectory()) {
            TeaBuilder.log("Copying assets from:");
            FileHandle source = assetsPath;
            String path = source.path();
            TeaBuilder.log(path);
            copyDirectory(source, assetsPath.assetsChildDir, target, defaultAssetFilter, assets);

            TeaBuilder.log("to:");
            TeaBuilder.log(assetsOutputPath);
        }

        TeaBuilder.log("to:");
        TeaBuilder.log(assetsOutputPath);

        return assets;
    }

    /**
     * Copy resources
     */
    private static ArrayList copy(TeaClassLoader classloader, List classPathAssetsFiles, AssetFilter filter, FileHandle target) {
        String assetsOutputPath = target.path();
        ArrayList assets = new ArrayList();
        AssetFilter defaultAssetFilter = filter != null ? filter : new DefaultAssetFilter();

        if(classloader != null && classPathAssetsFiles != null) {
            // Copy assets from class package directory
            addDirectoryClassPathFiles(classPathAssetsFiles);
            TeaBuilder.log("");
            TeaBuilder.log("Copying assets from:");
            for(String classpathFile : classPathAssetsFiles) {
                String path = classpathFile;
                if(path.startsWith("/") == false) {
                    path = "/" + path;
                }
                else {
                    classpathFile = classpathFile.replaceFirst("/", "");
                }
                AssetFilterOption op = new AssetFilterOption();
                if(defaultAssetFilter.accept(path, false, op)) {
                    try {
                        TeaBuilder.log(classpathFile);
                        InputStream is = classloader.getResourceAsStream(classpathFile);
                        if(is != null) {
                            FileHandle dest = target.child(classpathFile);
                            dest.write(is, false);
                            String destPath = dest.path();
                            if(!destPath.endsWith(".js") && !destPath.endsWith(".wasm")) {
                                AssetFileHandle dest2 = AssetFileHandle.createHandle(dest.file(), FileType.Classpath);
                                assets.add(new Asset(dest2, getType(destPath), op));
                            }
                            is.close();
                        }
                    }
                    catch(IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        TeaBuilder.log("to:");
        TeaBuilder.log(assetsOutputPath);

        return assets;
    }

    public static void generateAssetsFile(ArrayList assets, FileHandle location, FileHandle assetFile) {
        StringBuffer buffer = new StringBuffer();
        String assetsOutputPath = location.path();
        for(int i = 0; i < assets.size(); i++) {
            Asset asset = assets.get(i);
            setupPreloadAssetFileFormat(asset, buffer, assetsOutputPath);
        }
        assetFile.writeString(buffer.toString(), true);
    }

    private static void setupPreloadAssetFileFormat(Asset asset, StringBuffer buffer, String assetsOutputPath) {
        FileHandle fileHandle = asset.file;
        FileType type = fileHandle.type();
        String path = fileHandle.path();
        path = path.replace(assetsOutputPath, "");
        String fileTypeStr = "i";
        if(type == FileType.Local) {
            fileTypeStr = "l";
        }
        else if(type == FileType.Classpath) {
            fileTypeStr = "c";
        }

        buffer.append(fileTypeStr);
        buffer.append(":");
        buffer.append(asset.type.code);
        buffer.append(":");
        buffer.append(path);
        buffer.append(":");
        buffer.append(asset.file.isDirectory() ? 0 : asset.file.length());
        buffer.append(":");
        buffer.append(asset.op.shouldOverwriteLocalData ? 1 : 0);
        buffer.append("\n");
    }

    private static void addDirectoryClassPathFiles(List classPathFiles) {
        ArrayList folderFilePaths = new ArrayList<>();
        for(int k = 0; k < classPathFiles.size(); k++) {
            String classpathFile = classPathFiles.get(k);
            classpathFile = classpathFile.replace("\\", "/");
            if(classpathFile.startsWith("/") == false)
                classpathFile = "/" + classpathFile;
            URL resource = AssetsCopy.class.getResource(classpathFile);
            if(resource != null) {
                URI uri = null;
                try {
                    uri = resource.toURI();
                }
                catch(URISyntaxException e1) {
                    e1.printStackTrace();
                }
                if(uri == null)
                    continue;

                // solution to get files inside jar/folder
                Path myPath = null;
                String scheme = uri.getScheme();
                FileSystem fileSystem = null;
                if(scheme.equals("jar")) {
                    try {
                        fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap());
                    }
                    catch(IOException e) {
                        e.printStackTrace();
                        continue;
                    }
                    myPath = fileSystem.getPath(classpathFile);
                }
                else {
                    myPath = Paths.get(uri);
                }
                Stream walk = null;
                try {
                    walk = Files.walk(myPath, 1);
                }
                catch(IOException e) {
                    e.printStackTrace();
                    continue;
                }
                boolean first = true;
                for(Iterator it = walk.iterator(); it.hasNext(); ) {
                    Path next = it.next();
                    String path = next.toString();
                    boolean directory = Files.isDirectory(next);
                    path = path.replace("\\", "/");
                    int i = path.lastIndexOf(classpathFile); // remove absolute path
                    path = path.substring(i + 1);
                    if(path.startsWith("/") == false)
                        path = "/" + path;
                    if(path.contains(".class") || path.contains(".java"))
                        continue;
                    if(directory) {
                        if(first) {
                            first = false;
                            classPathFiles.remove(k);
                            k--;
                            continue;
                        }
                        else {
                            classPathFiles.add(path);
                            continue;
                        }
                    }
                    folderFilePaths.add(path);
                }
                walk.close();
                if(fileSystem != null) {
                    try {
                        fileSystem.close();
                    }
                    catch(IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            else {// remove if it dont exist
                classPathFiles.remove(k);
                k--;
            }
        }
        classPathFiles.addAll(folderFilePaths);
        //Hack to remove duplicates.
        // Fixme fix/improve asset copy
        HashSet set = new HashSet<>(folderFilePaths);
        classPathFiles.clear();
        classPathFiles.addAll(set);
    }

    private static void copyDirectory(FileHandle sourceDir, String assetsChildDir, FileHandle destDir, AssetFilter filter, ArrayList assets) {
        if(!assetsChildDir.isEmpty()) {
            destDir = destDir.child(assetsChildDir);
        }
        copyDirectory(sourceDir, destDir, filter, assets);
    }

    private static void copyFile(FileHandle source, FileHandle dest, AssetFilter filter, ArrayList assets) {
        AssetFilterOption op = new AssetFilterOption();
        if(!filter.accept(dest.path(), false, op)) return;
        try {
            assets.add(new Asset(dest, getType(dest.path()), op));
            InputStream read = source.read();
            dest.write(read, false);
            read.close();
        }
        catch(Exception ex) {
            throw new GdxRuntimeException("Error copying source file: " + source + "\n" //
                    + "To destination: " + dest, ex);
        }
    }

    private static void copyDirectory(FileHandle sourceDir, FileHandle destDir, AssetFilter filter, ArrayList assets) {
        String destPath = destDir.path();
        destDir.mkdirs();
        FileHandle[] files = sourceDir.list();
        for(int i = 0, n = files.length; i < n; i++) {
            FileHandle srcFile = files[i];
            FileHandle destFile1 = destDir.child(srcFile.name());
            // Destination type is copied from source type
            FileHandle destFile = AssetFileHandle.createHandle(destFile1.file(), srcFile.type());
            if(srcFile.isDirectory()) {
                AssetFilterOption op = new AssetFilterOption();
                if(!filter.accept(destPath, true, op)) continue;
                assets.add(new Asset(destFile, AssetType.Directory, op));
                copyDirectory(srcFile, destFile, filter, assets);
            }
            else
                copyFile(srcFile, destFile, filter, assets);
        }
    }

    /**
     * @param file the file to get the type for
     * @return the type of the file, one of {@link AssetType}
     */
    @Deprecated
    public static AssetType getType(String file) {
        String extension = extension(file).toLowerCase();
        return AssetType.Binary;
    }

    private static String extension(String file) {
        String name = file;
        int dotIndex = name.lastIndexOf('.');
        if(dotIndex == -1) return "";
        return name.substring(dotIndex + 1);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy