├── README.md
├── expose.gif
├── pom.xml
└── src
└── main
└── java
└── paroxayte
└── SelfExec.java
/README.md:
--------------------------------------------------------------------------------
1 | # selfexec-maven-plugin
2 |
3 | A maven plugin that allows jar files to be executed transparently (no java -jar ...). OS X and Linux systems are supported, Windows may be usable with a WSL. This maven plugin appends an sh script to the head of a certain jar in the ${project.build.directory} allowing it to be executed from a CLI without ceremony. The self-exec plugin may also be used to embed flags and user defined run commands.
4 |
5 |
6 | ## Usage
7 | *Making a self executing jar from a Hello World project and running*
8 | 
9 |
10 | ## Installation Instructions
11 |
12 |
13 |
14 | jitpack.io
15 | https://jitpack.io
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | com.github.paroxayte
24 | selfexec-maven-plugin
25 | v1.5.1
26 |
27 |
28 | com.github.paroxayte
29 | selfexec-maven-plugin
30 | v1.5.1
31 |
32 |
33 | ### *Optional*
34 | To making running this plugin from the command line significantly shorter, a configuration can be added to the maven settings.xml file. The is located in your maven home repository (eg: ~/.m2/repository). If a settings.xml does not exist create one and add the following:
35 |
36 |
37 | ....
38 |
39 | com.github.paroxayte
40 |
41 |
42 | After this added you will be able to invoke the plugin with `mvn selfexec:selfexec`
43 |
44 | ## Configurations
45 |
46 | This plugin has the following public properties:
47 |
48 | * **jarName:** Represents the jarFile to be made self executable. Default value - `${project.artifactId}-${project.version}`
49 |
50 | * **finalName:** Determines the name of the generated self-executing jar. If it is the same as another file name in the output directory, it will overwrite that file.
51 |
52 | * **jarLoc:** The directory which contains the target jarFile. Default value -`${project.build.directory}`
53 |
54 | * **flags:** The command to embed in to the jar file. Default value - `java -jar $0 \"$@\"`
55 |
56 | * **shebang** The shebang of the embedded script. Default value - `#!/bin/sh`
57 |
58 | The single goal of this plugin, **selfexec** simply creates a new file which is a self executing version of the provided jar.
59 |
60 | ### Example configuration
61 |
62 |
63 |
64 |
65 |
66 | com.github.paroxayte
67 | selfexec-maven-plugin
68 | v1.5.1
69 |
70 |
71 | com.github.paroxayte
72 | selfexec-maven-plugin
73 | v1.5.1
74 |
75 | foo
76 |
77 |
78 |
79 | install
80 |
81 | selfexec
82 |
83 |
84 |
85 |
86 |
87 | If you use a custom name on your jar, it may be desirable to set a property to keep you finalName and jarName linked since they must be the same. EG:
88 |
89 |
90 | example
91 |
92 | ...
93 | ${buildName}
94 | ...
95 | ${buildName}
96 |
97 | This plugin may also be run from the CLI in a maven project directory. `mvn selfexec:selfexec`
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/expose.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fireflowerr/selfexec-maven-plugin/60eb5b141d30353dfe7bec45acc4cce6dc2b4d41/expose.gif
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.github.paroxayte
5 | selfexec-maven-plugin
6 | maven-plugin
7 | v1.5.1
8 | selfexec-maven-plugin
9 | https://github.com/paroxayte/selfexec-maven-plugin
10 |
11 |
12 | UTF-8
13 | 1.8
14 | 1.8
15 |
16 |
17 |
18 |
19 | org.apache.maven
20 | maven-plugin-api
21 | 3.5.4
22 |
23 |
24 | org.apache.maven.plugin-tools
25 | maven-plugin-annotations
26 | 3.5.2
27 | compile
28 |
29 |
30 |
31 |
32 |
33 |
34 | org.apache.maven.plugins
35 | maven-plugin-plugin
36 | 3.5.2
37 |
38 | selfexec
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/main/java/paroxayte/SelfExec.java:
--------------------------------------------------------------------------------
1 | package paroxayte;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedOutputStream;
5 | import java.io.DataInputStream;
6 | import java.io.DataOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.OutputStream;
10 | import java.io.OutputStreamWriter;
11 | import java.io.PrintWriter;
12 | import java.nio.charset.StandardCharsets;
13 | import java.nio.file.FileSystems;
14 | import java.nio.file.Files;
15 | import java.nio.file.Path;
16 | import java.nio.file.StandardOpenOption;
17 | import java.nio.file.attribute.PosixFilePermissions;
18 | import org.apache.maven.plugin.AbstractMojo;
19 | import org.apache.maven.plugin.MojoExecutionException;
20 | import org.apache.maven.plugins.annotations.Mojo;
21 | import org.apache.maven.plugins.annotations.Parameter;
22 |
23 |
24 | @Mojo(name = "selfexec")
25 | public class SelfExec extends AbstractMojo {
26 |
27 | // The name of the jar to be made self executing.
28 | @Parameter(property = "jarName", defaultValue = "${project.artifactId}-${project.version}")
29 | private String jarName;
30 |
31 | // Determines the name of the outputed selfexec jar file. Default value is jarName without .jar extension
32 | @Parameter(property = "finalName")
33 | private String finalName;
34 |
35 | //The directory to look for the jar file in.
36 | @Parameter(property = "jarLoc", defaultValue = "${project.build.directory}")
37 | private String buildDir;
38 |
39 | //The command to run the jar with.
40 | @Parameter(property = "flags", defaultValue = "java -jar $0 \"$@\"")
41 | private String flags;
42 |
43 | //The shebang to use (change to use a different bash shell)
44 | @Parameter(property = "shebang", defaultValue = "#!/bin/sh")
45 | private String shebang;
46 |
47 | public void execute() throws MojoExecutionException {
48 | if(!jarName.matches(".+\\.jar$")) {
49 | jarName += ".jar";
50 | }
51 |
52 | if(finalName == null) {
53 | finalName = jarName.substring(0, jarName.length() - 4);
54 | }
55 |
56 | Path finalNamePath = FileSystems.getDefault().getPath(buildDir, finalName);
57 | Path jarFile = FileSystems.getDefault().getPath(buildDir, jarName);
58 |
59 | if (Files.exists(jarFile)) {
60 |
61 | try(InputStream baseIn = Files.newInputStream(jarFile, StandardOpenOption.READ); OutputStream baseOut = Files.newOutputStream(finalNamePath, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);) {
62 |
63 | // Begin constructing self executing jar
64 | PrintWriter scriptWrite = new PrintWriter(new OutputStreamWriter(baseOut, StandardCharsets.UTF_8), true);
65 | scriptWrite.println(shebang);
66 | scriptWrite.println("\n\n");
67 | scriptWrite.println("exec " + flags);
68 | scriptWrite.println("\n\n\n\n");
69 |
70 | // Build a execute script and append jar to it
71 | DataInputStream readIn = new DataInputStream(new BufferedInputStream(baseIn));
72 | DataOutputStream writeOut = new DataOutputStream(new BufferedOutputStream(baseOut));
73 | byte[] bufStore = new byte[readIn.available()];
74 | int bytesRead;
75 | while((bytesRead = readIn.read(bufStore)) > 0) {
76 | writeOut.write(bufStore, 0, bytesRead);
77 | }
78 | writeOut.flush();
79 |
80 | } catch(IOException e) {
81 | e.printStackTrace();
82 | } finally {
83 | try {
84 | Files.setPosixFilePermissions(finalNamePath, PosixFilePermissions.fromString("rwxr-xr-x"));
85 | } catch(IOException e) {
86 | throw new RuntimeException("Failed to set executable permissions...", e);
87 | }
88 | }
89 |
90 | } else {
91 | throw new MojoExecutionException(jarName + " not found in build output directory");
92 | }
93 |
94 | }
95 |
96 | }
--------------------------------------------------------------------------------