From 17ceb4f9b1fcda8da2129f0ed34b163db4b17560 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Fri, 20 Nov 2015 17:59:53 +0300 Subject: [PATCH] IDEA-57233 Editor font antialising/appearance problems on Linux Refactored jdk bundle handling, added tests Added linux jdk selection support --- bin/scripts/unix/idea.sh | 2 + .../openapi/util/SwitchBootJdkAction.java | 212 +++++++----------- .../src/com/intellij/util/JdkBundle.java | 155 +++++++++++++ .../src/com/intellij/util/JdkBundleList.java | 117 ++++++++++ .../com/intellij/util/JdkBundleListTest.java | 57 +++++ .../com/intellij/util/JdkBundleTest.java | 74 ++++++ .../src/com/intellij/util/VersionUtil.java | 38 ++++ .../com/intellij/util/VersionUtilTest.java | 27 ++- 8 files changed, 545 insertions(+), 137 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/util/JdkBundle.java create mode 100644 platform/lang-impl/src/com/intellij/util/JdkBundleList.java create mode 100644 platform/platform-tests/testSrc/com/intellij/util/JdkBundleListTest.java create mode 100644 platform/platform-tests/testSrc/com/intellij/util/JdkBundleTest.java diff --git a/bin/scripts/unix/idea.sh b/bin/scripts/unix/idea.sh index 39b95bf19b90..ebdc9a215500 100755 --- a/bin/scripts/unix/idea.sh +++ b/bin/scripts/unix/idea.sh @@ -59,6 +59,8 @@ IDE_BIN_HOME=`dirname "$SCRIPT_LOCATION"` # --------------------------------------------------------------------- if [ -n "$@@product_uc@@_JDK" -a -x "$@@product_uc@@_JDK/bin/java" ]; then JDK="$@@product_uc@@_JDK" +elif [ -s "$HOME/.@@system_selector@@/config/@@vm_options@@.jdk" ]; then + JDK=`$CAT $HOME/.@@system_selector@@/config/@@vm_options@@.jdk` elif [ -x "$IDE_HOME/jre/jre/bin/java" ] && "$IDE_HOME/jre/jre/bin/java" -version > /dev/null 2>&1 ; then JDK="$IDE_HOME/jre" elif [ -n "$JDK_HOME" -a -x "$JDK_HOME/bin/java" ]; then diff --git a/platform/lang-impl/src/com/intellij/openapi/util/SwitchBootJdkAction.java b/platform/lang-impl/src/com/intellij/openapi/util/SwitchBootJdkAction.java index d89cc4843c46..d5d2d8095163 100644 --- a/platform/lang-impl/src/com/intellij/openapi/util/SwitchBootJdkAction.java +++ b/platform/lang-impl/src/com/intellij/openapi/util/SwitchBootJdkAction.java @@ -27,20 +27,23 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.ui.JBColor; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBLabel; +import com.intellij.util.JdkBundle; +import com.intellij.util.JdkBundleList; +import com.intellij.util.PlatformUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; import java.io.*; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * @author denis @@ -49,37 +52,36 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware { @NonNls private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.SwitchBootJdkAction"); @NonNls private static final String productJdkConfigFileName = getExecutable() + ".jdk"; @NonNls private static final File productJdkConfigFile = new File(PathManager.getConfigPath(), productJdkConfigFileName); - @NonNls private static final File customJdkFile = new File(PathManager.getHomePath() + File.separator + "jre" + File.separator + "jdk"); + @NonNls private static final File bundledJdkFile = getBundledJDKFile(); + + + + @NotNull + private static File getBundledJDKFile() { + StringBuilder bundledJDKPath = new StringBuilder(PathManager.getHomePath() + File.separator + "jre"); + if (SystemInfo.isMac) { + bundledJDKPath.append(File.separator).append("jdk"); + } + return new File(bundledJDKPath.toString()); + } @Override public void update(AnActionEvent e) { Presentation presentation = e.getPresentation(); - if (!SystemInfo.isMac || !customJdkFile.exists()) { + if (!(SystemInfo.isMac || (SystemInfo.isLinux && PlatformUtils.isIntelliJ()))) { presentation.setEnabledAndVisible(false); return; } e.getPresentation().setText("Switch Boot JDK"); } - public static List getBundlesFromFile(@NotNull File fileWithBundles) { - InputStream stream = null; - InputStreamReader inputStream; - BufferedReader bufferedReader; - - List list = new ArrayList(); - - + public static List getBundlesFromFile(@NotNull File fileWithBundles) { + List list = new ArrayList(); try { - stream = new FileInputStream(fileWithBundles); - inputStream = new InputStreamReader(stream, Charset.forName("UTF-8")); - bufferedReader = new BufferedReader(inputStream); - - String line; - - while ((line = bufferedReader.readLine()) != null) { + for (String line : FileUtil.loadLines(fileWithBundles, "UTF-8")) { File file = new File(line); if (file.exists()) { - list.add(new JdkBundleDescriptor(file, file.getName())); + list.add(JdkBundle.createBundle(file, false, false)); } } @@ -87,14 +89,8 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware { // The device builders can throw IllegalStateExceptions if // build gets called before everything is properly setup LOG.error(e); - } catch (Exception e) { + } catch (IOException e) { LOG.error("Error reading JDK bundles", e); - } finally { - if (stream != null) { - try { - stream.close(); - } catch (IOException ignore) {} - } } return list; } @@ -120,6 +116,7 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware { File selectedJdkBundleFile = dialog.getSelectedFile(); FileWriter fooWriter = null; try { + //noinspection IOResourceOpenedButNotSafelyClosed fooWriter = new FileWriter(productJdkConfigFile, false); fooWriter.write(selectedJdkBundleFile.getAbsolutePath()); } @@ -140,67 +137,55 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware { } } - private static class JdkBundleDescriptor { - private File bundleAsFile; - private String visualRepresentation; - - public JdkBundleDescriptor(@NotNull File bundleAsFile, @NotNull String visualRepresentation) { - this.bundleAsFile = bundleAsFile; - this.visualRepresentation = visualRepresentation; - } - - public File getBundleAsFile() { - return bundleAsFile; - } - - public String getVisualRepresentation() { - return visualRepresentation; - } - } - private static class SwitchBootJdkDialog extends DialogWrapper { @NotNull private final ComboBox myComboBox; - protected SwitchBootJdkDialog(@Nullable Project project, final List jdkBundlesList) { + protected SwitchBootJdkDialog(@Nullable Project project, final List jdkBundlesList) { super(project, false); - final ArrayList pathsList = JdkUtil.findJdkPaths(); - if (!jdkBundlesList.isEmpty()) { - JdkBundleDescriptor jdkBundleDescription = jdkBundlesList.get(0); - pathsList.add(0, jdkBundleDescription); - } + final JdkBundleList pathsList = findJdkPaths(); myComboBox = new ComboBox(); DefaultComboBoxModel model = new DefaultComboBoxModel(); - for (JdkBundleDescriptor jdkBundlePath : pathsList) { - if (!(jdkBundlesList.isEmpty() || jdkBundlePath == null) - && FileUtil.filesEqual(jdkBundlePath.getBundleAsFile(),jdkBundlesList.get(0).getBundleAsFile())) - { - continue; - } + for (JdkBundle jdkBundlePath : pathsList.toArrayList()) { + //noinspection unchecked model.addElement(jdkBundlePath); } - myComboBox.setModel(model); + model.addListDataListener(new ListDataListener() { + @Override + public void intervalAdded(ListDataEvent e) { } - if (pathsList.isEmpty()) { - myComboBox.setEnabled(false); - } + @Override + public void intervalRemoved(ListDataEvent e) { } + + @Override + public void contentsChanged(ListDataEvent e) { + setOKActionEnabled(!((JdkBundle)myComboBox.getSelectedItem()).isBoot()); + } + }); + + //noinspection unchecked + myComboBox.setModel(model); myComboBox.setRenderer(new ListCellRendererWrapper() { @Override public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) { if (value != null) { - JdkBundleDescriptor jdkBundleDescriptor = ((JdkBundleDescriptor)value); + JdkBundle jdkBundleDescriptor = ((JdkBundle)value); + if (jdkBundleDescriptor.isBoot()) { + setForeground(JBColor.DARK_GRAY); + } setText(jdkBundleDescriptor.getVisualRepresentation()); - } else { + } + else { if (LOG.isDebugEnabled()) { - LOG.debug("Null value has been passed to a cell renderer. Available JDKs count: " + pathsList.size()); + LOG.debug("Null value has been passed to a cell renderer. Available JDKs count: " + pathsList.toArrayList().size()); StringBuilder jdkNames = new StringBuilder(); - for (JdkBundleDescriptor jdkBundlePath : pathsList) { + for (JdkBundle jdkBundlePath : pathsList.toArrayList()) { if (!jdkBundlesList.isEmpty()) { continue; } @@ -215,6 +200,7 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware { }); setTitle("Switch IDE Boot JDK"); + setOKActionEnabled(false); // First item is a boot jdk init(); } @@ -237,88 +223,44 @@ public class SwitchBootJdkAction extends AnAction implements DumbAware { } public File getSelectedFile() { - return ((JdkBundleDescriptor)myComboBox.getSelectedItem()).bundleAsFile; + return ((JdkBundle)myComboBox.getSelectedItem()).getBundleAsFile(); } } private static final String STANDARD_JDK_LOCATION_ON_MAC_OS_X = "/Library/Java/JavaVirtualMachines/"; private static final String STANDARD_JDK_6_LOCATION_ON_MAC_OS_X = "/System/Library/Java/JavaVirtualMachines/"; + private static final String [] STANDARD_JVM_LOCATIONS_ON_LINUX = new String[] { + "/usr/lib/jvm/", // Ubuntu + "/usr/java/" // Fedora + }; - private static class JdkUtil { - private static ArrayList findJdkPaths () { - ArrayList jdkPathsList = new ArrayList(); - if (!SystemInfo.isMac) return jdkPathsList; + private static final Version JDK6_VERSION = new Version(1, 6, 0); + private static final Version JDK8_VERSION = new Version(1, 8, 0); - if (customJdkFile.exists()) { - jdkPathsList.add(new JdkBundleDescriptor(customJdkFile, "JDK bundled with IDE")); - } - ArrayList jdk6List = jdkBundlesFromLocation(STANDARD_JDK_6_LOCATION_ON_MAC_OS_X, "1.6.0"); + private static JdkBundleList findJdkPaths() { + JdkBundle bootJdk = JdkBundle.createBoot(); - if (jdk6List.isEmpty()) { - jdkPathsList.addAll(jdkBundlesFromLocation(STANDARD_JDK_LOCATION_ON_MAC_OS_X, "1.6.0")); - } + JdkBundleList jdkBundleList = new JdkBundleList(); + jdkBundleList.addBundle(bootJdk, true); - jdkPathsList.addAll(jdkBundlesFromLocation(STANDARD_JDK_LOCATION_ON_MAC_OS_X, "jdk1.8.0_(\\d*).jdk")); - - return jdkPathsList; + if (bundledJdkFile.exists()) { + JdkBundle bundledJdk = JdkBundle.createBundle(bundledJdkFile, false, true); + jdkBundleList.addBundle(bundledJdk, true); } - private static ArrayList jdkBundlesFromLocation(String jdkLocationOnMacOsX, String filter) { - - ArrayList localJdkPathsList = new ArrayList(); - - File standardJdkLocationOnMacFile = new File(jdkLocationOnMacOsX); - - if (!standardJdkLocationOnMacFile.exists()) { - if (LOG.isDebugEnabled()) { - LOG.debug("Location does not exists: " + jdkLocationOnMacOsX); - } - return localJdkPathsList; - } - - File[] filesInStandardJdkLocation = standardJdkLocationOnMacFile.listFiles(); - - if (filesInStandardJdkLocation == null) { - LOG.debug("Some IO exception happened."); - return localJdkPathsList; - } - - int latestUpdateNumber = 0; - JdkBundleDescriptor latestBundle = null; - - Pattern p = Pattern.compile(filter); - - for (File possibleJdkBundle : filesInStandardJdkLocation) { - // todo add some logic to verify the bundle - - Matcher m = p.matcher(possibleJdkBundle.getName()); - - while (m.find()) { - try { - if (m.groupCount() > 0) { - int updateNumber = Integer.parseInt(m.group(1)); - if (latestUpdateNumber < updateNumber) { - latestBundle = new JdkBundleDescriptor(possibleJdkBundle, possibleJdkBundle.getName()); - } - } else { - latestBundle = new JdkBundleDescriptor(possibleJdkBundle, possibleJdkBundle.getName()); - } - } catch (NumberFormatException nfe) { - if (LOG.isDebugEnabled()) { - LOG.debug("Fail parsing update number"); - } - } - } - - } - - if (latestBundle != null) { - localJdkPathsList.add(latestBundle); - } - - return localJdkPathsList; + if (SystemInfo.isMac) { + jdkBundleList.addBundlesFromLocation(STANDARD_JDK_6_LOCATION_ON_MAC_OS_X, JDK6_VERSION, JDK6_VERSION); + jdkBundleList.addBundlesFromLocation(STANDARD_JDK_LOCATION_ON_MAC_OS_X, JDK6_VERSION, JDK6_VERSION); + jdkBundleList.addBundlesFromLocation(STANDARD_JDK_LOCATION_ON_MAC_OS_X, JDK8_VERSION, null); } + else if (SystemInfo.isLinux) { + for (String location : STANDARD_JVM_LOCATIONS_ON_LINUX) { + jdkBundleList.addBundlesFromLocation(location, JDK8_VERSION, null); + } + } + + return jdkBundleList; } @NotNull diff --git a/platform/lang-impl/src/com/intellij/util/JdkBundle.java b/platform/lang-impl/src/com/intellij/util/JdkBundle.java new file mode 100644 index 000000000000..511ede378fe4 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/JdkBundle.java @@ -0,0 +1,155 @@ +/* + * 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.util; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.util.ExecUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.Version; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.regex.Pattern; + +public class JdkBundle { + @NotNull private static final Logger LOG = Logger.getInstance("#com.intellij.util.JdkBundle"); + + private static final Pattern[] VERSION_UPDATE_PATTERNS = { + Pattern.compile("^java version \"([\\d]+\\.[\\d]+\\.[\\d]+)_([\\d]+)\".*", Pattern.MULTILINE), + Pattern.compile("^openjdk version \"([\\d]+\\.[\\d]+\\.[\\d]+)_([\\d]+).*\".*", Pattern.MULTILINE), + Pattern.compile("^[a-zA-Z() \"\\d]*([\\d]+\\.[\\d]+\\.?[\\d]*).*", Pattern.MULTILINE) + }; + + @NotNull private File myBundleAsFile; + @NotNull private String myBundleName; + @Nullable private Pair myVersionUpdate; + private boolean myBoot; + private boolean myBundled; + + public JdkBundle(@NotNull File bundleAsFile, + @NotNull String bundleName, + @Nullable Pair versionUpdate, boolean boot, boolean bundled) { + myBundleAsFile = bundleAsFile; + myBundleName = bundleName; + myVersionUpdate = versionUpdate; + myBoot = boot; + myBundled = bundled; + } + + + @Nullable + public static JdkBundle createBundle(@NotNull File jvm, boolean boot, boolean bundled) { + File javaHome = SystemInfo.isMac ? new File(jvm, "Contents/Home") : jvm; + if (!new File(javaHome, "lib/tools.jar").exists()) return null; // Skip JRE + + Pair> nameVersionAndUpdate = getJDKNameVersionAndUpdate(jvm.getAbsolutePath()); + return new JdkBundle(jvm, nameVersionAndUpdate.first, nameVersionAndUpdate.second, boot, bundled); + } + + public static JdkBundle createBoot() { + File bootJDK = new File(System.getProperty("java.home")).getParentFile(); + if (SystemInfo.isMac) { + bootJDK = bootJDK.getParentFile().getParentFile(); + } + return createBundle(bootJDK, true, false); + } + + @NotNull + public File getBundleAsFile() { + return myBundleAsFile; + } + + public String getVisualRepresentation() { + StringBuilder representation = new StringBuilder(myBundleName); + if (myVersionUpdate != null) { + representation.append(myVersionUpdate.first.toString()).append((myVersionUpdate.second > 0 ? "_" + myVersionUpdate.second : "")); + } + + if (myBoot || myBundled) { + representation.append(" ["); + if (myBoot) representation.append(myBundled ? "boot, " : "boot"); + if (myBundled) representation.append("bundled"); + representation.append("]"); + } + return representation.toString(); + } + + public void setBundled(boolean bundled) { + myBundled = bundled; + } + + public boolean isBoot() { + return myBoot; + } + + @NotNull + public String getBundleName() { + return myBundleName; + } + + @Nullable + public Pair getVersionUpdate() { + return myVersionUpdate; + } + + @Nullable + public Version getVersion() { + return myVersionUpdate != null ? myVersionUpdate.first : null; + } + + @NotNull + public String getNameVersion() { + return myBundleName + ((myVersionUpdate != null) ? myVersionUpdate.first.toString() : ""); + } + + private static Pair> getJDKNameVersionAndUpdate(String jvmPath) { + GeneralCommandLine commandLine = new GeneralCommandLine(); + commandLine.setExePath(jvmPath + (SystemInfo.isMac ? "/Contents/Home/" : "/") + "jre" + + File.separator + "bin" + File.separator + "java"); + commandLine.addParameter("-version"); + + String displayVersion = null; + Pair versionAndUpdate = null; + try { + displayVersion = ExecUtil.readFirstLine(commandLine.createProcess().getErrorStream(), null); + } + catch (ExecutionException e) { + LOG.debug(e); + } + + if (displayVersion != null) { + versionAndUpdate = VersionUtil.parseVersionAndUpdate(displayVersion, VERSION_UPDATE_PATTERNS); + displayVersion = displayVersion.replaceFirst("\".*\"", ""); + } + else { + displayVersion = new File(jvmPath).getName(); + } + + return Pair.create(displayVersion, versionAndUpdate); + } + + public boolean isBundled() { + return myBundled; + } + + public void setBoot(boolean boot) { + myBoot = boot; + } +} diff --git a/platform/lang-impl/src/com/intellij/util/JdkBundleList.java b/platform/lang-impl/src/com/intellij/util/JdkBundleList.java new file mode 100644 index 000000000000..c7cf5a7cba57 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/JdkBundleList.java @@ -0,0 +1,117 @@ +/* + * 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.util; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Version; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; + +public class JdkBundleList { + @NotNull private static final Logger LOG = Logger.getInstance("#com.intellij.util.JdkBundleList"); + + private ArrayList bundleList = new ArrayList(); + private HashMap bundleMap = new HashMap(); + private HashMap nameVersionMap = new HashMap(); + + public void addBundle(JdkBundle bundle, boolean forceOldVersion) { + JdkBundle bundleDescr = bundleMap.get(bundle.getBundleAsFile().getAbsolutePath()); + if (bundleDescr == null) { + addMostRecent(bundle, forceOldVersion); + } + else { + if (bundle.isBundled()) bundleDescr.setBundled(true); // preserve bundled flag + if (bundle.isBoot()) bundleDescr.setBoot(true); // preserve boot flag + } + } + + private void addMostRecent(JdkBundle bundleDescriptor, boolean forceOldVersion) { + Pair versionUpdate = bundleDescriptor.getVersionUpdate(); + boolean updateVersionMap = versionUpdate != null; + if (!bundleList.isEmpty() && updateVersionMap) { + JdkBundle latestJdk = nameVersionMap.get(bundleDescriptor.getNameVersion()); + if (latestJdk != null) { + Pair latestVersionUpdate = latestJdk.getVersionUpdate(); + if (latestVersionUpdate != null) { + if (latestVersionUpdate.second >= versionUpdate.second) { + if (!forceOldVersion) return; // do not add old non bundled jdk builds unless asked + + updateVersionMap = false; // include bundled version but do not update map + } + else if (!latestJdk.isBoot() && !latestJdk.isBundled()) { // preserve boot and bundled versions + bundleList.remove(latestJdk); + nameVersionMap.remove(latestJdk.getNameVersion()); + bundleMap.remove(latestJdk.getBundleAsFile().getAbsolutePath()); + } + } + } + } + + bundleList.add(bundleDescriptor); + bundleMap.put(bundleDescriptor.getBundleAsFile().getAbsolutePath(), bundleDescriptor); + + if (updateVersionMap) { + nameVersionMap.put(bundleDescriptor.getNameVersion(), bundleDescriptor); + } + } + + public void addBundlesFromLocation(String location, @Nullable Version minVer, @Nullable Version maxVer) { + File jvmLocation = new File(location); + + if (!jvmLocation.exists()) { + LOG.debug("Standard jvm location does not exists: " + jvmLocation); + return; + } + + File[] jvms = jvmLocation.listFiles(); + + if (jvms == null) { + LOG.debug("Cannot get jvm list from: " + jvmLocation); + return; + } + + for (File jvm : jvms) { + JdkBundle jvmBundle = JdkBundle.createBundle(jvm, false, false); + if (jvmBundle == null || jvmBundle.getVersionUpdate() == null) continue; + + Version jdkVer = jvmBundle.getVersion(); + if (jdkVer == null) continue; // Skip unknown + + if (minVer != null && jdkVer.lessThan(minVer.major, minVer.minor, minVer.bugfix)) { + continue; // Skip below supported + } + + if (maxVer != null && maxVer.lessThan(jdkVer.major, jdkVer.minor, jdkVer.bugfix)) { + continue; // Skip above supported + } + + addBundle(jvmBundle, false); + } + } + + public ArrayList toArrayList() { + return bundleList; + } + + public boolean contains(String path) { + return bundleMap.keySet().contains(path); + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/util/JdkBundleListTest.java b/platform/platform-tests/testSrc/com/intellij/util/JdkBundleListTest.java new file mode 100644 index 000000000000..acfecabae9c2 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/util/JdkBundleListTest.java @@ -0,0 +1,57 @@ +/* + * 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.util; + +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Version; +import org.junit.Test; + +import java.io.File; +import java.util.Arrays; + +import static com.intellij.testFramework.UsefulTestCase.assertSameElements; + +public class JdkBundleListTest { + @Test + public void testAddBundle() throws Exception { + JdkBundle jb0 = new JdkBundle(new File("/jb0"), "java", Pair.create(new Version(1, 8, 0), new Integer(0)), true, false); + JdkBundle jb1 = new JdkBundle(new File("/jb1"), "java", Pair.create(new Version(1, 8, 0), new Integer(1)), false, false); + JdkBundle jb2 = new JdkBundle(new File("/jb2"), "java", Pair.create(new Version(1, 8, 0), new Integer(2)), false, false); + JdkBundle jb3 = new JdkBundle(new File("/jb3"), "java", Pair.create(new Version(1, 8, 0), new Integer(3)), false, false); + JdkBundle jb4 = new JdkBundle(new File("/jb4"), "java", Pair.create(new Version(1, 8, 0), new Integer(4)), false, false); + + JdkBundle ob0 = new JdkBundle(new File("/ob0"), "openjdk", Pair.create(new Version(1, 8, 0), new Integer(0)), false, true); + JdkBundle ob1 = new JdkBundle(new File("/ob1"), "openjdk", Pair.create(new Version(1, 8, 0), new Integer(1)), false, false); + JdkBundle ob2 = new JdkBundle(new File("/ob2"), "openjdk", Pair.create(new Version(1, 8, 0), new Integer(2)), false, false); + JdkBundle ob3 = new JdkBundle(new File("/ob3"), "openjdk", Pair.create(new Version(1, 8, 0), new Integer(3)), false, false); + JdkBundle ob4 = new JdkBundle(new File("/ob4"), "openjdk", Pair.create(new Version(1, 8, 0), new Integer(4)), false, false); + + JdkBundleList bundleList = new JdkBundleList(); + + bundleList.addBundle(jb3, false); + bundleList.addBundle(ob1, false); + bundleList.addBundle(jb2, false); + bundleList.addBundle(ob2, false); + bundleList.addBundle(jb0, true); + bundleList.addBundle(ob0, true); + bundleList.addBundle(jb1, false); + bundleList.addBundle(ob4, false); + bundleList.addBundle(jb4, false); + bundleList.addBundle(ob3, false); + + assertSameElements(bundleList.toArrayList(), Arrays.asList(jb4, ob4, jb0, ob0)); + } +} \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/util/JdkBundleTest.java b/platform/platform-tests/testSrc/com/intellij/util/JdkBundleTest.java new file mode 100644 index 000000000000..5bfc5255cab9 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/util/JdkBundleTest.java @@ -0,0 +1,74 @@ +/* + * 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.util; + +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.Version; +import com.intellij.openapi.util.io.FileUtil; +import org.junit.Test; + +import java.io.File; + +import static junit.framework.TestCase.*; + +public class JdkBundleTest { + + @Test + public void testCreateBundle() throws Exception { + if (SystemInfo.isWindows) return; // Windows is not supported so far + File bootJDK = new File(System.getProperty("java.home")).getParentFile(); + if (SystemInfo.isMac) { + bootJDK = bootJDK.getParentFile().getParentFile(); + } + String verStr = System.getProperty("java.version"); + + JdkBundle bundle = JdkBundle.createBundle(bootJDK, true, true); + assertNotNull(bundle); + + assertTrue(bundle.isBoot()); + assertTrue(bundle.isBundled()); + + assertTrue(FileUtil.filesEqual(bundle.getBundleAsFile(), bootJDK)); + Pair verUpdate = bundle.getVersionUpdate(); + + assertNotNull(verUpdate); + + assertEquals(verStr, verUpdate.first.toString() + "_" + verUpdate.second.toString()); + } + + @Test + public void testCreateBoot() throws Exception { + if (SystemInfo.isWindows) return; // Windows is not supported so far + File bootJDK = new File(System.getProperty("java.home")).getParentFile(); + if (SystemInfo.isMac) { + bootJDK = bootJDK.getParentFile().getParentFile(); + } + String verStr = System.getProperty("java.version"); + + JdkBundle bundle = JdkBundle.createBoot(); + + assertTrue(bundle.isBoot()); + assertFalse(bundle.isBundled()); + + assertTrue(FileUtil.filesEqual(bundle.getBundleAsFile(), bootJDK)); + Pair verUpdate = bundle.getVersionUpdate(); + + assertNotNull(verUpdate); + + assertEquals(verStr, verUpdate.first.toString() + "_" + verUpdate.second.toString()); + } +} \ No newline at end of file diff --git a/platform/util/src/com/intellij/util/VersionUtil.java b/platform/util/src/com/intellij/util/VersionUtil.java index c6bd575f82e7..a8dc7d01eaae 100644 --- a/platform/util/src/com/intellij/util/VersionUtil.java +++ b/platform/util/src/com/intellij/util/VersionUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.util; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Version; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -48,4 +49,41 @@ public class VersionUtil { (versions.length > 2) ? Integer.parseInt(versions[2]) : 0); } + @Nullable + public static Pair parseVersionAndUpdate(@NotNull String version, @NotNull Pattern... patterns) { + String[] versions = null; + String updateStr = null; + + for (Pattern pattern : patterns) { + Matcher matcher = pattern.matcher(version); + if (matcher.find()) { + String versionGroup = matcher.group(1); + if (versionGroup != null) { + updateStr = matcher.groupCount() > 1 ? matcher.group(2) : null; + versions = versionGroup.split("\\."); + break; + } + } + } + + if (versions == null || versions.length < 2) { + return null; + } + + Integer update = null; + if (updateStr != null) { + try { + update = Integer.parseInt(updateStr); + } + catch (NumberFormatException e) { + // ignore + } + } + + if (update == null) update = new Integer(0); // Treating no update info as update 0 + + return Pair.create( + new Version(Integer.parseInt(versions[0]), Integer.parseInt(versions[1]), (versions.length > 2) ? Integer.parseInt(versions[2]) : 0), + update); + } } diff --git a/platform/util/testSrc/com/intellij/util/VersionUtilTest.java b/platform/util/testSrc/com/intellij/util/VersionUtilTest.java index 314f1fe74e29..b6bbc8d81f96 100644 --- a/platform/util/testSrc/com/intellij/util/VersionUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/VersionUtilTest.java @@ -1,5 +1,6 @@ package com.intellij.util; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Version; import junit.framework.TestCase; @@ -13,8 +14,13 @@ public class VersionUtilTest extends TestCase { Pattern.compile("^openjdk version \"([\\d]+\\.[\\d]+\\.[\\d]+)_[\\d]+.*\".*", Pattern.MULTILINE), Pattern.compile("^[a-zA-Z() \\d]*([\\d]+\\.[\\d]+\\.?[\\d]*).*", Pattern.MULTILINE) }; + private static final Pattern[] VERSION_UPDATE_PATTERNS = { + Pattern.compile("^java version \"([\\d]+\\.[\\d]+\\.[\\d]+)_([\\d]+)\".*", Pattern.MULTILINE), + Pattern.compile("^openjdk version \"([\\d]+\\.[\\d]+\\.[\\d]+)_([\\d]+).*\".*", Pattern.MULTILINE), + Pattern.compile("^[a-zA-Z() \"\\d]*([\\d]+\\.[\\d]+\\.?[\\d]*).*", Pattern.MULTILINE) + }; - private static final Object[][] testData = { + private static final Object[][] testDataVersion = { {"GNU gdb 6.3.50-20050815 (Apple version gdb-1824) (Wed Feb 6 22:51:23 UTC 2013)", new Version(6, 3, 50)}, {"GNU gdb (GDB) 7.6", new Version(7, 6, 0)}, {"GNU gdb (GDB) 7.6something123", new Version(7, 6, 0)}, @@ -29,10 +35,27 @@ public class VersionUtilTest extends TestCase { {"openjdk version \"1.8.1_60-release\"", new Version(1, 8, 1)} }; + private static final Object[][] testDataVersionUpdate = { + {"java version \"1.6.0\"", new Version(1, 6, 0), new Integer(0)}, + {"java version \"1.6.0_36\"", new Version(1, 6, 0), new Integer(36)}, + {"java version \"1.7.0_85\"", new Version(1, 7, 0), new Integer(85)}, + {"openjdk version \"1.8.0_45-internal\"", new Version(1, 8, 0), new Integer(45)}, + {"openjdk version \"1.8.1_60-release\"", new Version(1, 8, 1), new Integer(60)} + }; + public void testParseVersion() throws Exception { - for (Object[] aTestData : testData) { + for (Object[] aTestData : testDataVersion) { String versionString = (String)aTestData[0]; assertEquals("For \"" + versionString + "\"", aTestData[1], VersionUtil.parseVersion(versionString, VERSION_PATTERNS)); } } + public void testParseVersionAndUpdate() throws Exception { + for (Object[] aTestData : testDataVersionUpdate) { + String versionString = (String)aTestData[0]; + Pair versionAndUpdate = VersionUtil.parseVersionAndUpdate(versionString, VERSION_UPDATE_PATTERNS); + assertNotNull(versionAndUpdate); + assertEquals("For \"" + versionString + "\"", aTestData[1], versionAndUpdate.first); + assertEquals("For \"" + versionString + "\"", aTestData[2], versionAndUpdate.second); + } + } } \ No newline at end of file