package jetbrains.mps.execution.impl.configurations; /*Generated by MPS */ import com.intellij.openapi.components.ProjectComponent; import jetbrains.mps.plugins.PluginReloadingListener; import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import com.intellij.openapi.project.Project; import jetbrains.mps.plugins.projectplugins.ProjectPluginManager; import java.util.List; import jetbrains.mps.plugins.PluginContributor; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.application.ApplicationManager; import java.util.Iterator; import jetbrains.mps.internal.collections.runtime.ListSequence; import com.intellij.ui.content.Content; import org.apache.log4j.Level; import com.intellij.openapi.application.ModalityState; import com.intellij.execution.ExecutionManager; import com.intellij.execution.ui.RunContentManagerImpl; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import com.intellij.execution.configurations.RunConfiguration; import jetbrains.mps.classloading.ModuleClassLoader; import jetbrains.mps.internal.collections.runtime.ISelector; import java.util.ArrayList; import com.intellij.execution.impl.RunManagerImpl; import com.intellij.execution.RunManagerEx; import com.intellij.execution.impl.ProjectRunConfigurationManager; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import com.intellij.execution.configurations.ConfigurationType; import com.intellij.openapi.extensions.Extensions; import java.util.Set; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.HashSet; import org.jdom.Element; /** * This component allows to create reloadable (!) run configurations within MPS. * It listens to the project plugins manager because we use custom project plugins to register custom 'before' tasks (like 'make' etc.) * It saves all run configurations at the plugin unload and then restores them at the plugin load event */ public class RunConfigurationsStateManager implements ProjectComponent, PluginReloadingListener { private static final Logger LOG = LogManager.getLogger(RunConfigurationsStateManager.class); private final Project myProject; private final ProjectPluginManager myProjectPluginManager; private RunConfigurationsStateManager.RunConfigurationsState myState = null; public RunConfigurationsStateManager(Project project, ProjectPluginManager pluginManager) { myProject = project; myProjectPluginManager = pluginManager; } @Override public void afterPluginsLoaded(List<PluginContributor> contributors) { initRunConfigurations(); } @Override public void beforePluginsUnloaded(List<PluginContributor> contributors) { disposeRunConfigurations(); } @Override public void initComponent() { myState = new RunConfigurationsStateManager.RunConfigurationsState(); myState.saveState(); myProjectPluginManager.addReloadingListener(this); } @Override public void disposeComponent() { myProjectPluginManager.removeReloadingListener(this); } @Override public void projectOpened() { } @Override public void projectClosed() { } public void initRunConfigurations() { if (myProject.isDisposed()) { return; } myState.restoreState(); } public void disposeRunConfigurations() { assert !(myProject.isDisposed()); myState.saveState(); disposeRunContentDescriptors(); clearAllRunConfigurations(); } private void disposeRunContentDescriptors() { final List<RunContentDescriptor> descriptors = collectDescriptorsToDispose(); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { { Iterator<RunContentDescriptor> descriptor_it = ListSequence.fromList(descriptors).iterator(); RunContentDescriptor descriptor_var; while (descriptor_it.hasNext()) { descriptor_var = descriptor_it.next(); Content attachedContent = descriptor_var.getAttachedContent(); if (attachedContent == null) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("Attached content of descriptor " + descriptor_var.getDisplayName() + " is null."); } } else if (attachedContent.getManager() == null) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("Manager of attached content of descriptor " + descriptor_var.getDisplayName() + " is null."); } } else { attachedContent.getManager().removeAllContents(true); } } } } }, ModalityState.NON_MODAL); } private void clearAllRunConfigurations() { getRunManager().clearAll(); } private List<RunContentDescriptor> collectDescriptorsToDispose() { ExecutionManager executionManager = ExecutionManager.getInstance(myProject); final RunContentManagerImpl contentManager = (RunContentManagerImpl) executionManager.getContentManager(); final List<String> reloadableConfigurationNames = Sequence.fromIterable(Sequence.fromArray(getRunManager().getAllConfigurations())).where(new IWhereFilter<RunConfiguration>() { public boolean accept(RunConfiguration it) { return it.getClass().getClassLoader() instanceof ModuleClassLoader; } }).select(new ISelector<RunConfiguration, String>() { public String select(RunConfiguration it) { return it.getName(); } }).toListSequence(); final List<RunContentDescriptor> descriptors = ListSequence.fromList(new ArrayList<RunContentDescriptor>()); { Iterator<RunContentDescriptor> descriptor_it = ListSequence.fromList(contentManager.getAllDescriptors()).iterator(); RunContentDescriptor descriptor_var; while (descriptor_it.hasNext()) { descriptor_var = descriptor_it.next(); if (ListSequence.fromList(reloadableConfigurationNames).contains(descriptor_var.getDisplayName())) { ListSequence.fromList(descriptors).addElement(descriptor_var); } } } return descriptors; } private RunManagerImpl getRunManager() { return (RunManagerImpl) RunManagerEx.getInstanceEx(myProject); } private ProjectRunConfigurationManager getSharedConfigurationManager() { return myProject.getComponent(ProjectRunConfigurationManager.class); } @NonNls @NotNull @Override public String getComponentName() { return "MPS Run Configs Manager"; } public static ConfigurationType[] getConfigurationTypes() { ConfigurationType[] configurationTypes = Extensions.getExtensions(ConfigurationType.CONFIGURATION_TYPE_EP); List<ConfigurationType> result = ListSequence.fromList(new ArrayList<ConfigurationType>()); Set<String> uniqTypes = SetSequence.fromSet(new HashSet<String>()); for (ConfigurationType type : configurationTypes) { String typeId = type.getClass().getName(); if (!(SetSequence.fromSet(uniqTypes).contains(typeId))) { ListSequence.fromList(result).addElement(type); SetSequence.fromSet(uniqTypes).addElement(typeId); } } return ListSequence.fromList(result).toGenericArray(ConfigurationType.class); } public static RunConfigurationsStateManager getInstance(Project project) { return project.getComponent(RunConfigurationsStateManager.class); } private class RunConfigurationsState { private Element myState; private Element mySharedState; public RunConfigurationsState() { } public void restoreState() { assert myState != null && mySharedState != null; getRunManager().initializeConfigurationTypes(RunConfigurationsStateManager.getConfigurationTypes()); try { getRunManager().loadState(myState); getSharedConfigurationManager().loadState(mySharedState); } catch (Exception e) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("Can't read execution configurations state", e); } } } public void saveState() { try { myState = getRunManager().getState(); mySharedState = getSharedConfigurationManager().getState(); } catch (Exception e) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("Can't save run configurations state", e); } } } } }