atlascommunity / jira-plugins-groovy

Jira Groovy plugin
https://atlasteam.ru
BSD 2-Clause "Simplified" License
67 stars 41 forks source link

Add support for scripts from file system #8

Open lexek opened 5 years ago

BobbyNie commented 4 years ago

I did it by add a gloabl Class,maybe help

import org.apache.commons.io.FilenameUtils import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; import org.apache.commons.io.monitor.FileAlterationMonitor; import org.apache.commons.io.monitor.FileAlterationObserver; import org.codehaus.groovy.control.CompilerConfiguration import org.apache.commons.lang.exception.ExceptionUtils import org.codehaus.groovy.runtime.HandleMetaClass

class G extends HashMap<String,Object> { private static final List objectContainMethods = GroovyObject.methods.collect{it.name}+Object.metaClass.methods.collect{it.name} static class GroovyIOFileFilter extends IOFileFilter { @Override public boolean accept(File file) { String extension=FilenameUtils.getExtension(file.getAbsolutePath()); if(extension!=null&&extension.equals("groovy")){ return true; } return false; }

    @Override
    public boolean accept(File dir, String name)
    {
        String extension=FilenameUtils.getExtension(name);
        if(extension!=null&&extension.equals("groovy")){
            return true;
        }
        return false;
    }

}

private static GroovyClassLoader groovyClassLoader = null;
private static final String CLASS_PATH_OF_GROOVY="D:\\jira/data/runner"
private static FileFilter filter=FileFilterUtils.and(new GroovyIOFileFilter());
private static FileAlterationObserver groovyFileAltertionObserver=new FileAlterationObserver(CLASS_PATH_OF_GROOVY, filter);
private static FileAlterationMonitor filealterationMonitor=new FileAlterationMonitor(10000);
public String strProp = "Test Prop Groovy"
public G() {

    if(groovyClassLoader == null){
        CompilerConfiguration config = new CompilerConfiguration();
        config.setSourceEncoding("UTF-8");
        //config.setClasspath(CLASS_PATH_OF_GROOVY);
        groovyClassLoader = new GroovyClassLoader(this.getClass().getClassLoader(), config);
        groovyClassLoader.addClasspath(CLASS_PATH_OF_GROOVY)
        //println "classPath="+groovyClassLoader.classPath

    }

    def groovyDir = new File(CLASS_PATH_OF_GROOVY)
    groovyDir.eachFileMatch({"$it".endsWith(".groovy") }, {
        def objName = it.name  - ".groovy"
        def obj = loadGroovyObject( it)
        super["$objName"] = obj
    })

    final G gObj = this
    groovyFileAltertionObserver.addListener(new FileAlterationListenerAdaptor(){

                @Override
                public void onDirectoryCreate(File directory)
                {
                    //System.out.println("onDirectoryCreate");
                    super.onDirectoryCreate(directory);
                }

                @Override
                public void onDirectoryDelete(File directory)
                {
                    super.onDirectoryDelete(directory);
                }

                @Override
                public void onFileChange(File file)
                {
                    def objName = file.name  - ".groovy"
                    //when the groovy file changed  you must clear cache of groovyClassLoader to load new File
                    groovyClassLoader.clearCache()
                    def obj = loadGroovyObject( file);
                    //gObj.setProperty("$objName" , obj)
                    gObj[objName] =   obj
                    super.onFileChange(file);
                }

                @Override
                public void onFileCreate(File file)
                {
                    def objName = file.name  - ".groovy"
                    def obj =  loadGroovyObject( file)
                    //set the field to Object type.
                    //((HandleMetaClass)gObj.metaClass).setProperty("$objName",new Object())
                    //gObj.setProperty("$objName" , obj)
                    gObj[objName]=obj
                    super.onFileCreate(file);
                }

                @Override
                public void onFileDelete(File file)
                {
                    super.onFileDelete(file);
                }
            });

    filealterationMonitor.addObserver(groovyFileAltertionObserver);
    filealterationMonitor.start();

}

def loadGroovyObject(File groovyFile){
    try{
        Class<?> groovyClass = groovyClassLoader.parseClass(groovyFile);
        obj = (GroovyObject) groovyClass.newInstance();
        try {
            obj.invokeMethod("setG", this)
        }catch(Throwable e){
            return e  
        }
        return  obj
    }catch(Exception e){
        return e  
    }
}

public String getMethodInfo(String subObjName){
    String k = subObjName
    Object obj = this[k]
    String r = "*********$k of ${obj.class}**********\n"
    if(obj instanceof Exception){
        return "\tthe class: $k has compile error: "+ ExceptionUtils.getStackTrace(obj) +"\n"
    }

    GroovyObject v = (GroovyObject)obj
    if(v == null ) return ""

    v.properties.each({key,p->
        if( p != null &&  p instanceof Closure){
            r = r+ "\tClosure:$key \n"
        }
    })

    v.class.fields.each{
        def fieldValue = v.getProperty(it.name)
        if( fieldValue != null &&  fieldValue instanceof Closure){
            r = r+ "\tClosure:$it.name \n"
        }
    }

    v.metaClass.methods.each{ m->
        final String name = m.getName();
        if(!objectContainMethods.contains(name)) {
            r = r+ "\tMethod:$name  ( $m)\n"
        }
    }
    return r
}

@Override
public String toString(){
    String r = ""
    this.keySet().each{k->
        if(k != "class" ){
            r = r + getMethodInfo(k)+"\n"
        }
    }

    return r
}

static main(args) {
    G  g = new G();

    Map<String,Object> x = new HashMap<String,Object>()

    x.put("g",g)
    //println x.g.A
    //x.g.A.printA("sss")

    (new Thread({
        while(true){
            println g
            println "g="+g
            //println "g.A="+g.A.printA()
            Thread.sleep(10000)
        }
    } )).start()

}

}

andrei-a-papou commented 4 years ago

This would be a great feature. Currently I use it extensively in ScriptRunner as it allows me to use the IDEA IDE to build the scripts and then easily deploy them to the JIRA server via SSH.

@BobbyNie Any chance of submitting a pull request?