ZmtLaunchPlugin.groovy 5.47 KB
Newer Older
1 2 3 4
package de.zmt.gradle;

import org.gradle.api.*
import org.gradle.api.file.DuplicatesStrategy
5 6 7 8 9
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.attribute.PosixFilePermissions
import java.net.URL
import groovy.lang.Writable
10 11 12 13 14 15 16

/*
 * Distribution plugin for simulations based on zmt.core
 * <p>
 * With this plugin the simulation's jar file, source, dependencies
 * and the runtime dependencies are added to the distribution's lib
 * folder.
17 18 19
 * <p>
 * Start scripts for the launcher are added and a shortcut for running
 * the simulation in GUI mode.
20 21 22
 */
public class ZmtLaunchPlugin implements Plugin<Project> {
    private static final def MAIN_CLASS_NAME = 'de.zmt.Main'
23 24 25 26
    
    private static final def SHORTCUT_UNIX = 'run-with-gui'
    private static final def SHORTCUT_WIN = 'run-with-gui.bat'
    
27 28 29
    private static final def CONFIGURE = {
        apply plugin: 'distribution'
        
30 31 32 33 34 35
        // create shortcuts
        def shortcutDir = Files.createTempDirectory('shortcuts')
        Path unixShortcut = createLauncherShortcut(project, SHORTCUT_UNIX, shortcutDir)
        // set +x permissions for unix shortcut
        Files.setPosixFilePermissions(unixShortcut, PosixFilePermissions.fromString('rwxr-xr-x'))
        createLauncherShortcut(project, SHORTCUT_WIN, shortcutDir)
36 37 38 39 40 41 42 43 44 45
        
        distributions {
            main {
                contents {
                    into ('lib') {
                        // project's own library and dependencies     
                        from (project.jar)
                        from (project.sourceJar)
                        from (project.configurations.runtime)
                    }
46 47 48
                    
                    from (shortcutDir.toFile())
                    
49 50 51 52 53 54 55 56
                    // prevent adding duplicates 
                    // e.g. when several projects depend on the same library
                    // otherwise they are added several times to archives
                    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
                }
            }
        }
        
57
        def launcherProject = rootProject.ext.properties.get('launcherProject')
58 59 60 61
        // if this project is the launcher
        if (project.name == 'zmt-launcher') {
            // make it an application
            configure(project, MAKE_APPLICATION)
62
        }
63 64 65
        // else if the launcher project is present
        else if (launcherProject != null) {
            // include distribution contents from that project
66 67 68 69 70 71 72 73
            launcherProject.afterEvaluate {
                project.distributions.main.contents {
                    // include launcher and dependencies without sources
                    with (copySpec {
                        with (launcherProject.distributions.main.contents)
                        exclude('*sources*.jar')
                    })
                }
74 75 76 77 78 79
                
                /* add runtime dependency for this project in launcher 
                 * (if available) to make it executable */
                launcherProject.dependencies {
                    runtime(project)
                }
80 81
            }
        }
82
        // the launcher project is not present
83
        else {
84 85
            // add launcher dependency and make it an application
            project.dependencies {
86
                runtime 'de.zmt:zmt-launcher:latest.release'
87
            }
88
            configure(project, MAKE_APPLICATION)
89 90
        }
        
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
        // make jar executable
        jar {
            manifest {
                attributes 'Main-Class': MAIN_CLASS_NAME
            }
        }
    }
    
    /** 
     * Applies the application plugin, makes the main class point to launcher
     * and adds start scripts.
     */
    private static final def MAKE_APPLICATION = {
        apply plugin: 'application'
            
        mainClassName = MAIN_CLASS_NAME
    
        startScripts {
            /* Although launcher does not depend on other simulations, those
             * are needed to be included in the class path to be launched. */
            classpath += files('$APP_HOME/lib/*')
            applicationName = 'launcher'
        }
114 115 116
        
        run {
            description = description + ". Arguments can be supplied via 'args' project property (-Pargs='<args>')."
117
            if (project.hasProperty('args')) {
118 119
                args(project.args.split())
            }
120
            if (project.hasProperty('workingDir')) {
121 122
                workingDir = project.workingDir
            }
123
        }
124 125
    }
    
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
    private static final def TEMPLATE_ENGINE = new groovy.text.SimpleTemplateEngine()
    
    /**
      * Creates a launcher shortcut script. The template script is loaded
      * from given file name, processed to match the current project
      * and saved to the given directory.
      *
      * @param project the project
      * @param filename the file name of the template and the resulting file
      * @param directory the directory where to save the resulting file
      * @return the path to the resulting file
      */
    private static Path createLauncherShortcut(Project project, String filename, Path directory) {
        Path shortcut = Files.createFile(directory.resolve(filename))
        
        def binding = [projectName : project.name]
        def templateUrl = ZmtLaunchPlugin.class.getResource(filename)
        shortcut.append(TEMPLATE_ENGINE.createTemplate(templateUrl).make(binding))
        return shortcut
    }
    
147 148 149 150 151 152 153 154
    @Override
    void apply(Project project) {
        project.configure(project, CONFIGURE)
    }
}