diff --git a/src/main/java/io/jenkins/plugins/javax/activation/CommandMapInitializer.java b/src/main/java/io/jenkins/plugins/javax/activation/CommandMapInitializer.java new file mode 100644 index 0000000..3ecb187 --- /dev/null +++ b/src/main/java/io/jenkins/plugins/javax/activation/CommandMapInitializer.java @@ -0,0 +1,25 @@ +package io.jenkins.plugins.javax.activation; + +import hudson.init.InitMilestone; +import hudson.init.Initializer; +import javax.activation.CommandMap; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class CommandMapInitializer { + + @Initializer(after = InitMilestone.PLUGINS_PREPARED, before = InitMilestone.PLUGINS_STARTED) + public static synchronized void init() { + Thread t = Thread.currentThread(); + ClassLoader orig = t.getContextClassLoader(); + t.setContextClassLoader(CommandMapInitializer.class.getClassLoader()); + try { + // Getting the default command map fetches a per-thread-context-class-loader default. + // Setting the default command map removes the per-thread-context-class-loader command map. + CommandMap.setDefaultCommandMap(new DelegatingCommandMap(CommandMap.getDefaultCommandMap())); + } finally { + t.setContextClassLoader(orig); + } + } +} diff --git a/src/main/java/io/jenkins/plugins/javax/activation/DelegatingCommandMap.java b/src/main/java/io/jenkins/plugins/javax/activation/DelegatingCommandMap.java new file mode 100644 index 0000000..9fe4e0d --- /dev/null +++ b/src/main/java/io/jenkins/plugins/javax/activation/DelegatingCommandMap.java @@ -0,0 +1,76 @@ +package io.jenkins.plugins.javax.activation; + +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.Objects; +import java.util.function.Supplier; +import javax.activation.CommandInfo; +import javax.activation.CommandMap; +import javax.activation.DataContentHandler; +import javax.activation.DataSource; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class DelegatingCommandMap extends CommandMap { + private final CommandMap delegate; + + public DelegatingCommandMap(@NonNull CommandMap delegate) { + this.delegate = Objects.requireNonNull(delegate); + } + + private static final T runWithContextClassLoader(Supplier supplier) { + Thread t = Thread.currentThread(); + ClassLoader orig = t.getContextClassLoader(); + t.setContextClassLoader(DelegatingCommandMap.class.getClassLoader()); + try { + return supplier.get(); + } finally { + t.setContextClassLoader(orig); + } + } + + @Override + public CommandInfo[] getPreferredCommands(String mimeType) { + return runWithContextClassLoader(() -> delegate.getPreferredCommands(mimeType)); + } + + @Override + public CommandInfo[] getPreferredCommands(String mimeType, DataSource ds) { + return runWithContextClassLoader(() -> delegate.getPreferredCommands(mimeType, ds)); + } + + @Override + public CommandInfo[] getAllCommands(String mimeType) { + return runWithContextClassLoader(() -> delegate.getAllCommands(mimeType)); + } + + @Override + public CommandInfo[] getAllCommands(String mimeType, DataSource ds) { + return runWithContextClassLoader(() -> delegate.getAllCommands(mimeType, ds)); + } + + @Override + public CommandInfo getCommand(String mimeType, String cmdName) { + return runWithContextClassLoader(() -> delegate.getCommand(mimeType, cmdName)); + } + + @Override + public CommandInfo getCommand(String mimeType, String cmdName, DataSource ds) { + return runWithContextClassLoader(() -> delegate.getCommand(mimeType, cmdName, ds)); + } + + @Override + public DataContentHandler createDataContentHandler(String mimeType) { + return runWithContextClassLoader(() -> delegate.createDataContentHandler(mimeType)); + } + + @Override + public DataContentHandler createDataContentHandler(String mimeType, DataSource ds) { + return runWithContextClassLoader(() -> delegate.createDataContentHandler(mimeType, ds)); + } + + @Override + public String[] getMimeTypes() { + return runWithContextClassLoader(() -> delegate.getMimeTypes()); + } +}