mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
android - get rid of projectComponentsInitialized usage
GitOrigin-RevId: 775b972b3780a7d17785870df06332d8765a5add
This commit is contained in:
committed by
intellij-monorepo-bot
parent
64dd326ea7
commit
6778d1b884
@@ -10,7 +10,6 @@ import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.picocontainer.PicoContainer;
|
||||
|
||||
/**
|
||||
@@ -96,9 +95,6 @@ public interface ComponentManager extends UserDataHolder, Disposable, AreaInstan
|
||||
@NotNull
|
||||
Condition<?> getDisposed();
|
||||
|
||||
default void initializeComponent(@NotNull Object component, @Nullable ServiceDescriptor serviceDescriptor) {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
default <T> T getService(@NotNull Class<T> serviceClass, boolean isCreate) {
|
||||
// default impl to keep backward compatibility
|
||||
|
||||
@@ -40,6 +40,7 @@ public final class ServiceDescriptor {
|
||||
return serviceInterface != null ? serviceInterface : getImplementation();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getImplementation() {
|
||||
return testServiceImplementation != null && ApplicationManager.getApplication().isUnitTestMode() ? testServiceImplementation : serviceImplementation;
|
||||
}
|
||||
|
||||
@@ -2,24 +2,22 @@
|
||||
package com.intellij.util.messages.impl;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.diagnostic.ControlFlowException;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.lang.CompoundRuntimeException;
|
||||
import com.intellij.util.messages.ListenerDescriptor;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.messages.Topic;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@@ -60,7 +58,7 @@ public class MessageBusImpl implements MessageBus {
|
||||
private final RootBus myRootBus;
|
||||
|
||||
//is used for debugging purposes
|
||||
private final String myOwner;
|
||||
private final Object myOwner;
|
||||
private boolean myDisposed;
|
||||
private final Disposable myConnectionDisposable;
|
||||
private MessageDeliveryListener myMessageDeliveryListener;
|
||||
@@ -68,8 +66,8 @@ public class MessageBusImpl implements MessageBus {
|
||||
private final MessageBusConnectionImpl myLazyConnection;
|
||||
|
||||
public MessageBusImpl(@NotNull Object owner, @NotNull MessageBusImpl parentBus) {
|
||||
myOwner = owner + " of " + owner.getClass();
|
||||
myConnectionDisposable = Disposer.newDisposable(myOwner);
|
||||
myOwner = owner;
|
||||
myConnectionDisposable = Disposer.newDisposable(myOwner.toString());
|
||||
myParentBus = parentBus;
|
||||
myRootBus = parentBus.myRootBus;
|
||||
synchronized (parentBus.myChildBuses) {
|
||||
@@ -85,7 +83,7 @@ public class MessageBusImpl implements MessageBus {
|
||||
// root message bus constructor
|
||||
private MessageBusImpl(@NotNull Object owner) {
|
||||
myOwner = owner + " of " + owner.getClass();
|
||||
myConnectionDisposable = Disposer.newDisposable(myOwner);
|
||||
myConnectionDisposable = Disposer.newDisposable(myOwner.toString());
|
||||
myOrder = ArrayUtil.EMPTY_INT_ARRAY;
|
||||
myRootBus = (RootBus)this;
|
||||
myLazyConnection = connect();
|
||||
@@ -208,9 +206,29 @@ public class MessageBusImpl implements MessageBus {
|
||||
for (ListenerDescriptor listenerDescriptor : listenerDescriptors) {
|
||||
ClassLoader classLoader = listenerDescriptor.pluginDescriptor.getPluginClassLoader();
|
||||
try {
|
||||
listeners.add(ReflectionUtil.newInstance(Class.forName(listenerDescriptor.listenerClassName, true, classLoader), false));
|
||||
Class<?> aClass = Class.forName(listenerDescriptor.listenerClassName, true, classLoader);
|
||||
Constructor<?>[] constructors = aClass.getDeclaredConstructors();
|
||||
if (constructors.length > 1) {
|
||||
Arrays.sort(constructors, Comparator.comparingInt(Constructor::getParameterCount));
|
||||
}
|
||||
Constructor<?> constructor = constructors[0];
|
||||
constructor.setAccessible(true);
|
||||
if (constructor.getParameterCount() == 1) {
|
||||
listeners.add(constructor.newInstance(myOwner));
|
||||
}
|
||||
else {
|
||||
listeners.add(constructor.newInstance());
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
//noinspection InstanceofCatchParameter
|
||||
if (e instanceof InvocationTargetException) {
|
||||
Throwable targetException = ((InvocationTargetException)e).getTargetException();
|
||||
if (targetException instanceof ControlFlowException && targetException instanceof RuntimeException) {
|
||||
throw (RuntimeException)targetException;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.error("Cannot create listener", e);
|
||||
}
|
||||
}
|
||||
@@ -291,8 +309,9 @@ public class MessageBusImpl implements MessageBus {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@TestOnly
|
||||
String getOwner() {
|
||||
return myOwner;
|
||||
return myOwner.toString();
|
||||
}
|
||||
|
||||
private void calcSubscribers(@NotNull Topic<?> topic, @NotNull List<? super MessageBusConnectionImpl> result) {
|
||||
|
||||
@@ -400,8 +400,8 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor {
|
||||
private static ServiceDescriptor readServiceDescriptor(@NotNull Element element) {
|
||||
ServiceDescriptor descriptor = new ServiceDescriptor();
|
||||
descriptor.serviceInterface = element.getAttributeValue("serviceInterface");
|
||||
descriptor.serviceImplementation = element.getAttributeValue("serviceImplementation");
|
||||
descriptor.testServiceImplementation = element.getAttributeValue("testServiceImplementation");
|
||||
descriptor.serviceImplementation = StringUtil.nullize(element.getAttributeValue("serviceImplementation"));
|
||||
descriptor.testServiceImplementation = StringUtil.nullize(element.getAttributeValue("testServiceImplementation"));
|
||||
descriptor.configurationSchemaKey = element.getAttributeValue("configurationSchemaKey");
|
||||
descriptor.preload = Boolean.parseBoolean(element.getAttributeValue("preload"));
|
||||
descriptor.overrides = Boolean.parseBoolean(element.getAttributeValue("overrides"));
|
||||
|
||||
+8
-17
@@ -8,10 +8,7 @@ import com.intellij.ide.plugins.PluginManagerCore;
|
||||
import com.intellij.ide.plugins.cl.PluginClassLoader;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.components.BaseComponent;
|
||||
import com.intellij.openapi.components.ComponentConfig;
|
||||
import com.intellij.openapi.components.ComponentManager;
|
||||
import com.intellij.openapi.components.NamedComponent;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.extensions.PluginDescriptor;
|
||||
@@ -50,7 +47,7 @@ import java.util.Map;
|
||||
public abstract class ComponentManagerImpl extends UserDataHolderBase implements ComponentManager, Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.components.ComponentManager");
|
||||
|
||||
private final DefaultPicoContainer myPicoContainer;
|
||||
protected final DefaultPicoContainer myPicoContainer;
|
||||
private final ExtensionsAreaImpl myExtensionArea;
|
||||
|
||||
private volatile boolean myDisposed;
|
||||
@@ -68,15 +65,11 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
|
||||
private final List<BaseComponent> myBaseComponents = new SmartList<>();
|
||||
|
||||
private final ComponentManager myParent;
|
||||
protected final ComponentManager myParent;
|
||||
|
||||
protected ComponentManagerImpl(@Nullable ComponentManager parent) {
|
||||
this(parent, new DefaultPicoContainer(parent == null ? null : parent.getPicoContainer()));
|
||||
}
|
||||
|
||||
protected ComponentManagerImpl(@Nullable ComponentManager parent, @NotNull DefaultPicoContainer picoContainer) {
|
||||
myParent = parent;
|
||||
myPicoContainer = picoContainer;
|
||||
myPicoContainer = new DefaultPicoContainer(parent == null ? null : parent.getPicoContainer());
|
||||
myExtensionArea = new ExtensionsAreaImpl(myPicoContainer);
|
||||
if (parent == null) {
|
||||
Extensions.setRootArea(myExtensionArea);
|
||||
@@ -143,8 +136,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
|
||||
@NotNull
|
||||
private MessageBus createMessageBus() {
|
||||
String name = toString();
|
||||
MessageBus messageBus = MessageBusFactory.newMessageBus(name, getParentComponentManager() == null ? null : getParentComponentManager().getMessageBus());
|
||||
MessageBus messageBus = MessageBusFactory.newMessageBus(this, myParent == null ? null : myParent.getMessageBus());
|
||||
if (messageBus instanceof MessageBusImpl) {
|
||||
((MessageBusImpl) messageBus).setMessageDeliveryListener((topic, messageName, handler, duration) -> logMessageBusDelivery(topic, messageName, handler, duration));
|
||||
}
|
||||
@@ -329,10 +321,6 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
StartUpMeasurer.addPluginCost(pluginId, "MessageBus", durationNanos);
|
||||
}
|
||||
|
||||
protected final ComponentManager getParentComponentManager() {
|
||||
return myParent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ApiStatus.Internal
|
||||
public static PluginId getConfig(@NotNull ComponentAdapter adapter) {
|
||||
@@ -428,6 +416,9 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
return myNameToComponent.get(name);
|
||||
}
|
||||
|
||||
protected void initializeComponent(@NotNull Object component, @Nullable ServiceDescriptor serviceDescriptor) {
|
||||
}
|
||||
|
||||
protected final class ComponentConfigComponentAdapter extends CachingConstructorInjectionComponentAdapter {
|
||||
private final PluginId myPluginId;
|
||||
private volatile Object myInitializedComponentInstance;
|
||||
|
||||
+119
-39
@@ -1,44 +1,37 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.serviceContainer
|
||||
|
||||
import com.intellij.diagnostic.ActivitySubNames
|
||||
import com.intellij.diagnostic.LoadingPhase
|
||||
import com.intellij.diagnostic.ParallelActivity
|
||||
import com.intellij.diagnostic.run
|
||||
import com.intellij.diagnostic.*
|
||||
import com.intellij.ide.plugins.*
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.ComponentManager
|
||||
import com.intellij.openapi.components.PathMacroManager
|
||||
import com.intellij.openapi.components.ServiceDescriptor
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.components.impl.ComponentManagerImpl
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore
|
||||
import com.intellij.openapi.components.stateStore
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.util.ReflectionUtil
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch
|
||||
import com.intellij.util.messages.ListenerDescriptor
|
||||
import com.intellij.util.messages.MessageBusFactory
|
||||
import com.intellij.util.messages.impl.MessageBusImpl
|
||||
import com.intellij.util.pico.DefaultPicoContainer
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
private val LOG = logger<PlatformComponentManagerImpl>()
|
||||
|
||||
private fun createPicoContainer(parent: ComponentManager?): DefaultPicoContainer {
|
||||
return when (parent) {
|
||||
null -> ServiceContainer(null)
|
||||
else -> DefaultPicoContainer(parent.picoContainer)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : ComponentManagerImpl(parent, createPicoContainer(parent)) {
|
||||
abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : ComponentManagerImpl(parent) {
|
||||
private var handlingInitComponentError = false
|
||||
|
||||
private val lightServices: ConcurrentMap<Class<*>, Any>? = if (parent == null || parent.picoContainer.parent == null) ContainerUtil.newConcurrentMap() else null
|
||||
|
||||
private val componentStore: IComponentStore
|
||||
get() = this.stateStore
|
||||
|
||||
@@ -72,7 +65,7 @@ abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : Compone
|
||||
}
|
||||
}
|
||||
|
||||
ServiceManagerImpl.registerServices(containerDescriptor.services, plugin, this)
|
||||
registerServices(containerDescriptor.services, plugin)
|
||||
|
||||
val listeners = containerDescriptor.listeners
|
||||
if (listeners.isNotEmpty()) {
|
||||
@@ -106,6 +99,22 @@ abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : Compone
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerServices(services: List<ServiceDescriptor>, pluginDescriptor: IdeaPluginDescriptor) {
|
||||
val picoContainer = myPicoContainer
|
||||
for (descriptor in services) {
|
||||
// Allow to re-define service implementations in plugins.
|
||||
// Empty serviceImplementation means we want to unregister service.
|
||||
if (descriptor.overrides && picoContainer.unregisterComponent(descriptor.getInterface()) == null) {
|
||||
throw PluginException("Service: ${descriptor.getInterface()} doesn't override anything", pluginDescriptor.pluginId)
|
||||
}
|
||||
|
||||
// empty serviceImplementation means we want to unregister service
|
||||
if (descriptor.implementation != null) {
|
||||
picoContainer.registerComponent(ServiceManagerImpl.createServiceAdapter(descriptor, pluginDescriptor, this))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final override fun handleInitComponentError(t: Throwable, componentClassName: String, pluginId: PluginId) {
|
||||
if (handlingInitComponentError) {
|
||||
return
|
||||
@@ -129,27 +138,41 @@ abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : Compone
|
||||
|
||||
protected abstract fun getContainerDescriptor(pluginDescriptor: IdeaPluginDescriptorImpl): ContainerDescriptor
|
||||
|
||||
@ApiStatus.Internal
|
||||
final override fun <T> getService(serviceClass: Class<T>, isCreate: Boolean): T? {
|
||||
val componentKey = serviceClass.name
|
||||
var instance = picoContainer.getService(serviceClass, isCreate)
|
||||
if (instance == null && isCreate) {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
if (parentComponentManager != null) {
|
||||
instance = parentComponentManager.getService(serviceClass, isCreate)
|
||||
if (instance != null) {
|
||||
LOG.error("$componentKey is registered as application service, but requested as project one")
|
||||
return instance
|
||||
final override fun <T : Any> getService(serviceClass: Class<T>, isCreate: Boolean): T? {
|
||||
val lightServices = lightServices
|
||||
if (lightServices != null && isLightService(serviceClass)) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val result = lightServices.get(serviceClass) as T?
|
||||
if (result != null || !isCreate) {
|
||||
return result
|
||||
}
|
||||
else {
|
||||
synchronized(serviceClass) {
|
||||
return getOrCreateLightService(serviceClass, lightServices)
|
||||
}
|
||||
}
|
||||
|
||||
instance = getComponent(serviceClass) ?: return null
|
||||
LOG.error("$componentKey requested as a service, but it is a component - convert it to a service or " +
|
||||
"change call to ${if (parentComponentManager == null) "ApplicationManager.getApplication().getComponent()" else "project.getComponent()"}")
|
||||
return instance
|
||||
}
|
||||
return instance
|
||||
|
||||
val componentKey = serviceClass.name
|
||||
var result = picoContainer.getService(serviceClass, isCreate)
|
||||
if (result != null || !isCreate) {
|
||||
return result
|
||||
}
|
||||
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
if (myParent != null) {
|
||||
result = myParent.getService(serviceClass, isCreate)
|
||||
if (result != null) {
|
||||
LOG.error("$componentKey is registered as application service, but requested as project one")
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
result = getComponent(serviceClass) ?: return null
|
||||
LOG.error("$componentKey requested as a service, but it is a component - convert it to a service or " +
|
||||
"change call to ${if (myParent == null) "ApplicationManager.getApplication().getComponent()" else "project.getComponent()"}")
|
||||
return result
|
||||
}
|
||||
|
||||
final override fun getServiceImplementationClassNames(prefix: String): MutableList<String> {
|
||||
@@ -163,6 +186,31 @@ abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : Compone
|
||||
return result
|
||||
}
|
||||
|
||||
private fun <T : Any> getOrCreateLightService(serviceClass: Class<T>, cache: ConcurrentMap<Class<*>, Any>): T {
|
||||
LoadingPhase.COMPONENT_REGISTERED.assertAtLeast()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
var result = cache.get(serviceClass) as T?
|
||||
if (result != null) {
|
||||
return result
|
||||
}
|
||||
|
||||
HeavyProcessLatch.INSTANCE.processStarted("Creating service '${serviceClass.name}'").use {
|
||||
if (ProgressIndicatorProvider.getGlobalProgressIndicator() == null) {
|
||||
result = createLightService(serviceClass)
|
||||
}
|
||||
else {
|
||||
ProgressManager.getInstance().executeNonCancelableSection {
|
||||
result = createLightService(serviceClass)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val prevValue = cache.put(serviceClass, result)
|
||||
LOG.assertTrue(prevValue == null)
|
||||
return result!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Use only if approved by core team.
|
||||
*/
|
||||
@@ -170,7 +218,7 @@ abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : Compone
|
||||
fun registerComponent(key: Class<*>, implementation: Class<*>, pluginId: PluginId, override: Boolean) {
|
||||
val picoContainer = picoContainer
|
||||
if (override && picoContainer.unregisterComponent(key) == null) {
|
||||
throw IllegalStateException("Component $key must be already registered")
|
||||
throw PluginException("Component $key doesn't override anything", pluginId)
|
||||
}
|
||||
picoContainer.registerComponent(ComponentConfigComponentAdapter(key, implementation, pluginId, false))
|
||||
}
|
||||
@@ -183,7 +231,7 @@ abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : Compone
|
||||
val picoContainer = picoContainer
|
||||
val serviceKey = serviceClass.name
|
||||
if (override && picoContainer.unregisterComponent(serviceKey) == null) {
|
||||
throw IllegalStateException("Service $serviceKey must be already registered")
|
||||
throw PluginException("Service $serviceKey doesn't override anything", pluginDescriptor.pluginId)
|
||||
}
|
||||
|
||||
val descriptor = ServiceDescriptor()
|
||||
@@ -191,4 +239,36 @@ abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : Compone
|
||||
descriptor.serviceImplementation = implementation.name
|
||||
picoContainer.registerComponent(ServiceManagerImpl.createServiceAdapter(descriptor, pluginDescriptor, this))
|
||||
}
|
||||
|
||||
private fun <T : Any> createLightService(serviceClass: Class<T>): T {
|
||||
val startTime = StartUpMeasurer.getCurrentTime()
|
||||
|
||||
val result: T
|
||||
if (myParent == null) {
|
||||
result = ReflectionUtil.newInstance(serviceClass, false)
|
||||
}
|
||||
else {
|
||||
val constructors = serviceClass.declaredConstructors
|
||||
constructors.sortBy { it.parameterCount }
|
||||
val constructor = constructors.first()
|
||||
constructor.isAccessible = true
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
result = when (constructor.parameterCount) {
|
||||
1 -> constructor.newInstance(this)
|
||||
else -> constructor.newInstance()
|
||||
} as T
|
||||
}
|
||||
|
||||
if (result is Disposable) {
|
||||
Disposer.register(this, result)
|
||||
}
|
||||
|
||||
initializeComponent(result, null)
|
||||
ParallelActivity.SERVICE.record(startTime, result.javaClass, StartUpMeasurer.Level.APPLICATION)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> isLightService(serviceClass: Class<T>): Boolean {
|
||||
return Modifier.isFinal(serviceClass.modifiers) && serviceClass.isAnnotationPresent(Service::class.java)
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.serviceContainer
|
||||
|
||||
import com.intellij.diagnostic.LoadingPhase
|
||||
import com.intellij.diagnostic.ParallelActivity
|
||||
import com.intellij.diagnostic.StartUpMeasurer
|
||||
import com.intellij.diagnostic.StartUpMeasurer.Level
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.ComponentManager
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.util.ReflectionUtil
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch
|
||||
import com.intellij.util.pico.DefaultPicoContainer
|
||||
import org.picocontainer.PicoContainer
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
private val LOG = logger<ServiceManager>()
|
||||
|
||||
// used only for Application for now
|
||||
internal class ServiceContainer(parent: PicoContainer?) : DefaultPicoContainer(parent) {
|
||||
private val lightServices: ConcurrentMap<Class<*>, Any>? = if (parent == null) ContainerUtil.newConcurrentMap() else null
|
||||
|
||||
override fun <T : Any> getService(serviceClass: Class<T>, isCreate: Boolean): T? {
|
||||
val lightServices = lightServices
|
||||
if (lightServices == null || !isLightService(serviceClass)) {
|
||||
return super.getService(serviceClass, isCreate)
|
||||
}
|
||||
else {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val result = lightServices.get(serviceClass) as T?
|
||||
if (result != null || !isCreate) {
|
||||
return result
|
||||
}
|
||||
else {
|
||||
synchronized(serviceClass) {
|
||||
return getOrCreateLightService(serviceClass, lightServices)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Any> getOrCreateLightService(serviceClass: Class<T>, cache: ConcurrentMap<Class<*>, Any>): T {
|
||||
LoadingPhase.COMPONENT_REGISTERED.assertAtLeast()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
var instance = cache.get(serviceClass) as T?
|
||||
if (instance != null) {
|
||||
return instance
|
||||
}
|
||||
|
||||
val componentManager = ApplicationManager.getApplication()
|
||||
HeavyProcessLatch.INSTANCE.processStarted("Creating service '${serviceClass.name}'").use {
|
||||
if (ProgressIndicatorProvider.getGlobalProgressIndicator() == null) {
|
||||
instance = createLightService(serviceClass, componentManager)
|
||||
}
|
||||
else {
|
||||
ProgressManager.getInstance().executeNonCancelableSection {
|
||||
instance = createLightService(serviceClass, componentManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val prevValue = cache.put(serviceClass, instance)
|
||||
LOG.assertTrue(prevValue == null)
|
||||
return instance!!
|
||||
}
|
||||
|
||||
private fun <T : Any> createLightService(serviceClass: Class<T>, componentManager: ComponentManager): T {
|
||||
val startTime = StartUpMeasurer.getCurrentTime()
|
||||
val instance = ReflectionUtil.newInstance(serviceClass, false)
|
||||
if (instance is Disposable) {
|
||||
Disposer.register(componentManager, instance as Disposable)
|
||||
}
|
||||
componentManager.initializeComponent(instance, null)
|
||||
ParallelActivity.SERVICE.record(startTime, instance.javaClass, Level.APPLICATION)
|
||||
return instance
|
||||
}
|
||||
|
||||
private fun <T> isLightService(serviceClass: Class<T>): Boolean {
|
||||
return Modifier.isFinal(serviceClass.modifiers) && serviceClass.isAnnotationPresent(Service::class.java)
|
||||
}
|
||||
+3
-27
@@ -25,7 +25,6 @@ import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
import com.intellij.util.pico.AssignableToComponentAdapter;
|
||||
@@ -37,7 +36,6 @@ import org.picocontainer.*;
|
||||
import org.picocontainer.defaults.InstanceComponentAdapter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
@@ -45,32 +43,10 @@ import java.util.function.Consumer;
|
||||
public final class ServiceManagerImpl implements Disposable {
|
||||
private static final Logger LOG = Logger.getInstance(ServiceManagerImpl.class);
|
||||
|
||||
static void registerServices(@NotNull List<ServiceDescriptor> services,
|
||||
@NotNull IdeaPluginDescriptor pluginDescriptor,
|
||||
@NotNull ComponentManager componentManager) {
|
||||
MutablePicoContainer picoContainer = (MutablePicoContainer)componentManager.getPicoContainer();
|
||||
for (ServiceDescriptor descriptor : services) {
|
||||
// Allow to re-define service implementations in plugins.
|
||||
// empty serviceImplementation means we want to unregister service
|
||||
if (descriptor.overrides) {
|
||||
// Allow to re-define service implementations in plugins.
|
||||
ComponentAdapter oldAdapter = picoContainer.unregisterComponent(descriptor.getInterface());
|
||||
if (oldAdapter == null) {
|
||||
throw new PluginException("Service: " + descriptor.getInterface() + " doesn't override anything", pluginDescriptor.getPluginId());
|
||||
}
|
||||
}
|
||||
|
||||
// empty serviceImplementation means we want to unregister service
|
||||
if (!StringUtil.isEmpty(descriptor.getImplementation())) {
|
||||
picoContainer.registerComponent(createServiceAdapter(descriptor, pluginDescriptor, componentManager));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static ComponentAdapter createServiceAdapter(@NotNull ServiceDescriptor descriptor,
|
||||
@NotNull IdeaPluginDescriptor pluginDescriptor,
|
||||
@NotNull ComponentManager componentManager) {
|
||||
@NotNull PlatformComponentManagerImpl componentManager) {
|
||||
return new MyComponentAdapter(descriptor, pluginDescriptor, componentManager);
|
||||
}
|
||||
|
||||
@@ -169,10 +145,10 @@ public final class ServiceManagerImpl implements Disposable {
|
||||
private ComponentAdapter myDelegate;
|
||||
private final PluginDescriptor myPluginDescriptor;
|
||||
private final ServiceDescriptor myDescriptor;
|
||||
private final ComponentManager myComponentManager;
|
||||
private final PlatformComponentManagerImpl myComponentManager;
|
||||
private volatile Object myInitializedComponentInstance;
|
||||
|
||||
MyComponentAdapter(@NotNull ServiceDescriptor descriptor, @NotNull PluginDescriptor pluginDescriptor, @NotNull ComponentManager componentManager) {
|
||||
MyComponentAdapter(@NotNull ServiceDescriptor descriptor, @NotNull PluginDescriptor pluginDescriptor, @NotNull PlatformComponentManagerImpl componentManager) {
|
||||
myDescriptor = descriptor;
|
||||
myPluginDescriptor = pluginDescriptor;
|
||||
myComponentManager = componentManager;
|
||||
|
||||
Reference in New Issue
Block a user