com.almworks.jira.structure.api.util.JiraComponents Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of structure-api Show documentation
Show all versions of structure-api Show documentation
Public API for the Structure Plugin for JIRA
package com.almworks.jira.structure.api.util;
import com.almworks.jira.structure.api.lifecycle.CachingComponent;
import com.atlassian.jira.avatar.AvatarManager;
import com.atlassian.jira.bc.project.component.ProjectComponentManager;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.config.ConstantsManager;
import com.atlassian.jira.config.properties.ApplicationProperties;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.customfields.manager.OptionsManager;
import com.atlassian.jira.plugin.ComponentClassManager;
import com.atlassian.jira.project.ProjectManager;
import com.atlassian.jira.project.version.VersionManager;
import com.atlassian.jira.security.*;
import com.atlassian.jira.security.groups.GroupManager;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.user.util.UserManager;
import com.atlassian.jira.user.util.UserUtil;
import com.atlassian.plugin.PluginAccessor;
import org.jetbrains.annotations.*;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import java.lang.reflect.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class JiraComponents implements DisposableBean, InitializingBean, CachingComponent {
private static final Map, ? super Object> proxyCache = new ConcurrentHashMap<>();
@Nullable
public static T getOSGiComponentInstanceOfType(@NotNull Class intfClass) {
assert intfClass.isInterface() : intfClass;
T service = ComponentAccessor.getOSGiComponentInstanceOfType(intfClass);
return createTCCLSwitchingProxy(intfClass, service);
}
@Nullable
public static T getComponentOfType(@NotNull Class intfClass) {
assert intfClass.isInterface() : intfClass;
T service = ComponentAccessor.getComponentOfType(intfClass);
return getTCCLSwitchingProxy(intfClass, service);
}
@Nullable
public static T getComponent(@NotNull Class intfClass) {
assert intfClass.isInterface() : intfClass;
T service = ComponentAccessor.getComponent(intfClass);
return getTCCLSwitchingProxy(intfClass, service);
}
public static JiraAuthenticationContext getJiraAuthenticationContext() {
return getTCCLSwitchingProxy(JiraAuthenticationContext.class, ComponentAccessor.getJiraAuthenticationContext());
}
public static ProjectManager getProjectManager() {
return getTCCLSwitchingProxy(ProjectManager.class, ComponentAccessor.getProjectManager());
}
public static ProjectComponentManager getProjectComponentManager() {
return getTCCLSwitchingProxy(ProjectComponentManager.class, ComponentAccessor.getProjectComponentManager());
}
public static ConstantsManager getConstantsManager() {
return getTCCLSwitchingProxy(ConstantsManager.class, ComponentAccessor.getConstantsManager());
}
public static VersionManager getVersionManager() {
return getTCCLSwitchingProxy(VersionManager.class, ComponentAccessor.getVersionManager());
}
public static OptionsManager getOptionsManager() {
return getTCCLSwitchingProxy(OptionsManager.class, ComponentAccessor.getOptionsManager());
}
public static UserManager getUserManager() {
return getTCCLSwitchingProxy(UserManager.class, ComponentAccessor.getUserManager());
}
public static GroupManager getGroupManager() {
return getTCCLSwitchingProxy(GroupManager.class, ComponentAccessor.getGroupManager());
}
public static UserUtil getUserUtil() {
return getTCCLSwitchingProxy(UserUtil.class, ComponentAccessor.getUserUtil());
}
public static PluginAccessor getPluginAccessor() {
return getTCCLSwitchingProxy(PluginAccessor.class, ComponentAccessor.getPluginAccessor());
}
public static PermissionManager getPermissionManager() {
return getTCCLSwitchingProxy(PermissionManager.class, ComponentAccessor.getPermissionManager());
}
public static ApplicationProperties getApplicationProperties() {
return getTCCLSwitchingProxy(ApplicationProperties.class, ComponentAccessor.getApplicationProperties());
}
public static IssueManager getIssueManager() {
return getTCCLSwitchingProxy(IssueManager.class, ComponentAccessor.getIssueManager());
}
public static AvatarManager getAvatarManager() {
return getTCCLSwitchingProxy(AvatarManager.class, ComponentAccessor.getAvatarManager());
}
public static ComponentClassManager getComponentClassManager() {
return getTCCLSwitchingProxy(ComponentClassManager.class, ComponentAccessor.getComponentClassManager());
}
public static GlobalPermissionManager getGlobalPermissionManager() {
return getTCCLSwitchingProxy(GlobalPermissionManager.class, ComponentAccessor.getGlobalPermissionManager());
}
@Contract("_, null -> null; _, !null -> !null")
private static T getTCCLSwitchingProxy(@NotNull Class intfClass, @Nullable T service) {
if (service == null) return null;
Object cache = proxyCache.get(intfClass);
if (cache != null) {
// noinspection unchecked
return (T) cache;
}
T proxy = createTCCLSwitchingProxy(intfClass, service);
proxyCache.put(intfClass, proxy);
return proxy;
}
@Contract("_, null -> null; _, !null -> !null")
private static T createTCCLSwitchingProxy(@NotNull Class intfClass, @Nullable T service) {
// noinspection Contract
assert intfClass.isInterface() : intfClass;
// noinspection unchecked
return service == null ? null : (T) Proxy.newProxyInstance(
service.getClass().getClassLoader(), new Class[] {intfClass},
new TCCLSwitchingInvocationHandler(service));
}
@Override
public final void afterPropertiesSet() throws Exception {
proxyCache.clear();
}
@Override
public final void destroy() throws Exception {
proxyCache.clear();
}
@Override
public void clearCaches() {
proxyCache.clear();
}
@Override
public void clearUserCaches(@NotNull ApplicationUser user) {
}
private static final class TCCLSwitchingInvocationHandler implements InvocationHandler {
private final Object myService;
private final ClassLoader myClassLoader;
public TCCLSwitchingInvocationHandler(Object service) {
myService = service;
myClassLoader = service.getClass().getClassLoader();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Thread thread = Thread.currentThread();
ClassLoader ccl = thread.getContextClassLoader();
thread.setContextClassLoader(myClassLoader);
try {
return method.invoke(myService, args);
} catch (InvocationTargetException e) {
throw e.getCause();
} finally {
thread.setContextClassLoader(ccl);
}
}
}
public static T withThreadContextClassLoaderOf(@NotNull Object object, @NotNull CallableE code) throws E {
Thread thread = Thread.currentThread();
ClassLoader ccl = thread.getContextClassLoader();
thread.setContextClassLoader((object instanceof Class ? (Class)object : object.getClass()).getClassLoader());
try {
return code.call();
} finally {
thread.setContextClassLoader(ccl);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy