com.intellij.openapi.components.impl.ServiceManagerImpl Maven / Gradle / Ivy
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.components.impl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.BaseComponent;
import com.intellij.openapi.components.ComponentConfig;
import com.intellij.openapi.components.ComponentManager;
import com.intellij.openapi.components.ServiceDescriptor;
import com.intellij.openapi.components.ex.ComponentManagerEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.*;
import com.intellij.openapi.extensions.impl.ExtensionComponentAdapter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PairProcessor;
import com.intellij.util.PlatformUtils;
import com.intellij.util.io.storage.HeavyProcessLatch;
import com.intellij.util.pico.AssignableToComponentAdapter;
import com.intellij.util.pico.ConstructorInjectionComponentAdapter;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.picocontainer.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class ServiceManagerImpl implements BaseComponent {
private static final Logger LOG = Logger.getInstance(ServiceManagerImpl.class);
private static final ExtensionPointName APP_SERVICES = new ExtensionPointName("com.intellij.applicationService");
private static final ExtensionPointName PROJECT_SERVICES = new ExtensionPointName("com.intellij.projectService");
private ExtensionPointName myExtensionPointName;
private ExtensionPointListener myExtensionPointListener;
public ServiceManagerImpl() {
installEP(APP_SERVICES, ApplicationManager.getApplication());
}
public ServiceManagerImpl(Project project) {
installEP(PROJECT_SERVICES, project);
}
protected ServiceManagerImpl(boolean ignoreInit) {
}
protected void installEP(@NotNull ExtensionPointName pointName, @NotNull final ComponentManager componentManager) {
LOG.assertTrue(myExtensionPointName == null, "Already called installEP with " + myExtensionPointName);
myExtensionPointName = pointName;
final ExtensionPoint extensionPoint = Extensions.getArea(null).getExtensionPoint(pointName);
final MutablePicoContainer picoContainer = (MutablePicoContainer)componentManager.getPicoContainer();
myExtensionPointListener = new ExtensionPointListener() {
@Override
public void extensionAdded(@NotNull final ServiceDescriptor descriptor, final PluginDescriptor pluginDescriptor) {
if (descriptor.overrides) {
// Allow to re-define service implementations in plugins.
ComponentAdapter oldAdapter = picoContainer.unregisterComponent(descriptor.getInterface());
if (oldAdapter == null) {
throw new RuntimeException("Service: " + descriptor.getInterface() + " doesn't override anything");
}
}
// empty serviceImplementation means we want to unregister service
if (!StringUtil.isEmpty(descriptor.serviceImplementation)) {
picoContainer.registerComponent(new MyComponentAdapter(descriptor, pluginDescriptor, (ComponentManagerEx)componentManager));
}
}
@Override
public void extensionRemoved(@NotNull final ServiceDescriptor extension, final PluginDescriptor pluginDescriptor) {
picoContainer.unregisterComponent(extension.getInterface());
}
};
extensionPoint.addExtensionPointListener(myExtensionPointListener);
}
public List getAllDescriptors() {
ServiceDescriptor[] extensions = Extensions.getExtensions(myExtensionPointName);
return Arrays.asList(extensions);
}
public static void processAllImplementationClasses(@NotNull ComponentManagerImpl componentManager, @NotNull PairProcessor, PluginDescriptor> processor) {
Collection adapters = componentManager.getPicoContainer().getComponentAdapters();
if (adapters.isEmpty()) {
return;
}
for (Object o : adapters) {
Class aClass;
if (o instanceof MyComponentAdapter) {
MyComponentAdapter adapter = (MyComponentAdapter)o;
PluginDescriptor pluginDescriptor = adapter.myPluginDescriptor;
try {
ComponentAdapter delegate = adapter.myDelegate;
// avoid delegation creation & class initialization
if (delegate == null) {
ClassLoader classLoader = pluginDescriptor == null ? ServiceManagerImpl.class.getClassLoader() : pluginDescriptor.getPluginClassLoader();
aClass = Class.forName(adapter.myDescriptor.getImplementation(), false, classLoader);
}
else {
aClass = delegate.getComponentImplementation();
}
}
catch (Throwable e) {
if (PlatformUtils.isIdeaUltimate()) {
LOG.error(e);
}
else {
// well, component registered, but required jar is not added to classpath (community edition or junior IDE)
LOG.warn(e);
}
continue;
}
if (!processor.process(aClass, pluginDescriptor)) {
break;
}
}
else if (o instanceof ComponentAdapter && !(o instanceof ExtensionComponentAdapter)) {
try {
aClass = ((ComponentAdapter)o).getComponentImplementation();
}
catch (Throwable e) {
LOG.error(e);
continue;
}
ComponentConfig config = componentManager.getConfig(aClass);
if (config != null) {
processor.process(aClass, config.pluginDescriptor);
}
}
}
}
@Override
@NonNls
@NotNull
public String getComponentName() {
return getClass().getName();
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
final ExtensionPoint extensionPoint = Extensions.getArea(null).getExtensionPoint(myExtensionPointName);
extensionPoint.removeExtensionPointListener(myExtensionPointListener);
}
private static class MyComponentAdapter implements AssignableToComponentAdapter {
private ComponentAdapter myDelegate;
private final ServiceDescriptor myDescriptor;
private final PluginDescriptor myPluginDescriptor;
private final ComponentManagerEx myComponentManager;
private volatile Object myInitializedComponentInstance = null;
public MyComponentAdapter(final ServiceDescriptor descriptor, final PluginDescriptor pluginDescriptor, ComponentManagerEx componentManager) {
myDescriptor = descriptor;
myPluginDescriptor = pluginDescriptor;
myComponentManager = componentManager;
myDelegate = null;
}
@Override
public String getComponentKey() {
return myDescriptor.getInterface();
}
@Override
public Class getComponentImplementation() {
return loadClass(myDescriptor.getInterface());
}
private Class loadClass(final String className) {
try {
final ClassLoader classLoader = myPluginDescriptor != null ? myPluginDescriptor.getPluginClassLoader() : getClass().getClassLoader();
return Class.forName(className, true, classLoader);
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public Object getComponentInstance(final PicoContainer container) throws PicoInitializationException, PicoIntrospectionException {
Object instance = myInitializedComponentInstance;
if (instance != null) return instance;
return ApplicationManager.getApplication().runReadAction(new Computable
© 2015 - 2025 Weber Informatics LLC | Privacy Policy