Skip to content

Commit c3a9f46

Browse files
authored
Merge pull request #341 from Lilianne-Blaze/patch3-require-admin1
"Require admin rights" option for Windows exes
2 parents 9e01ec4 + 39b20ec commit c3a9f46

File tree

4 files changed

+122
-0
lines changed

4 files changed

+122
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.akathist.maven.plugins.launch4j;
2+
3+
import java.io.BufferedInputStream;
4+
import java.io.BufferedOutputStream;
5+
import java.io.ByteArrayOutputStream;
6+
import java.io.File;
7+
import java.io.FileInputStream;
8+
import java.io.FileOutputStream;
9+
import java.io.IOException;
10+
import java.io.InputStream;
11+
import java.util.Arrays;
12+
13+
public final class FileUtils {
14+
15+
public static final int DEF_BUF_SIZE = 4 * 1024;
16+
17+
public static byte[] readResourceAsBytes(String resName) throws IOException {
18+
ClassLoader cl = Thread.currentThread().getContextClassLoader();
19+
ByteArrayOutputStream baos = new ByteArrayOutputStream(4 * 1024);
20+
InputStream is = cl.getResourceAsStream(resName);
21+
22+
return readAllBytes(is);
23+
}
24+
25+
public static byte[] readBytes(File inFile) throws IOException {
26+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
27+
FileInputStream fis = new FileInputStream(inFile);
28+
BufferedInputStream bis = new BufferedInputStream(fis);
29+
30+
return readAllBytes(bis);
31+
}
32+
33+
public static byte[] readAllBytes(InputStream is) throws IOException {
34+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
35+
36+
byte buf[] = new byte[DEF_BUF_SIZE];
37+
int bytesRead = 0;
38+
while ((bytesRead = is.read(buf)) != -1) {
39+
baos.write(buf, 0, bytesRead);
40+
}
41+
42+
return baos.toByteArray();
43+
}
44+
45+
public static void writeBytesIfDiff(File outFile, byte[] outBytes) throws IOException {
46+
if (outFile.exists()) {
47+
byte[] existingBytes = readBytes(outFile);
48+
if (Arrays.equals(outBytes, existingBytes)) {
49+
return;
50+
}
51+
}
52+
writeBytes(outFile, outBytes);
53+
}
54+
55+
public static void writeBytes(File outFile, byte[] outBytes) throws IOException {
56+
try (
57+
FileOutputStream fos = new FileOutputStream(outFile, false);
58+
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
59+
bos.write(outBytes);
60+
bos.flush();
61+
}
62+
}
63+
64+
}

src/main/java/com/akathist/maven/plugins/launch4j/Launch4jMojo.java

+47
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import java.nio.file.Path;
5454
import java.nio.file.StandardCopyOption;
5555
import java.util.ArrayList;
56+
import java.util.Arrays;
5657
import java.util.Date;
5758
import java.util.Enumeration;
5859
import java.util.List;
@@ -78,6 +79,12 @@ public class Launch4jMojo extends AbstractMojo {
7879
@Parameter(defaultValue = "net.sf.launch4j", required = true)
7980
private String launch4jGroupId;
8081

82+
// intentionally non-static non-final so it can be hacked with reflection if someone really needs to
83+
private String DEF_REQADMMAN_RES = "META-INF/resources/manifest-requireAdminRights-v1.xml";
84+
85+
// intentionally non-static non-final so it can be hacked with reflection if someone really needs to
86+
private String DEF_REQADMMAN_FILE = "target/classes/META-INF/manifest-requireAdminRights.xml";
87+
8188
/**
8289
* Maven Session.
8390
*/
@@ -239,6 +246,12 @@ public class Launch4jMojo extends AbstractMojo {
239246
@Parameter
240247
private File icon;
241248

249+
/**
250+
* Whether the executable should ask for admin rights (Windows only).
251+
*/
252+
@Parameter(defaultValue = "false")
253+
private boolean requireAdminRights;
254+
242255
/**
243256
* Object files to include. Used for custom headers only.
244257
*/
@@ -351,6 +364,8 @@ private void doExecute() throws MojoExecutionException {
351364
return;
352365
}
353366

367+
processRequireAdminRights();
368+
354369
fillSensibleJreDefaults();
355370

356371
if (!disableVersionInfoDefaults) {
@@ -506,6 +521,37 @@ private void fillSensibleJreDefaults() throws MojoExecutionException {
506521
}
507522
}
508523

524+
private void processRequireAdminRights() throws MojoExecutionException {
525+
if (requireAdminRights) {
526+
getLog().warn("Modifying the resulting exe to always require Admin rights.");
527+
getLog().warn("Make sure it's necessary. Consider writing your own manifest file.");
528+
529+
if (manifest != null) {
530+
getLog().warn("manifest param is already set, overriding. Make sure that's what's intended.");
531+
}
532+
533+
try {
534+
File metaInfDir = new File(basedir, "target/classes/META-INF");
535+
metaInfDir.mkdir();
536+
537+
File manFile = new File(basedir, DEF_REQADMMAN_FILE);
538+
byte[] manBytes = FileUtils.readResourceAsBytes(DEF_REQADMMAN_RES);
539+
540+
FileUtils.writeBytesIfDiff(manFile, manBytes);
541+
542+
byte[] savedBytes = FileUtils.readBytes(manFile);
543+
if (Arrays.equals(manBytes, savedBytes)) {
544+
getLog().info("Manifest file written to " + manFile);
545+
}
546+
547+
manifest = manFile;
548+
} catch (Exception e) {
549+
getLog().error(e);
550+
throw new MojoExecutionException(e);
551+
}
552+
}
553+
}
554+
509555
/**
510556
* Prepares a little directory for launch4j to do its thing. Launch4j needs a bunch of object files
511557
* (in the w32api and head directories) and the ld and windres binaries (in the bin directory).
@@ -904,6 +950,7 @@ public String toString() {
904950
", stayAlive=" + stayAlive +
905951
", restartOnCrash=" + restartOnCrash +
906952
", icon=" + icon +
953+
", requireAdminRights=" + requireAdminRights +
907954
", objs=" + objs +
908955
", libs=" + libs +
909956
", vars=" + vars +
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
3+
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
4+
<security>
5+
<requestedPrivileges>
6+
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
7+
</requestedPrivileges>
8+
</security>
9+
</trustInfo>
10+
</assembly>

src/test/java/com/akathist/maven/plugins/launch4j/Launch4jMojoTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public void testPrintOutFulfilledConfiguration() throws Exception {
2727
"stayAlive=false, " +
2828
"restartOnCrash=false, " +
2929
"icon=null, " +
30+
"requireAdminRights=false, " +
3031
"objs=null, " +
3132
"libs=null, " +
3233
"vars=null, " +

0 commit comments

Comments
 (0)