diff --git a/java/execution/impl/src/com/intellij/execution/CommonJavaRunConfigurationParameters.java b/java/execution/impl/src/com/intellij/execution/CommonJavaRunConfigurationParameters.java index 884dc59391dd..45b40d3b15d6 100644 --- a/java/execution/impl/src/com/intellij/execution/CommonJavaRunConfigurationParameters.java +++ b/java/execution/impl/src/com/intellij/execution/CommonJavaRunConfigurationParameters.java @@ -37,4 +37,17 @@ public interface CommonJavaRunConfigurationParameters extends CommonProgramRunCo @Nullable String getPackage(); + + /** + * @return null if option was not selected explicitly, legacy user-local options to be used + */ + @Nullable + default ShortenClasspath getShortenClasspath() { + return null; + } + + /** + * Called from UI, when user explicitly selects method to be used to shorten the command line or from the deserialization + */ + default void setShortenClasspath(ShortenClasspath mode) {} } diff --git a/java/execution/impl/src/com/intellij/execution/JavaTestConfigurationBase.java b/java/execution/impl/src/com/intellij/execution/JavaTestConfigurationBase.java index 6b033b62746c..b207d8e395e7 100644 --- a/java/execution/impl/src/com/intellij/execution/JavaTestConfigurationBase.java +++ b/java/execution/impl/src/com/intellij/execution/JavaTestConfigurationBase.java @@ -21,15 +21,21 @@ import com.intellij.execution.configurations.ModuleBasedConfiguration; import com.intellij.execution.configurations.RefactoringListenerProvider; import com.intellij.execution.testframework.TestSearchScope; import com.intellij.execution.testframework.sm.runner.SMRunnerConsolePropertiesProvider; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; +import org.jdom.Element; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; public abstract class JavaTestConfigurationBase extends ModuleBasedConfiguration implements CommonJavaRunConfigurationParameters, RefactoringListenerProvider, SMRunnerConsolePropertiesProvider { + private ShortenClasspath myShortenClasspath = null; + public JavaTestConfigurationBase(String name, @NotNull JavaRunConfigurationModule configurationModule, @NotNull ConfigurationFactory factory) { @@ -57,4 +63,27 @@ public abstract class JavaTestConfigurationBase extends ModuleBasedConfiguration } public abstract TestSearchScope getTestSearchScope(); + + @Nullable + @Override + public ShortenClasspath getShortenClasspath() { + return myShortenClasspath; + } + + @Override + public void setShortenClasspath(ShortenClasspath shortenClasspath) { + myShortenClasspath = shortenClasspath; + } + + @Override + public void readExternal(Element element) throws InvalidDataException { + super.readExternal(element); + setShortenClasspath(ShortenClasspath.readShortenClasspathMethod(element)); + } + + @Override + public void writeExternal(Element element) throws WriteExternalException { + super.writeExternal(element); + ShortenClasspath.writeShortenClasspathMethod(element, myShortenClasspath); + } } diff --git a/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java b/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java index b5ff7680c984..1b6ad00c8ba9 100644 --- a/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java +++ b/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java @@ -194,10 +194,10 @@ public abstract class JavaTestFrameworkRunnableState - + @@ -63,11 +63,20 @@ - + + + + + + + + + + diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java index 91092a1824f0..c08054558247 100644 --- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java +++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java @@ -18,6 +18,7 @@ package com.intellij.execution.application; import com.intellij.application.options.ModuleDescriptionsComboBox; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.JavaExecutionUtil; +import com.intellij.execution.ShortenClasspath; import com.intellij.execution.configurations.ConfigurationUtil; import com.intellij.execution.ui.*; import com.intellij.execution.util.JreVersionDetector; @@ -43,6 +44,7 @@ public class ApplicationConfigurable extends SettingsEditor myMainClass; private LabeledComponent myModule; + private LabeledComponent myShortenClasspathModeCombo; private JPanel myWholePanel; private final ConfigurationModuleSelector myModuleSelector; @@ -65,7 +67,8 @@ public class ApplicationConfigurable extends SettingsEditor(); + myShortenClasspathModeCombo.setComponent(new ShortenClasspathModeCombo(myProject)); } @Override @@ -144,5 +151,6 @@ public class ApplicationConfigurable extends SettingsEditor myEnvs = new LinkedHashMap<>(); public boolean PASS_PARENT_ENVS = true; @@ -243,6 +245,7 @@ public class ApplicationConfiguration extends ModuleBasedConfiguration extends BaseJavaApplicationCommandLineState { @@ -267,7 +283,8 @@ public class ApplicationConfiguration extends ModuleBasedConfiguration { + private final Project myProject; + + public ShortenClasspathModeCombo(Project project) { + myProject = project; + addItem(null); + for (ShortenClasspath mode : ShortenClasspath.values()) { + addItem(mode); + } + setRenderer(new ColoredListCellRenderer() { + @Override + protected void customizeCellRenderer(@NotNull JList list, + ShortenClasspath value, + int index, + boolean selected, + boolean hasFocus) { + if (value == null) { + ShortenClasspath defaultMode = ShortenClasspath.getDefaultMethod(myProject); + append("user-local default: " + defaultMode.getPresentableName()).append(" - " + defaultMode.getDescription(), SimpleTextAttributes.GRAYED_ATTRIBUTES); + } + else { + append(value.getPresentableName()).append(" - " + value.getDescription(), SimpleTextAttributes.GRAYED_ATTRIBUTES); + } + } + }); + } +} diff --git a/platform/lang-api/src/com/intellij/execution/ShortenClasspath.java b/platform/lang-api/src/com/intellij/execution/ShortenClasspath.java new file mode 100644 index 000000000000..4563caf27c6b --- /dev/null +++ b/platform/lang-api/src/com/intellij/execution/ShortenClasspath.java @@ -0,0 +1,66 @@ +// Copyright 2000-2017 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; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.JdkUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; + +/** + * Command line has length limit depending on used OS. In order to allow java command lines of any length for any OS, a number of approaches are possible. + * + * Since 2017.3, it's possible to setup shortening command line method per run configuration, e.g. {@link com.intellij.execution.CommonJavaRunConfigurationParameters#getShortenClasspath} + */ +public enum ShortenClasspath { + NONE("none", "java [options] classname [args]"), + MANIFEST("JAR manifest", "java -cp classpath.jar classname [args]"), + CLASSPATH_FILE("classpath file", "java WrapperClass classpathFile [args]"); + + private final String myPresentableName; + private final String myDescription; + + ShortenClasspath(String presentableName, String description) { + myPresentableName = presentableName; + myDescription = description; + } + + public String getDescription() { + return myDescription; + } + + public String getPresentableName() { + return myPresentableName; + } + + public static ShortenClasspath getDefaultMethod(Project project) { + if (!JdkUtil.useDynamicClasspath(project)) return NONE; + if (JdkUtil.useClasspathJar()) return MANIFEST; + return CLASSPATH_FILE; + } + + public static ShortenClasspath readShortenClasspathMethod(@NotNull Element element) { + Element mode = element.getChild("shortenClasspath"); + if (mode != null) { + return valueOf(mode.getAttributeValue("name")); + } + return null; + } + + public static void writeShortenClasspathMethod(@NotNull Element element, ShortenClasspath shortenClasspath) { + if (shortenClasspath != null) { + element.addContent(new Element("shortenClasspath").setAttribute("name", shortenClasspath.name())); + } + } +} diff --git a/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java b/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java index 411c81dfebc2..d17947d44745 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java @@ -17,6 +17,7 @@ package com.intellij.execution.configurations; import com.intellij.execution.CantRunException; import com.intellij.execution.ExecutionException; +import com.intellij.execution.ShortenClasspath; import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessTerminatedListener; import com.intellij.openapi.diagnostic.Logger; @@ -129,9 +130,18 @@ public class SimpleJavaParameters extends SimpleProgramParameters { return myUseClasspathJar; } - /** Allows to use a specially crafted .jar file instead of a custom class loader to pass classpath/properties/parameters. */ + /** + * Allows to use a specially crafted .jar file instead of a custom class loader to pass classpath/properties/parameters. + * Would have no effect if user explicitly disabled idea.dynamic.classpath.jar + */ public void setUseClasspathJar(boolean useClasspathJar) { - myUseClasspathJar = useClasspathJar; + myUseClasspathJar = useClasspathJar && JdkUtil.useClasspathJar(); + } + + public void setShortenClasspath(@Nullable ShortenClasspath mode, Project project) { + if (mode == null) mode = ShortenClasspath.getDefaultMethod(project); + myUseDynamicClasspath = mode != ShortenClasspath.NONE; + myUseClasspathJar = mode == ShortenClasspath.MANIFEST; } public String getJarPath() { diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java index 22585bd351ed..9d3b9aa3f287 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java @@ -35,15 +35,12 @@ import com.intellij.openapi.vfs.encoding.EncodingManager; import com.intellij.util.PathUtil; import com.intellij.util.PathsList; import com.intellij.util.execution.ParametersListUtil; -import com.intellij.util.lang.ClassPath; import com.intellij.util.lang.UrlClassLoader; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.*; -import java.net.MalformedURLException; -import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; @@ -175,7 +172,7 @@ public class JdkUtil { dynamicMainClass = dynamicParameters; } else if (!explicitClassPath(vmParameters) && javaParameters.getJarPath() == null && (commandLineWrapper = getCommandLineWrapperClass()) != null) { - if (canUseClasspathJar(javaParameters)) { + if (javaParameters.isUseClasspathJar()) { setClasspathJarParams(commandLine, javaParameters, vmParameters, commandLineWrapper, dynamicVMOptions, dynamicParameters); } else { @@ -431,33 +428,6 @@ public class JdkUtil { throw new CantRunException("Failed to a create temporary file in " + FileUtilRt.getTempDirectory(), cause); } - private static boolean canUseClasspathJar(SimpleJavaParameters javaParameters) { - String currentPath = PathUtil.getJarPathForClass(ClassPath.class); - if (javaParameters.isUseClasspathJar() && useClasspathJar()) { - try { - final List urls = new ArrayList<>(); - for (String path : javaParameters.getClassPath().getPathList()) { - if (!path.equals(currentPath)) { - try { - urls.add(new File(path).toURI().toURL()); - } - catch (MalformedURLException ignore) {} - } - } - final Class aClass = Class.forName("com.intellij.util.lang.ClassPath", false, UrlClassLoader.build().urls(urls).get()); - try { - aClass.getDeclaredMethod("initLoaders", URL.class, boolean.class, int.class); - } - catch (NoSuchMethodException e) { - return false; - } - } - catch (Throwable ignore) {} - return true; - } - return false; - } - private static void appendParamsEncodingClasspath(SimpleJavaParameters javaParameters, GeneralCommandLine commandLine, ParametersList vmParameters) { diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index 85cfa5626f37..bf01ada1d73e 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -219,6 +219,7 @@ class.not.specified.error.message=Class not specified. failed.to.generate.wrapper.error.message=Failed to generate temporary html wrapper for applet class application.configuration.use.classpath.and.jdk.of.module.label=Use classpath of m&odule: +application.configuration.shorten.command.line.label=Shorten command line: application.configuration.main.class.label=Main &class: jre.path.is.not.valid.jre.home.error.message=''{0}'' is not a valid JRE home jre.path.is.jdk.error.message=Alternative JRE path needs to point to a JRE, not to a complete JDK installation diff --git a/platform/util/src/com/intellij/util/lang/ClassPath.java b/platform/util/src/com/intellij/util/lang/ClassPath.java index 7d66e25d8374..03a76797f817 100644 --- a/platform/util/src/com/intellij/util/lang/ClassPath.java +++ b/platform/util/src/com/intellij/util/lang/ClassPath.java @@ -175,10 +175,6 @@ public class ClassPath { return result; } - /** - * Used in com.intellij.openapi.projectRoots.JdkUtil#isClassPathJarEnabled(List, String) - * as a condition that UrlClassLoader supports classpath jars. Please modify it accordingly. - */ private void initLoaders(final URL url, boolean lastOne, int index) throws IOException { String path; diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form index 9d1d2f305c3f..c562c44c12a7 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.form @@ -3,7 +3,7 @@ - + @@ -43,7 +43,7 @@ - + @@ -68,11 +68,15 @@ - + - + - + + + + + @@ -83,9 +87,15 @@ - + + + + + + + diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index 39210a5fc491..1f0daa36ec8a 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -19,6 +19,7 @@ package com.intellij.execution.junit2.configuration; import com.intellij.application.options.ModuleDescriptionsComboBox; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.MethodBrowser; +import com.intellij.execution.ShortenClasspath; import com.intellij.execution.configuration.BrowseModuleValueActionListener; import com.intellij.execution.junit.JUnitConfiguration; import com.intellij.execution.junit.JUnitConfigurationType; @@ -37,7 +38,9 @@ import com.intellij.openapi.fileTypes.PlainTextLanguage; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.*; +import com.intellij.openapi.ui.ComponentWithBrowseButton; +import com.intellij.openapi.ui.LabeledComponent; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.ui.ex.MessagesEx; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; @@ -49,8 +52,8 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.rt.execution.junit.RepeatCount; import com.intellij.ui.*; -import com.intellij.ui.components.fields.ExpandableTextField; import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.fields.ExpandableTextField; import com.intellij.util.IconUtil; import com.intellij.util.ui.UIUtil; import gnu.trove.TIntArrayList; @@ -101,6 +104,7 @@ public class JUnitConfigurable extends SettingsEdi private JRadioButton myModuleWDScope; private TextFieldWithBrowseButton myPatternTextField; private JrePathEditor myJrePathEditor; + private LabeledComponent myShortenClasspathModeCombo; private JComboBox myForkCb; private JBLabel myTestLabel; private JComboBox myTypeChooser; @@ -264,6 +268,7 @@ public class JUnitConfigurable extends SettingsEdi setAnchor(mySearchForTestsLabel); myJrePathEditor.setAnchor(myModule.getLabel()); myCommonJavaParameters.setAnchor(myModule.getLabel()); + myShortenClasspathModeCombo.setAnchor(myModule.getLabel()); final DefaultComboBoxModel model = new DefaultComboBoxModel<>(); myChangeListLabeledComponent.getComponent().setModel(model); @@ -310,6 +315,7 @@ public class JUnitConfigurable extends SettingsEdi myCommonJavaParameters.applyTo(configuration); configuration.setForkMode((String)myForkCb.getSelectedItem()); + configuration.setShortenClasspath((ShortenClasspath)myShortenClasspathModeCombo.getComponent().getSelectedItem()); } public void resetEditorFrom(@NotNull final JUnitConfiguration configuration) { @@ -335,6 +341,7 @@ public class JUnitConfigurable extends SettingsEdi myJrePathEditor .setPathOrName(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled()); myForkCb.setSelectedItem(configuration.getForkMode()); + myShortenClasspathModeCombo.getComponent().setSelectedItem(configuration.getShortenClasspath()); } private void changePanel () { @@ -516,6 +523,9 @@ public class JUnitConfigurable extends SettingsEdi JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE, PlainTextLanguage.INSTANCE.getAssociatedFileType()); myMethod.setComponent(textFieldWithBrowseButton); + + myShortenClasspathModeCombo = new LabeledComponent<>(); + myShortenClasspathModeCombo.setComponent(new ShortenClasspathModeCombo(myProject)); } @Override diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.form b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.form index 68d67c975184..53c87cef5bdb 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.form +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.form @@ -140,7 +140,7 @@ - + @@ -158,11 +158,14 @@ - + - + - + + + + @@ -174,7 +177,7 @@ - + @@ -184,6 +187,12 @@ + + + + + + diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java index 699134bc1f39..8a2000091568 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java @@ -20,12 +20,10 @@ import com.intellij.application.options.ModulesComboBox; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.JavaExecutionUtil; import com.intellij.execution.MethodBrowser; +import com.intellij.execution.ShortenClasspath; import com.intellij.execution.configuration.BrowseModuleValueActionListener; import com.intellij.execution.testframework.TestSearchScope; -import com.intellij.execution.ui.CommonJavaParametersPanel; -import com.intellij.execution.ui.ConfigurationModuleSelector; -import com.intellij.execution.ui.DefaultJreSelector; -import com.intellij.execution.ui.JrePathEditor; +import com.intellij.execution.ui.*; import com.intellij.ide.util.TreeClassChooser; import com.intellij.ide.util.TreeClassChooserFactory; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -36,16 +34,18 @@ import com.intellij.openapi.fileTypes.PlainTextLanguage; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.*; +import com.intellij.openapi.ui.ComponentWithBrowseButton; +import com.intellij.openapi.ui.LabeledComponent; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.*; -import com.intellij.ui.components.fields.ExpandableTextField; import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBList; +import com.intellij.ui.components.fields.ExpandableTextField; import com.intellij.ui.table.TableView; import com.intellij.util.IconUtil; import com.theoryinpractice.testng.MessageInfoException; @@ -101,6 +101,7 @@ public class TestNGConfigurationEditor extends Se private LabeledComponent myPattern; private JPanel myPropertiesPanel; private JPanel myListenersPanel; + private LabeledComponent myShortenCommandLineCombo; TextFieldWithBrowseButton myPatternTextField; private final CommonJavaParametersPanel commonJavaParameters = new CommonJavaParametersPanel(); private final ArrayList> propertiesList = new ArrayList<>(); @@ -205,6 +206,7 @@ public class TestNGConfigurationEditor extends Se setAnchor(outputDirectory.getLabel()); alternateJDK.setAnchor(moduleClasspath.getLabel()); commonJavaParameters.setAnchor(moduleClasspath.getLabel()); + myShortenCommandLineCombo.setAnchor(moduleClasspath.getLabel()); } private void evaluateModuleClassPath() { @@ -301,6 +303,7 @@ public class TestNGConfigurationEditor extends Se listenerModel.setListenerList(data.TEST_LISTENERS); myUseDefaultReportersCheckBox.setSelected(data.USE_DEFAULT_REPORTERS); + myShortenCommandLineCombo.getComponent().setSelectedItem(config.getShortenClasspath()); } @Override @@ -334,6 +337,7 @@ public class TestNGConfigurationEditor extends Se data.TEST_LISTENERS.addAll(listenerModel.getListenerList()); data.USE_DEFAULT_REPORTERS = myUseDefaultReportersCheckBox.isSelected(); + config.setShortenClasspath((ShortenClasspath)myShortenCommandLineCombo.getComponent().getSelectedItem()); } public ConfigurationModuleSelector getModuleSelector() { @@ -364,6 +368,11 @@ public class TestNGConfigurationEditor extends Se myTestLabel.setAnchor(anchor); } + private void createUIComponents() { + myShortenCommandLineCombo = new LabeledComponent<>(); + myShortenCommandLineCombo.setComponent(new ShortenClasspathModeCombo(project)); + } + private static void registerListener(JRadioButton[] buttons, ChangeListener changelistener) { ButtonGroup buttongroup = new ButtonGroup(); for (JRadioButton button : buttons) {