| /* |
| * Copyright 2000-2013 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.execution.impl; |
| |
| import com.intellij.execution.*; |
| import com.intellij.execution.configurations.*; |
| import com.intellij.execution.runners.ProgramRunner; |
| import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.extensions.ExtensionException; |
| import com.intellij.openapi.util.Factory; |
| import com.intellij.openapi.util.InvalidDataException; |
| import com.intellij.openapi.util.JDOMExternalizable; |
| import com.intellij.openapi.util.WriteExternalException; |
| import com.intellij.openapi.util.text.StringUtil; |
| import org.jdom.Element; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.*; |
| |
| /** |
| * @author dyoma |
| */ |
| public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, Cloneable, RunnerAndConfigurationSettings, Comparable { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.execution.impl.RunnerAndConfigurationSettings"); |
| |
| @NonNls |
| private static final String RUNNER_ELEMENT = "RunnerSettings"; |
| @NonNls |
| private static final String CONFIGURATION_ELEMENT = "ConfigurationWrapper"; |
| @NonNls |
| private static final String RUNNER_ID = "RunnerId"; |
| @NonNls |
| private static final String CONFIGURATION_TYPE_ATTRIBUTE = "type"; |
| @NonNls |
| private static final String FACTORY_NAME_ATTRIBUTE = "factoryName"; |
| @NonNls |
| private static final String FOLDER_NAME = "folderName"; |
| @NonNls |
| private static final String TEMPLATE_FLAG_ATTRIBUTE = "default"; |
| @NonNls |
| public static final String NAME_ATTR = "name"; |
| //@NonNls |
| //public static final String UNIQUE_ID = "id"; |
| @NonNls |
| protected static final String DUMMY_ELEMENT_NANE = "dummy"; |
| @NonNls |
| private static final String TEMPORARY_ATTRIBUTE = "temporary"; |
| @NonNls |
| private static final String EDIT_BEFORE_RUN = "editBeforeRun"; |
| @NonNls |
| public static final String SINGLETON = "singleton"; |
| |
| |
| /** for compatibility */ |
| @NonNls |
| private static final String TEMP_CONFIGURATION = "tempConfiguration"; |
| |
| private final RunManagerImpl myManager; |
| private RunConfiguration myConfiguration; |
| private boolean myIsTemplate; |
| |
| private final Map<ProgramRunner, RunnerSettings> myRunnerSettings = new HashMap<ProgramRunner, RunnerSettings>(); |
| private List<Element> myUnloadedRunnerSettings = null; |
| |
| private final Map<ProgramRunner, ConfigurationPerRunnerSettings> myConfigurationPerRunnerSettings = new HashMap<ProgramRunner, ConfigurationPerRunnerSettings>(); |
| private List<Element> myUnloadedConfigurationPerRunnerSettings = null; |
| |
| private boolean myTemporary; |
| private boolean myEditBeforeRun; |
| private boolean mySingleton; |
| private boolean myWasSingletonSpecifiedExplicitly; |
| private String myFolderName; |
| //private String myID = null; |
| |
| public RunnerAndConfigurationSettingsImpl(RunManagerImpl manager) { |
| myManager = manager; |
| } |
| |
| public RunnerAndConfigurationSettingsImpl(RunManagerImpl manager, @NotNull RunConfiguration configuration, boolean isTemplate) { |
| myManager = manager; |
| myConfiguration = configuration; |
| myIsTemplate = isTemplate; |
| } |
| |
| @Override |
| @Nullable |
| public ConfigurationFactory getFactory() { |
| return myConfiguration == null ? null : myConfiguration.getFactory(); |
| } |
| |
| @Override |
| public boolean isTemplate() { |
| return myIsTemplate; |
| } |
| |
| @Override |
| public boolean isTemporary() { |
| return myTemporary; |
| } |
| |
| @Override |
| public void setTemporary(boolean temporary) { |
| myTemporary = temporary; |
| } |
| |
| @Override |
| public RunConfiguration getConfiguration() { |
| return myConfiguration; |
| } |
| |
| @Override |
| public Factory<RunnerAndConfigurationSettings> createFactory() { |
| return new Factory<RunnerAndConfigurationSettings>() { |
| @Override |
| public RunnerAndConfigurationSettings create() { |
| RunConfiguration configuration = myConfiguration.getFactory().createConfiguration(ExecutionBundle.message("default.run.configuration.name"), myConfiguration); |
| return new RunnerAndConfigurationSettingsImpl(myManager, configuration, false); |
| } |
| }; |
| } |
| |
| @Override |
| public void setName(String name) { |
| myConfiguration.setName(name); |
| } |
| |
| @Override |
| public String getName() { |
| return myConfiguration.getName(); |
| } |
| |
| @Override |
| public String getUniqueID() { |
| return myConfiguration.getType().getDisplayName() + "." + myConfiguration.getName() + |
| (myConfiguration instanceof UnknownRunConfiguration ? myConfiguration.getUniqueID() : ""); |
| //if (myID == null) { |
| // myID = UUID.randomUUID().toString(); |
| //} |
| //return myID; |
| } |
| |
| @Override |
| public void setEditBeforeRun(boolean b) { |
| myEditBeforeRun = b; |
| } |
| |
| @Override |
| public boolean isEditBeforeRun() { |
| return myEditBeforeRun; |
| } |
| |
| @Override |
| public void setSingleton(boolean singleton) { |
| mySingleton = singleton; |
| } |
| |
| @Override |
| public boolean isSingleton() { |
| return mySingleton; |
| } |
| |
| @Override |
| public void setFolderName(@Nullable String folderName) { |
| myFolderName = folderName; |
| } |
| |
| @Nullable |
| @Override |
| public String getFolderName() { |
| return myFolderName; |
| } |
| |
| @Nullable |
| private ConfigurationFactory getFactory(final Element element) { |
| final String typeName = element.getAttributeValue(CONFIGURATION_TYPE_ATTRIBUTE); |
| String factoryName = element.getAttributeValue(FACTORY_NAME_ATTRIBUTE); |
| return myManager.getFactory(typeName, factoryName, !myIsTemplate); |
| } |
| |
| @Override |
| public void readExternal(Element element) throws InvalidDataException { |
| myIsTemplate = Boolean.valueOf(element.getAttributeValue(TEMPLATE_FLAG_ATTRIBUTE)).booleanValue(); |
| myTemporary = Boolean.valueOf(element.getAttributeValue(TEMPORARY_ATTRIBUTE)).booleanValue() || TEMP_CONFIGURATION.equals(element.getName()); |
| myEditBeforeRun = Boolean.valueOf(element.getAttributeValue(EDIT_BEFORE_RUN)).booleanValue(); |
| myFolderName = element.getAttributeValue(FOLDER_NAME); |
| //assert myID == null: "myId must be null at readExternal() stage"; |
| //myID = element.getAttributeValue(UNIQUE_ID, UUID.randomUUID().toString()); |
| final ConfigurationFactory factory = getFactory(element); |
| if (factory == null) return; |
| |
| myWasSingletonSpecifiedExplicitly = false; |
| if (myIsTemplate) { |
| mySingleton = factory.isConfigurationSingletonByDefault(); |
| } |
| else { |
| String singletonStr = element.getAttributeValue(SINGLETON); |
| if (StringUtil.isEmpty(singletonStr)) { |
| mySingleton = factory.isConfigurationSingletonByDefault(); |
| } |
| else { |
| myWasSingletonSpecifiedExplicitly = true; |
| mySingleton = Boolean.parseBoolean(singletonStr); |
| } |
| } |
| |
| if (myIsTemplate) { |
| myConfiguration = myManager.getConfigurationTemplate(factory).getConfiguration(); |
| } else { |
| final String name = element.getAttributeValue(NAME_ATTR); |
| // shouldn't call createConfiguration since it calls StepBeforeRunProviders that |
| // may not be loaded yet. This creates initialization order issue. |
| myConfiguration = myManager.doCreateConfiguration(name, factory, false); |
| } |
| |
| myConfiguration.readExternal(element); |
| List<Element> runners = element.getChildren(RUNNER_ELEMENT); |
| myUnloadedRunnerSettings = null; |
| for (final Element runnerElement : runners) { |
| String id = runnerElement.getAttributeValue(RUNNER_ID); |
| ProgramRunner runner = RunnerRegistry.getInstance().findRunnerById(id); |
| if (runner != null) { |
| RunnerSettings settings = createRunnerSettings(runner); |
| if (settings != null) { |
| settings.readExternal(runnerElement); |
| } |
| myRunnerSettings.put(runner, settings); |
| } |
| else { |
| if (myUnloadedRunnerSettings == null) myUnloadedRunnerSettings = new ArrayList<Element>(1); |
| IdeaPluginDescriptorImpl.internJDOMElement(runnerElement); |
| myUnloadedRunnerSettings.add(runnerElement); |
| } |
| } |
| |
| List configurations = element.getChildren(CONFIGURATION_ELEMENT); |
| myUnloadedConfigurationPerRunnerSettings = null; |
| for (final Object configuration : configurations) { |
| Element configurationElement = (Element) configuration; |
| String id = configurationElement.getAttributeValue(RUNNER_ID); |
| ProgramRunner runner = RunnerRegistry.getInstance().findRunnerById(id); |
| if (runner != null) { |
| ConfigurationPerRunnerSettings settings = myConfiguration.createRunnerSettings(new InfoProvider(runner)); |
| if (settings != null) { |
| settings.readExternal(configurationElement); |
| } |
| myConfigurationPerRunnerSettings.put(runner, settings); |
| } else { |
| if (myUnloadedConfigurationPerRunnerSettings == null) |
| myUnloadedConfigurationPerRunnerSettings = new ArrayList<Element>(1); |
| myUnloadedConfigurationPerRunnerSettings.add(configurationElement); |
| } |
| } |
| } |
| |
| @Override |
| public void writeExternal(final Element element) throws WriteExternalException { |
| final ConfigurationFactory factory = myConfiguration.getFactory(); |
| |
| if (!(myConfiguration instanceof UnknownRunConfiguration)) { |
| element.setAttribute(TEMPLATE_FLAG_ATTRIBUTE, String.valueOf(myIsTemplate)); |
| if (!myIsTemplate) { |
| element.setAttribute(NAME_ATTR, myConfiguration.getName()); |
| } |
| element.setAttribute(CONFIGURATION_TYPE_ATTRIBUTE, factory.getType().getId()); |
| element.setAttribute(FACTORY_NAME_ATTRIBUTE, factory.getName()); |
| if (myFolderName != null) { |
| element.setAttribute(FOLDER_NAME, myFolderName); |
| } |
| //element.setAttribute(UNIQUE_ID, getUniqueID()); |
| |
| if (isEditBeforeRun()) element.setAttribute(EDIT_BEFORE_RUN, String.valueOf(true)); |
| if (myWasSingletonSpecifiedExplicitly || mySingleton != factory.isConfigurationSingletonByDefault()) { |
| element.setAttribute(SINGLETON, String.valueOf(mySingleton)); |
| } |
| if (myTemporary) { |
| element.setAttribute(TEMPORARY_ATTRIBUTE, Boolean.toString(myTemporary)); |
| } |
| } |
| |
| myConfiguration.writeExternal(element); |
| |
| if (!(myConfiguration instanceof UnknownRunConfiguration)) { |
| final Comparator<Element> runnerComparator = createRunnerComparator(); |
| writeRunnerSettings(runnerComparator, element); |
| writeConfigurationPerRunnerSettings(runnerComparator, element); |
| } |
| } |
| |
| private void writeConfigurationPerRunnerSettings(final Comparator<Element> runnerComparator, final Element element) |
| throws WriteExternalException { |
| final ArrayList<Element> configurationPerRunnerSettings = new ArrayList<Element>(); |
| for (ProgramRunner runner : myConfigurationPerRunnerSettings.keySet()) { |
| ConfigurationPerRunnerSettings settings = myConfigurationPerRunnerSettings.get(runner); |
| Element runnerElement = new Element(CONFIGURATION_ELEMENT); |
| if (settings != null) { |
| settings.writeExternal(runnerElement); |
| } |
| runnerElement.setAttribute(RUNNER_ID, runner.getRunnerId()); |
| configurationPerRunnerSettings.add(runnerElement); |
| } |
| if (myUnloadedConfigurationPerRunnerSettings != null) { |
| for (Element unloadedCRunnerSetting : myUnloadedConfigurationPerRunnerSettings) { |
| configurationPerRunnerSettings.add(unloadedCRunnerSetting.clone()); |
| } |
| } |
| Collections.sort(configurationPerRunnerSettings, runnerComparator); |
| for (Element runnerConfigurationSetting : configurationPerRunnerSettings) { |
| element.addContent(runnerConfigurationSetting); |
| } |
| } |
| |
| private void writeRunnerSettings(final Comparator<Element> runnerComparator, final Element element) throws WriteExternalException { |
| final ArrayList<Element> runnerSettings = new ArrayList<Element>(); |
| for (ProgramRunner runner : myRunnerSettings.keySet()) { |
| RunnerSettings settings = myRunnerSettings.get(runner); |
| Element runnerElement = new Element(RUNNER_ELEMENT); |
| if (settings != null) { |
| settings.writeExternal(runnerElement); |
| } |
| runnerElement.setAttribute(RUNNER_ID, runner.getRunnerId()); |
| runnerSettings.add(runnerElement); |
| } |
| if (myUnloadedRunnerSettings != null) { |
| for (Element unloadedRunnerSetting : myUnloadedRunnerSettings) { |
| runnerSettings.add(unloadedRunnerSetting.clone()); |
| } |
| } |
| Collections.sort(runnerSettings, runnerComparator); |
| for (Element runnerSetting : runnerSettings) { |
| element.addContent(runnerSetting); |
| } |
| } |
| |
| @Override |
| public void checkSettings() throws RuntimeConfigurationException { |
| checkSettings(null); |
| } |
| |
| @Override |
| public void checkSettings(@Nullable Executor executor) throws RuntimeConfigurationException { |
| myConfiguration.checkConfiguration(); |
| if (myConfiguration instanceof RunConfigurationBase) { |
| final RunConfigurationBase runConfigurationBase = (RunConfigurationBase) myConfiguration; |
| Set<ProgramRunner> runners = new HashSet<ProgramRunner>(); |
| runners.addAll(myRunnerSettings.keySet()); |
| runners.addAll(myConfigurationPerRunnerSettings.keySet()); |
| for (ProgramRunner runner : runners) { |
| if (executor == null || runner.canRun(executor.getId(), myConfiguration)) { |
| runConfigurationBase.checkRunnerSettings(runner, myRunnerSettings.get(runner), myConfigurationPerRunnerSettings.get(runner)); |
| } |
| } |
| if (executor != null) { |
| runConfigurationBase.checkSettingsBeforeRun(); |
| } |
| } |
| } |
| |
| @Override |
| public boolean canRunOn(@NotNull ExecutionTarget target) { |
| if (myConfiguration instanceof TargetAwareRunProfile) { |
| return ((TargetAwareRunProfile)myConfiguration).canRunOn(target); |
| } |
| return true; |
| } |
| |
| private static Comparator<Element> createRunnerComparator() { |
| return new Comparator<Element>() { |
| @Override |
| public int compare(final Element o1, final Element o2) { |
| final String attributeValue1 = o1.getAttributeValue(RUNNER_ID); |
| if (attributeValue1 == null) { |
| return 1; |
| |
| } |
| final String attributeValue2 = o2.getAttributeValue(RUNNER_ID); |
| if (attributeValue2 == null) { |
| return -1; |
| } |
| return attributeValue1.compareTo(attributeValue2); |
| } |
| }; |
| } |
| |
| @Override |
| public RunnerSettings getRunnerSettings(@NotNull ProgramRunner runner) { |
| if (!myRunnerSettings.containsKey(runner)) { |
| try { |
| RunnerSettings runnerSettings = createRunnerSettings(runner); |
| myRunnerSettings.put(runner, runnerSettings); |
| return runnerSettings; |
| } |
| catch (AbstractMethodError e) { |
| LOG.error("Update failed for: " + myConfiguration.getType().getDisplayName() + ", runner: " + runner.getRunnerId(), new ExtensionException(runner.getClass())); |
| } |
| } |
| return myRunnerSettings.get(runner); |
| } |
| |
| @Override |
| @Nullable |
| public ConfigurationPerRunnerSettings getConfigurationSettings(@NotNull ProgramRunner runner) { |
| if (!myConfigurationPerRunnerSettings.containsKey(runner)) { |
| ConfigurationPerRunnerSettings settings = myConfiguration.createRunnerSettings(new InfoProvider(runner)); |
| myConfigurationPerRunnerSettings.put(runner, settings); |
| return settings; |
| } |
| return myConfigurationPerRunnerSettings.get(runner); |
| } |
| |
| @Override |
| @Nullable |
| public ConfigurationType getType() { |
| return myConfiguration == null ? null : myConfiguration.getType(); |
| } |
| |
| @Override |
| public RunnerAndConfigurationSettings clone() { |
| RunnerAndConfigurationSettingsImpl copy = new RunnerAndConfigurationSettingsImpl(myManager, myConfiguration.clone(), false); |
| copy.importRunnerAndConfigurationSettings(this); |
| return copy; |
| } |
| |
| public void importRunnerAndConfigurationSettings(RunnerAndConfigurationSettingsImpl template) { |
| try { |
| for (ProgramRunner runner : template.myRunnerSettings.keySet()) { |
| RunnerSettings data = createRunnerSettings(runner); |
| myRunnerSettings.put(runner, data); |
| if (data != null) { |
| Element temp = new Element(DUMMY_ELEMENT_NANE); |
| RunnerSettings templateSettings = template.myRunnerSettings.get(runner); |
| if (templateSettings != null) { |
| templateSettings.writeExternal(temp); |
| data.readExternal(temp); |
| } |
| } |
| } |
| |
| for (ProgramRunner runner : template.myConfigurationPerRunnerSettings.keySet()) { |
| ConfigurationPerRunnerSettings data = myConfiguration.createRunnerSettings(new InfoProvider(runner)); |
| myConfigurationPerRunnerSettings.put(runner, data); |
| if (data != null) { |
| Element temp = new Element(DUMMY_ELEMENT_NANE); |
| ConfigurationPerRunnerSettings templateSettings = template.myConfigurationPerRunnerSettings.get(runner); |
| if (templateSettings != null) { |
| templateSettings.writeExternal(temp); |
| data.readExternal(temp); |
| } |
| } |
| } |
| setSingleton(template.isSingleton()); |
| setEditBeforeRun(template.isEditBeforeRun()); |
| } |
| catch (WriteExternalException e) { |
| LOG.error(e); |
| } |
| catch (InvalidDataException e) { |
| LOG.error(e); |
| } |
| } |
| |
| private RunnerSettings createRunnerSettings(final ProgramRunner runner) { |
| return runner.createConfigurationData(new InfoProvider(runner)); |
| } |
| |
| @Override |
| public int compareTo(final Object o) { |
| if (o instanceof RunnerAndConfigurationSettings) { |
| return getName().compareTo(((RunnerAndConfigurationSettings) o).getName()); |
| } |
| return 0; |
| } |
| |
| @Override |
| public String toString() { |
| ConfigurationType type = getType(); |
| return (type != null ? type.getDisplayName() + ": " : "") + (isTemplate() ? "<template>" : getName()); |
| } |
| |
| private class InfoProvider implements ConfigurationInfoProvider { |
| private final ProgramRunner myRunner; |
| |
| public InfoProvider(ProgramRunner runner) { |
| myRunner = runner; |
| } |
| |
| @Override |
| public ProgramRunner getRunner() { |
| return myRunner; |
| } |
| |
| @Override |
| public RunConfiguration getConfiguration() { |
| return myConfiguration; |
| } |
| |
| @Override |
| public RunnerSettings getRunnerSettings() { |
| return RunnerAndConfigurationSettingsImpl.this.getRunnerSettings(myRunner); |
| } |
| |
| @Override |
| public ConfigurationPerRunnerSettings getConfigurationSettings() { |
| return RunnerAndConfigurationSettingsImpl.this.getConfigurationSettings(myRunner); |
| } |
| } |
| } |