diff --git a/src/main/java/io/jenkins/plugins/javax/activation/DelegatingFileTypeMap.java b/src/main/java/io/jenkins/plugins/javax/activation/DelegatingFileTypeMap.java new file mode 100644 index 0000000..95b9bff --- /dev/null +++ b/src/main/java/io/jenkins/plugins/javax/activation/DelegatingFileTypeMap.java @@ -0,0 +1,39 @@ +package io.jenkins.plugins.javax.activation; + +import edu.umd.cs.findbugs.annotations.NonNull; +import java.io.File; +import java.util.Objects; +import java.util.function.Supplier; +import javax.activation.FileTypeMap; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class DelegatingFileTypeMap extends FileTypeMap { + private final FileTypeMap delegate; + + public DelegatingFileTypeMap(@NonNull FileTypeMap delegate) { + this.delegate = Objects.requireNonNull(delegate); + } + + private static final T runWithContextClassLoader(Supplier supplier) { + Thread t = Thread.currentThread(); + ClassLoader orig = t.getContextClassLoader(); + t.setContextClassLoader(DelegatingFileTypeMap.class.getClassLoader()); + try { + return supplier.get(); + } finally { + t.setContextClassLoader(orig); + } + } + + @Override + public String getContentType(File file) { + return runWithContextClassLoader(() -> delegate.getContentType(file)); + } + + @Override + public String getContentType(String filename) { + return runWithContextClassLoader(() -> delegate.getContentType(filename)); + } +} diff --git a/src/main/java/io/jenkins/plugins/javax/activation/FileTypeMapInitializer.java b/src/main/java/io/jenkins/plugins/javax/activation/FileTypeMapInitializer.java new file mode 100644 index 0000000..f30a86c --- /dev/null +++ b/src/main/java/io/jenkins/plugins/javax/activation/FileTypeMapInitializer.java @@ -0,0 +1,25 @@ +package io.jenkins.plugins.javax.activation; + +import hudson.init.InitMilestone; +import hudson.init.Initializer; +import javax.activation.FileTypeMap; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class FileTypeMapInitializer { + + @Initializer(after = InitMilestone.PLUGINS_PREPARED, before = InitMilestone.PLUGINS_STARTED) + public static synchronized void init() { + Thread t = Thread.currentThread(); + ClassLoader orig = t.getContextClassLoader(); + t.setContextClassLoader(FileTypeMapInitializer.class.getClassLoader()); + try { + // Getting the default file type map fetches a per-thread-context-class-loader default. + // Setting the default file type map removes the per-thread-context-class-loader file type map. + FileTypeMap.setDefaultFileTypeMap(new DelegatingFileTypeMap(FileTypeMap.getDefaultFileTypeMap())); + } finally { + t.setContextClassLoader(orig); + } + } +}