I want to add custom manifest attributes to an existing jar file. The file is an external jar and is not the jar containing my application, nor is it a dependency of my application.
I drafted up some test code and verified that it makes the desired changes (by accessing the manifest with 7zip). However, it seems like Java is ignoring the manifest entry. When I call java.util.jar.Attributes.getValue(String)
, it returns null. This is the code I am using:
public static void main(String[] args) throws IOException, URISyntaxException {
File jar = new File("C:\\Users\\employee1234\\Desktop\\auth-0.1.3.jar");
String testVersion = "1.2.3";
Map<String, String> env = new HashMap<>();
env.put("create", "true");
// Mount the jar
try (FileSystem fileSystem = FileSystems.newFileSystem(jarFileToURI(jar), env)) {
// Read the manifest
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Path manifestPath = fileSystem.getPath("/META-INF/MANIFEST.MF");
Files.copy(manifestPath, byteArrayOutputStream);
// Convert the manifest bytes to a string and construct a string builder
StringBuilder manifestData = new StringBuilder(byteArrayOutputStream.toString().trim());
// Add the custom manifest attribute
manifestData.append("\n");
manifestData.append("Deployments-Version: ");
manifestData.append(testVersion);
// Write the manifest back to the jar
Files.copy(new ByteArrayInputStream(manifestData.toString().getBytes()), manifestPath,
StandardCopyOption.REPLACE_EXISTING);
// Try-with-resources closes the mounted jar
}
// This part doesn't work
try (JarFile jarFile = new JarFile(jar)) {
Manifest manifest = jarFile.getManifest();
System.out.println(manifest.getMainAttributes().getValue("Deployments-Version"));
}
}
// Stolen from java.io.File with some modifications
private static URI jarFileToURI(File jarFile) throws URISyntaxException {
String sp = slashify(jarFile.getAbsoluteFile().getPath(), false);
if (sp.startsWith("//"))
sp = "//" + sp;
return new URI("jar:file", null, sp, null);
}
// Stolen from java.io.File;
private static String slashify(String path, boolean isDirectory) {
String p = path;
if (File.separatorChar != '/')
p = p.replace(File.separatorChar, '/');
if (!p.startsWith("/"))
p = "/" + p;
if (!p.endsWith("/") && isDirectory)
p = p + "/";
return p;
}
I inspected the Manifest
instance in my debugger and the attribute was not anywhere present. I double and triple checked the jar file, and the manifest reflects my changes:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: employee1234
Build-Jdk: 1.8.0_202
Deployments-Version: 1.2.3
Is my issue with the way I am adding the attribute, or is the way I am attempting to read it? What am I doing wrong?
Make sure you append another linefeed after your newly added entry in the manifest and you should be good to go.
manifestData.append("\n").append("Deployments-Version: ").append(testVersion).append("\n");