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

com.redhat.ceylon.common.tool.PathPlugins Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package com.redhat.ceylon.common.tool;

import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.FileUtil;
import com.redhat.ceylon.common.OSUtil;
import com.redhat.ceylon.common.tool.ToolLoader;

/******************************************************
 * IMPORTANT There are two exact copies of this file
 * that need to be kept in sync! One in ceylon-compiler
 * (com.redhat.ceylon.launcher) and on in ceylon-common
 * (com.redhat.ceylon.common.tool)
 ******************************************************/

/**
 * Finds command plugins for the "ceylon" command 
 */
public class PathPlugins {
    private Set pathPlugins;

    public Set getPathPlugins() {
        if(pathPlugins == null){
            pathPlugins = new TreeSet();
            findPathPlugins();
        }
        return pathPlugins;
    }

    private void findPathPlugins() {
        Set names = new HashSet();
        // First in the project dir hierarchy, that is ./.ceylon/bin and  ./.ceylon/bin/{moduleName}/
        // and then going up into the parent folder until we reach the root
        File projectDir = (new File("")).getAbsoluteFile();
        while (projectDir != null) {
            File configBin = new File(new File(projectDir, Constants.CEYLON_CONFIG_DIR), Constants.CEYLON_BIN_DIR);
            findPathPlugins(configBin, names);
            projectDir = projectDir.getParentFile();
        }
        // Then look in ~/.ceylon/bin and ~/.ceylon/bin/{moduleName}/
        File defUserDir = new File(FileUtil.getDefaultUserDir(), Constants.CEYLON_BIN_DIR);
        findPathPlugins(defUserDir, names);
        // Then look in /etc/ceylon/bin and /etc/ceylon/bin/{moduleName}/
        // (or their equivalents on Windows and MacOS)
        File systemDir = new File(FileUtil.getSystemConfigDir(), Constants.CEYLON_BIN_DIR);
        findPathPlugins(systemDir, names);
        // Then the ones from CEYLON_HOME/bin and CEYLON_HOME/bin/{moduleName}/
        File ceylonHome = FileUtil.getInstallDir();
        if (ceylonHome != null) {
            findPathPlugins(new File(ceylonHome, Constants.CEYLON_BIN_DIR), names);
        }
        // And finally in the user's PATH
        File[] paths = FileUtil.getExecPath();
        for (File part : paths) {
            findPluginInPath(part, names);
        }
    }

    private void findPathPlugins(File dir, Set names) {
        // Look in dir 
        findPluginInPath(dir, names);
        // And in every installed script plugin in /{moduleName}/
        if(dir.isDirectory() && dir.canRead()){
            for(File scriptPluginDir : dir.listFiles()){
                if(scriptPluginDir.isDirectory()){
                    findPluginInPath(scriptPluginDir, names);
                }
            }
        }
    }

    private void findPluginInPath(File dir, final Set names) {
        if(dir.isDirectory() && dir.canRead()){
            // listing /usr/bin with >2k entries takes about 100ms using File.listFiles(Filter) and 39ms with NIO2
            // and checking for file name before file type
            DirectoryStream.Filter filter = new DirectoryStream.Filter() {
                public boolean accept(Path f) throws IOException {
                    String fileName = f.getFileName().toString();
                    if(fileName.toLowerCase().startsWith("ceylon-") && Files.isRegularFile(f)){
                        String name = fileName.substring(7);
                        // Is it a plugin file?
                        if(name.toLowerCase().endsWith(".plugin")){
                            name = name.substring(0, name.length()-7);
                            // we're good if it's unique
                            if (names.add(name)) {
                                pathPlugins.add(ToolLoader.PLUGIN_PREFIX+f.toAbsolutePath().toString());
                                return true;
                            }
                        }
                        // Is is a shell/batch script?
                        if(Files.isExecutable(f)){
                            if(OSUtil.isWindows()){
                                // script must end with ".bat"
                                if(!name.toLowerCase().endsWith(".bat"))
                                    return false;
                                // strip it
                                name = name.substring(0, name.length()-4);
                            }
                            // refuse any name with dots in there (like ceylon-completion.bash)
                            if(name.indexOf('.') != -1)
                                return false;
                            // also refuse ceylon-sh-setup
                            if(name.equalsIgnoreCase("sh-setup"))
                                return false;
                            // we're good if it's unique
                            if (names.add(name)) {
                                pathPlugins.add(ToolLoader.SCRIPT_PREFIX+f.toAbsolutePath().toString());
                                return true;
                            }
                        }
                    } else {
                        
                    }
                    return false;
                }
            };
            
            DirectoryStream  stream = null;
            try {
                stream = Files.newDirectoryStream(dir.toPath(), filter);
                for(@SuppressWarnings("unused") Path sub : stream){
                    // Nothing to do, just iterating
                }
            } catch (IOException e) {
                e.printStackTrace();
                // too bad, give up
            } finally {
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (IOException e) {
                    }
                }
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy