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

org.bridje.vfs.CpSource Maven / Gradle / Ivy


package org.bridje.vfs;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * This object represents a Class Path source for the virtual file system.
 */
public class CpSource implements VfsSource
{
    private final String resource;

    private Map childs;

    /**
     * The only constructor for this object, the resource path needs to be specified.
     * 
     * @param resource The path to the resource folder to be mount.
     * @throws IOException If any IO exception occurs scanning the resource.
     * @throws URISyntaxException If the specified resource has an invalid URI.
     */
    public CpSource(String resource) throws IOException, URISyntaxException
    {
        this.resource = new Path(resource).toString();
        List resourceListing = getResourceListing(getClass(), this.resource + "/");
        if(resourceListing != null && !resourceListing.isEmpty())
        {
            this.childs = new HashMap<>();
            for (String childName : resourceListing)
            {
                this.childs.put(childName, new CpSource(resource + "/" + childName));
            }
        }
    }

    @Override
    public boolean isDirectory(Path path)
    {
        if(path == null || path.isRoot()) return childs != null;
        CpSource cp = childs.get(path.getFirstElement());
        return cp != null && cp.isDirectory(path.getNext());
    }

    @Override
    public boolean isFile(Path path)
    {
        if(path == null || path.isRoot()) return childs == null;
        CpSource cp = childs.get(path.getFirstElement());
        return cp != null && cp.isFile(path.getNext());
    }

    @Override
    public boolean exists(Path path)
    {
        if(path == null)
        {
            return true;
        }
        else
        {
            if (childs == null) return false;
            CpSource cp = childs.get(path.getFirstElement());
            return cp != null && cp.exists(path.getNext());
        }
    }

    @Override
    public boolean canWrite(Path path)
    {
        return false;
    }

    @Override
    public boolean canRead(Path path)
    {
        return isFile(path);
    }

    @Override
    public String[] list(Path path)
    {
        if(childs == null) return null;
        if(path == null)
        {
            String[] arr = new String[childs.size()];
            return childs.keySet().toArray(arr);
        }
        else
        {
            CpSource cp = childs.get(path.getFirstElement());
            if(cp == null) return null;
            return cp.list(path.getNext());
        }
    }

    @Override
    public InputStream openForRead(Path path)
    {
        if(path == null)
        {
            if(childs == null)
            {
                return getClass().getClassLoader().getResourceAsStream(resource);
            }
            return null;
        }
        else
        {
            CpSource cp = childs.get(path.getFirstElement());
            if(cp == null) return null;
            return cp.openForRead(path.getNext());
        }
    }

    @Override
    public OutputStream openForWrite(Path path)
    {
        return null;
    }

    private List getResourceListing(Class clazz, String path) throws URISyntaxException, IOException
    {
        String currentPath = path;
        if(currentPath.startsWith("/"))
        {
            currentPath = currentPath.substring(1);
        }
        Enumeration resources = clazz.getClassLoader().getResources(currentPath);
        Set result = new HashSet<>(); //avoid duplicates in case it is a subdirectory
        while (resources.hasMoreElements())
        {
            URL dirURL = resources.nextElement();
            if (dirURL != null && dirURL.getProtocol().equals("file"))
            {
                /* A file path: easy enough */
                String[] list = new File(dirURL.toURI()).list();
                if(list == null)
                {
                    return null;
                }
                result.addAll(Arrays.asList(list));
            }

            if (dirURL == null)
            {
                /*
                 * In case of a jar file, we can't actually find a directory.
                 * Have to assume the same jar as clazz.
                 */
                String me = clazz.getName().replace(".", "/").concat(".class");
                dirURL = clazz.getClassLoader().getResource(me);
            }

            if (dirURL != null && dirURL.getProtocol().equals("jar"))
            {
                /* A JAR path */
                String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
                JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
                Enumeration entries = jar.entries(); //gives ALL entries in jar
                Set currentProjectResource = new HashSet<>(); //avoid duplicates in case it is a subdirectory
                while (entries.hasMoreElements())
                {
                    JarEntry jarEntry = entries.nextElement();
                    String name = jarEntry.getName().trim();
                    if (name.startsWith(currentPath))
                    {
                        //filter according to the path
                        String entry = name.trim().substring(currentPath.length());
                        int checkSubdir = entry.indexOf("/");
                        if (checkSubdir >= 0)
                        {
                            // if it is a subdirectory, we just return the directory name
                            entry = entry.substring(0, checkSubdir);
                        }
                        if(!entry.isEmpty())
                        {
                            currentProjectResource.add(entry);
                        }
                    }
                }
                result.addAll(currentProjectResource);
            }
        }
        if (result.isEmpty())
        {
            return null;
        }
        List res = new LinkedList<>();
        res.addAll(result);
        return res;
    }

    @Override
    public List search(GlobExpr globExpr, Path path)
    {
        CpSource resource = findResource(path);
        if(resource.isDirectory(null))
        {
            List files = new ArrayList<>();
            resource.search(globExpr, path, files);
            return files;
        }
        return null;
    }
    
    /**
     * Finds a Class Path source associeted with the given path.
     * 
     * @param path The path of the resource.
     * @return The Class Path source associeted with the given path.
     */
    public CpSource findResource(Path path)
    {
        if(path == null || path.isRoot()) return this;
        CpSource child = childs.get(path.getFirstElement());
        if(child == null) return null;
        return child.findResource(path.getNext());
    }

    /**
     * Search for all the files that match the globExpr provided.
     * 
     * @param globExpr The glob expr provided.
     * @param path The path that needs to prefix all paths resulting from this search.
     * @param files The resulting paths for the search.
     */
    public void search(GlobExpr globExpr, Path path, List files)
    {
        for (Entry entry : childs.entrySet())
        {
            if(entry.getValue().isDirectory(null))
            {
                entry.getValue().search(globExpr, path.join(entry.getKey()), files);
            }
            else if(entry.getValue().isFile(null))
            {
                Path fullPath = path.join(entry.getKey());
                if(globExpr.globMatches(fullPath))
                {
                    files.add(fullPath);
                }
            }
        }
    }

    @Override
    public boolean createNewFile(Path path)
    {
        return false;
    }

    @Override
    public boolean mkdir(Path path)
    {
        return false;
    }

    @Override
    public boolean delete(Path path)
    {
        return false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy