Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save riccardobl/bdbbae9f2e8fefcd28dc5482ddc6b374 to your computer and use it in GitHub Desktop.
Save riccardobl/bdbbae9f2e8fefcd28dc5482ddc6b374 to your computer and use it in GitHub Desktop.
Gradle task to merge Log4j2Plugins.dat

A gradle task that merges Log4j2Plugins.dat from the various dependencies in a single file.

Useful when building a standalone jar.

If Log4j2Plugins.dat is not properly merged, log4j2 will print something like this:

ERROR StatusLogger Unrecognized format specifier [d]
ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [thread]
ERROR StatusLogger Unrecognized conversion specifier [thread] starting at position 25 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [level]
ERROR StatusLogger Unrecognized conversion specifier [level] starting at position 35 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [logger]
ERROR StatusLogger Unrecognized conversion specifier [logger] starting at position 47 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [msg]
ERROR StatusLogger Unrecognized conversion specifier [msg] starting at position 54 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [n]
ERROR StatusLogger Unrecognized conversion specifier [n] starting at position 56 in conversion pattern.
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
ERROR StatusLogger Unrecognized format specifier [d]
ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [thread]
ERROR StatusLogger Unrecognized conversion specifier [thread] starting at position 25 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [level]
ERROR StatusLogger Unrecognized conversion specifier [level] starting at position 35 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [logger]
ERROR StatusLogger Unrecognized conversion specifier [logger] starting at position 47 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [msg]
ERROR StatusLogger Unrecognized conversion specifier [msg] starting at position 54 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [n]
// License: CC0
def log4j2PluginsDatPath='META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat';
def mergeLog4j2PluginsDatTo(iin,to){
def writer=new DataOutputStream(to);
def reader=new DataInputStream(iin);
def count=reader.readInt();
println("Merge $count entries");
for(def k=0;k<count;k++){
writer.writeUTF(reader.readUTF());
def entries=reader.readInt();
writer.writeInt(entries);
for(def j=0;j<entries;j++){
writer.writeUTF(reader.readUTF());
writer.writeUTF(reader.readUTF());
writer.writeUTF(reader.readUTF());
writer.writeBoolean(reader.readBoolean());
writer.writeBoolean(reader.readBoolean());
}
}
writer.flush();
return count;
}
task mergeLog4j2PluginsDat << {
def log4j2PluginsDatFile = new File("$buildDir/classes/main/$log4j2PluginsDatPath");
def parent=log4j2PluginsDatFile.getParentFile();
def writer=new ByteArrayOutputStream();
if(!parent.exists()){
print("Path $parent does not exists. Create.");
log4j2PluginsDatFile.getParentFile().mkdirs();
}
def count=0;
configurations.compile.files.each { File file ->
def zipFile = new java.util.zip.ZipFile(file);
zipFile.entries().findAll { it.name =~ "Log4j2Plugins.dat" }.each {
def zipin=new BufferedInputStream(zipFile.getInputStream(it));
count+=mergeLog4j2PluginsDatTo(zipin,writer);
zipin.close();
}
}
if(log4j2PluginsDatFile.exists()){
def filein=new BufferedInputStream(new FileInputStream(log4j2PluginsDatFile));
count+=mergeLog4j2PluginsDatTo(filein,writer);
filein.close();
}
def bytes=writer.toByteArray();
writer.close();
writer=new DataOutputStream(new FileOutputStream(log4j2PluginsDatFile));
writer.writeInt(count);
writer.write(bytes);
writer.close();
}
classes.finalizedBy(mergeLog4j2PluginsDat)
@Corionis
Copy link

Corionis commented Mar 5, 2024

Created a Java "port" of this for those using Ant scripts. A stand-alone tool to merge a project's annotation-generated Log4j2Plugins.dat with multiple Log4j2Plugins.dat files found in Jars in the project library directory.

For those with legacy Ant scripts or who do not want to move to Maven or Gradle this solves the problem.

See GitHub project MergeLog4j2Plugins.

Thanks Riccardo!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment