diff options
author | Petr Mrázek <peterix@gmail.com> | 2016-01-02 00:35:54 +0100 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2016-01-02 00:35:54 +0100 |
commit | a008efd24e81441a23ff3e81320ac3522251327e (patch) | |
tree | f73886925814cc4cfb397be9f8342f7963d8f8d7 | |
parent | 5f57df81109d268c79b34aac799fc7694ec5882a (diff) | |
download | MultiMC-a008efd24e81441a23ff3e81320ac3522251327e.tar MultiMC-a008efd24e81441a23ff3e81320ac3522251327e.tar.gz MultiMC-a008efd24e81441a23ff3e81320ac3522251327e.tar.lz MultiMC-a008efd24e81441a23ff3e81320ac3522251327e.tar.xz MultiMC-a008efd24e81441a23ff3e81320ac3522251327e.zip |
GH-1365 rework java version parsing and sorting
23 files changed, 414 insertions, 138 deletions
diff --git a/application/JavaCommon.cpp b/application/JavaCommon.cpp index 2bec046a..403883e7 100644 --- a/application/JavaCommon.cpp +++ b/application/JavaCommon.cpp @@ -26,7 +26,7 @@ void JavaCommon::TestCheck::javaWasOk(JavaCheckResult result) { QString text; text += tr("Java test succeeded!<br />Platform reported: %1<br />Java version " - "reported: %2<br />").arg(result.realPlatform, result.javaVersion); + "reported: %2<br />").arg(result.realPlatform, result.javaVersion.toString()); if (result.errorLog.size()) { auto htmlError = result.errorLog; @@ -87,7 +87,7 @@ void JavaCommon::TestCheck::checkFinished(JavaCheckResult result) checker->m_args = m_args; checker->m_minMem = m_minMem; checker->m_maxMem = m_maxMem; - if (Strings::naturalCompare(result.javaVersion, "1.8", Qt::CaseInsensitive) < 0) + if (result.javaVersion.requiresPermGen()) { checker->m_permGen = m_permGen; } diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp index 2fab40cb..82d923bb 100644 --- a/application/MainWindow.cpp +++ b/application/MainWindow.cpp @@ -55,7 +55,7 @@ #include <auth/flows/RefreshTask.h> #include <icons/IconList.h> #include <java/JavaUtils.h> -#include <java/JavaVersionList.h> +#include <java/JavaInstallList.h> #include <launch/LaunchTask.h> #include <minecraft/MinecraftVersionList.h> #include <minecraft/LwjglVersionList.h> @@ -1638,14 +1638,14 @@ void MainWindow::checkSetDefaultJava() { qDebug() << "Java path needs resetting, showing Java selection dialog..."; - JavaVersionPtr java; + JavaInstallPtr java; VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, false); vselect.setResizeOn(2); vselect.exec(); if (vselect.selectedVersion()) - java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion()); + java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion()); else { CustomMessageBox::selectable(this, tr("Invalid version selected"), tr("You didn't select a valid Java version, so MultiMC will " diff --git a/application/MultiMC.cpp b/application/MultiMC.cpp index cd5e145a..a2a14506 100644 --- a/application/MultiMC.cpp +++ b/application/MultiMC.cpp @@ -586,11 +586,11 @@ std::shared_ptr<MinecraftVersionList> MultiMC::minecraftlist() return m_minecraftlist; } -std::shared_ptr<JavaVersionList> MultiMC::javalist() +std::shared_ptr<JavaInstallList> MultiMC::javalist() { if (!m_javalist) { - m_javalist.reset(new JavaVersionList()); + m_javalist.reset(new JavaInstallList()); ENV.registerVersionList("com.java", m_javalist); } return m_javalist; diff --git a/application/MultiMC.h b/application/MultiMC.h index 492544fc..5b19db19 100644 --- a/application/MultiMC.h +++ b/application/MultiMC.h @@ -20,7 +20,7 @@ class IconList; class QNetworkAccessManager; class ForgeVersionList; class LiteLoaderVersionList; -class JavaVersionList; +class JavaInstallList; class UpdateChecker; class BaseProfilerFactory; class BaseDetachedToolFactory; @@ -79,7 +79,7 @@ public: std::shared_ptr<LWJGLVersionList> lwjgllist(); std::shared_ptr<ForgeVersionList> forgelist(); std::shared_ptr<LiteLoaderVersionList> liteloaderlist(); - std::shared_ptr<JavaVersionList> javalist(); + std::shared_ptr<JavaInstallList> javalist(); // APPLICATION ONLY std::shared_ptr<InstanceList> instances() @@ -160,7 +160,7 @@ private: std::shared_ptr<ForgeVersionList> m_forgelist; std::shared_ptr<LiteLoaderVersionList> m_liteloaderlist; std::shared_ptr<MinecraftVersionList> m_minecraftlist; - std::shared_ptr<JavaVersionList> m_javalist; + std::shared_ptr<JavaInstallList> m_javalist; std::shared_ptr<TranslationDownloader> m_translationChecker; std::shared_ptr<GenericPageProvider> m_globalSettingsProvider; diff --git a/application/pages/InstanceSettingsPage.cpp b/application/pages/InstanceSettingsPage.cpp index a23d7c22..2922e469 100644 --- a/application/pages/InstanceSettingsPage.cpp +++ b/application/pages/InstanceSettingsPage.cpp @@ -9,7 +9,7 @@ #include "JavaCommon.h" #include "MultiMC.h" -#include <java/JavaVersionList.h> +#include <java/JavaInstallList.h> #include <FileSystem.h> InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) @@ -170,7 +170,7 @@ void InstanceSettingsPage::loadSettings() void InstanceSettingsPage::on_javaDetectBtn_clicked() { - JavaVersionPtr java; + JavaInstallPtr java; VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true); vselect.setResizeOn(2); @@ -178,7 +178,7 @@ void InstanceSettingsPage::on_javaDetectBtn_clicked() if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) { - java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion()); + java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion()); ui->javaPathTextBox->setText(java->path); } } diff --git a/application/pages/global/JavaPage.cpp b/application/pages/global/JavaPage.cpp index 1c33a9ff..82103e23 100644 --- a/application/pages/global/JavaPage.cpp +++ b/application/pages/global/JavaPage.cpp @@ -25,7 +25,7 @@ #include <ColumnResizer.h> #include "java/JavaUtils.h" -#include "java/JavaVersionList.h" +#include "java/JavaInstallList.h" #include "settings/SettingsObject.h" #include <FileSystem.h> @@ -93,14 +93,14 @@ void JavaPage::loadSettings() void JavaPage::on_javaDetectBtn_clicked() { - JavaVersionPtr java; + JavaInstallPtr java; VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true); vselect.exec(); if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) { - java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion()); + java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion()); ui->javaPathTextBox->setText(java->path); } } diff --git a/depends/launcher/org/multimc/Utils.java b/depends/launcher/org/multimc/Utils.java index 1077065a..32cf7919 100644 --- a/depends/launcher/org/multimc/Utils.java +++ b/depends/launcher/org/multimc/Utils.java @@ -235,8 +235,12 @@ public class Utils ZipFile zip = new ZipFile(source); boolean applyHacks = false; - String[] javaVersionElements = System.getProperty("java.version").split("\\."); - int major = Integer.parseInt(javaVersionElements[1]); + String[] javaVersionElements = System.getProperty("java.version").split("[.\\-+]"); + int major = Integer.parseInt(javaVersionElements[0]); + if(major == 1) + { + major = Integer.parseInt(javaVersionElements[1]); + } if (major >= 8) { applyHacks = true; diff --git a/logic/CMakeLists.txt b/logic/CMakeLists.txt index 6d03e3bd..0398cffe 100644 --- a/logic/CMakeLists.txt +++ b/logic/CMakeLists.txt @@ -260,12 +260,16 @@ set(LOGIC_SOURCES # Java related code java/JavaChecker.h java/JavaChecker.cpp - java/JavaUtils.h - java/JavaUtils.cpp - java/JavaVersionList.h - java/JavaVersionList.cpp java/JavaCheckerJob.h java/JavaCheckerJob.cpp + java/JavaInstall.h + java/JavaInstall.cpp + java/JavaInstallList.h + java/JavaInstallList.cpp + java/JavaUtils.h + java/JavaUtils.cpp + java/JavaVersion.h + java/JavaVersion.cpp # Assets minecraft/AssetsUtils.h diff --git a/logic/java/JavaChecker.h b/logic/java/JavaChecker.h index 3399f07e..650e7ce3 100644 --- a/logic/java/JavaChecker.h +++ b/logic/java/JavaChecker.h @@ -5,15 +5,16 @@ #include "multimc_logic_export.h" -class JavaChecker; +#include "JavaVersion.h" +class JavaChecker; -struct JavaCheckResult +struct MULTIMC_LOGIC_EXPORT JavaCheckResult { QString path; QString mojangPlatform; QString realPlatform; - QString javaVersion; + JavaVersion javaVersion; QString errorLog; bool valid = false; bool is_64bit = false; diff --git a/logic/java/JavaInstall.cpp b/logic/java/JavaInstall.cpp new file mode 100644 index 00000000..bb262b6e --- /dev/null +++ b/logic/java/JavaInstall.cpp @@ -0,0 +1,28 @@ +#include "JavaInstall.h" +#include <MMCStrings.h> + +bool JavaInstall::operator<(const JavaInstall &rhs) +{ + auto archCompare = Strings::naturalCompare(arch, rhs.arch, Qt::CaseInsensitive); + if(archCompare != 0) + return archCompare < 0; + if(id < rhs.id) + { + return true; + } + if(id > rhs.id) + { + return false; + } + return Strings::naturalCompare(path, rhs.path, Qt::CaseInsensitive) < 0; +} + +bool JavaInstall::operator==(const JavaInstall &rhs) +{ + return arch == rhs.arch && id == rhs.id && path == rhs.path; +} + +bool JavaInstall::operator>(const JavaInstall &rhs) +{ + return (!operator<(rhs)) && (!operator==(rhs)); +} diff --git a/logic/java/JavaInstall.h b/logic/java/JavaInstall.h new file mode 100644 index 00000000..882c7386 --- /dev/null +++ b/logic/java/JavaInstall.h @@ -0,0 +1,38 @@ +#pragma once + +#include "BaseVersion.h" +#include "JavaVersion.h" + +struct JavaInstall : public BaseVersion +{ + JavaInstall(){} + JavaInstall(QString id, QString arch, QString path) + : id(id), arch(arch), path(path) + { + } + virtual QString descriptor() + { + return id.toString(); + } + + virtual QString name() + { + return id.toString(); + } + + virtual QString typeString() const + { + return arch; + } + + bool operator<(const JavaInstall & rhs); + bool operator==(const JavaInstall & rhs); + bool operator>(const JavaInstall & rhs); + + JavaVersion id; + QString arch; + QString path; + bool recommended = false; +}; + +typedef std::shared_ptr<JavaInstall> JavaInstallPtr; diff --git a/logic/java/JavaVersionList.cpp b/logic/java/JavaInstallList.cpp index e3929f45..fbd8ee9b 100644 --- a/logic/java/JavaVersionList.cpp +++ b/logic/java/JavaInstallList.cpp @@ -19,37 +19,37 @@ #include <QDebug> -#include "java/JavaVersionList.h" +#include "java/JavaInstallList.h" #include "java/JavaCheckerJob.h" #include "java/JavaUtils.h" #include "MMCStrings.h" #include "minecraft/VersionFilterData.h" -JavaVersionList::JavaVersionList(QObject *parent) : BaseVersionList(parent) +JavaInstallList::JavaInstallList(QObject *parent) : BaseVersionList(parent) { } -Task *JavaVersionList::getLoadTask() +Task *JavaInstallList::getLoadTask() { return new JavaListLoadTask(this); } -const BaseVersionPtr JavaVersionList::at(int i) const +const BaseVersionPtr JavaInstallList::at(int i) const { return m_vlist.at(i); } -bool JavaVersionList::isLoaded() +bool JavaInstallList::isLoaded() { return m_loaded; } -int JavaVersionList::count() const +int JavaInstallList::count() const { return m_vlist.count(); } -QVariant JavaVersionList::data(const QModelIndex &index, int role) const +QVariant JavaInstallList::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); @@ -57,7 +57,7 @@ QVariant JavaVersionList::data(const QModelIndex &index, int role) const if (index.row() > count()) return QVariant(); - auto version = std::dynamic_pointer_cast<JavaVersion>(m_vlist[index.row()]); + auto version = std::dynamic_pointer_cast<JavaInstall>(m_vlist[index.row()]); switch (role) { case VersionPointerRole: @@ -65,7 +65,7 @@ QVariant JavaVersionList::data(const QModelIndex &index, int role) const case VersionIdRole: return version->descriptor(); case VersionRole: - return version->id; + return version->id.toString(); case RecommendedRole: return version->recommended; case PathRole: @@ -77,37 +77,21 @@ QVariant JavaVersionList::data(const QModelIndex &index, int role) const } } -BaseVersionList::RoleList JavaVersionList::providesRoles() +BaseVersionList::RoleList JavaInstallList::providesRoles() { return {VersionPointerRole, VersionIdRole, VersionRole, RecommendedRole, PathRole, ArchitectureRole}; } -void JavaVersionList::updateListData(QList<BaseVersionPtr> versions) +void JavaInstallList::updateListData(QList<BaseVersionPtr> versions) { beginResetModel(); m_vlist = versions; m_loaded = true; - // manual testing fakery - /* - m_vlist.push_back(std::make_shared<JavaVersion>("1.6.0_33", "64", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.6.0_44", "64", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.6.0_55", "64", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.7.0_44", "64", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.8.0_44", "64", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.6.0_33", "32", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.6.0_44", "32", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.6.0_55", "32", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.7.0_44", "32", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.8.0_44", "32", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.9.0_1231", "32", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.9.0_1", "32", "/foo/bar/baz")); - m_vlist.push_back(std::make_shared<JavaVersion>("1.9.0_1", "64", "/foo/bar/baz")); - */ sortVersions(); if(m_vlist.size()) { - auto best = std::dynamic_pointer_cast<JavaVersion>(m_vlist[0]); + auto best = std::dynamic_pointer_cast<JavaInstall>(m_vlist[0]); best->recommended = true; } endResetModel(); @@ -115,35 +99,19 @@ void JavaVersionList::updateListData(QList<BaseVersionPtr> versions) bool sortJavas(BaseVersionPtr left, BaseVersionPtr right) { - auto rleft = std::dynamic_pointer_cast<JavaVersion>(left); - auto rright = std::dynamic_pointer_cast<JavaVersion>(right); - // prefer higher arch - auto archCompare = Strings::naturalCompare(rleft->arch, rright->arch, Qt::CaseInsensitive); - if(archCompare != 0) - return archCompare > 0; - // dirty hack - 1.9 and above is too new - auto labove19 = Strings::naturalCompare(rleft->name(), g_VersionFilterData.discouragedJavaVersion, Qt::CaseInsensitive) >= 0; - auto rabove19 = Strings::naturalCompare(rright->name(), g_VersionFilterData.discouragedJavaVersion, Qt::CaseInsensitive) >= 0; - if(labove19 == rabove19) - { - // prefer higher versions in general - auto nameCompare = Strings::naturalCompare(rleft->name(), rright->name(), Qt::CaseInsensitive); - if(nameCompare != 0) - return nameCompare > 0; - // if all else is equal, sort by path - return Strings::naturalCompare(rleft->path, rright->path, Qt::CaseInsensitive) < 0; - } - return labove19 < rabove19; + auto rleft = std::dynamic_pointer_cast<JavaInstall>(left); + auto rright = std::dynamic_pointer_cast<JavaInstall>(right); + return (*rleft) > (*rright); } -void JavaVersionList::sortVersions() +void JavaInstallList::sortVersions() { beginResetModel(); std::sort(m_vlist.begin(), m_vlist.end(), sortJavas); endResetModel(); } -JavaListLoadTask::JavaListLoadTask(JavaVersionList *vlist) : Task() +JavaListLoadTask::JavaListLoadTask(JavaInstallList *vlist) : Task() { m_list = vlist; m_currentRecommended = NULL; @@ -183,21 +151,21 @@ void JavaListLoadTask::executeTask() void JavaListLoadTask::javaCheckerFinished(QList<JavaCheckResult> results) { - QList<JavaVersionPtr> candidates; + QList<JavaInstallPtr> candidates; qDebug() << "Found the following valid Java installations:"; for(JavaCheckResult result : results) { if(result.valid) { - JavaVersionPtr javaVersion(new JavaVersion()); + JavaInstallPtr javaVersion(new JavaInstall()); javaVersion->id = result.javaVersion; javaVersion->arch = result.mojangPlatform; javaVersion->path = result.path; candidates.append(javaVersion); - qDebug() << " " << javaVersion->id << javaVersion->arch << javaVersion->path; + qDebug() << " " << javaVersion->id.toString() << javaVersion->arch << javaVersion->path; } } diff --git a/logic/java/JavaVersionList.h b/logic/java/JavaInstallList.h index 3acb5343..f2ec20f7 100644 --- a/logic/java/JavaVersionList.h +++ b/logic/java/JavaInstallList.h @@ -20,47 +20,19 @@ #include "BaseVersionList.h" #include "tasks/Task.h" -#include "java/JavaCheckerJob.h" + +#include "JavaCheckerJob.h" +#include "JavaInstall.h" #include "multimc_logic_export.h" class JavaListLoadTask; -struct JavaVersion : public BaseVersion -{ - JavaVersion(){} - JavaVersion(QString id, QString arch, QString path) - : id(id), arch(arch), path(path) - { - } - virtual QString descriptor() - { - return id; - } - - virtual QString name() - { - return id; - } - - virtual QString typeString() const - { - return arch; - } - - QString id; - QString arch; - QString path; - bool recommended = false; -}; - -typedef std::shared_ptr<JavaVersion> JavaVersionPtr; - -class MULTIMC_LOGIC_EXPORT JavaVersionList : public BaseVersionList +class MULTIMC_LOGIC_EXPORT JavaInstallList : public BaseVersionList { Q_OBJECT public: - explicit JavaVersionList(QObject *parent = 0); + explicit JavaInstallList(QObject *parent = 0); virtual Task *getLoadTask() override; virtual bool isLoaded() override; @@ -85,7 +57,7 @@ class JavaListLoadTask : public Task Q_OBJECT public: - explicit JavaListLoadTask(JavaVersionList *vlist); + explicit JavaListLoadTask(JavaInstallList *vlist); ~JavaListLoadTask(); virtual void executeTask(); @@ -94,6 +66,6 @@ public slots: protected: std::shared_ptr<JavaCheckerJob> m_job; - JavaVersionList *m_list; - JavaVersion *m_currentRecommended; + JavaInstallList *m_list; + JavaInstall *m_currentRecommended; }; diff --git a/logic/java/JavaUtils.cpp b/logic/java/JavaUtils.cpp index 7c3cc2a1..9dfb7897 100644 --- a/logic/java/JavaUtils.cpp +++ b/logic/java/JavaUtils.cpp @@ -23,15 +23,15 @@ #include <QDebug> #include "java/JavaUtils.h" #include "java/JavaCheckerJob.h" -#include "java/JavaVersionList.h" +#include "java/JavaInstallList.h" JavaUtils::JavaUtils() { } -JavaVersionPtr JavaUtils::MakeJavaPtr(QString path, QString id, QString arch) +JavaInstallPtr JavaUtils::MakeJavaPtr(QString path, QString id, QString arch) { - JavaVersionPtr javaVersion(new JavaVersion()); + JavaInstallPtr javaVersion(new JavaInstall()); javaVersion->id = id; javaVersion->arch = arch; @@ -40,9 +40,9 @@ JavaVersionPtr JavaUtils::MakeJavaPtr(QString path, QString id, QString arch) return javaVersion; } -JavaVersionPtr JavaUtils::GetDefaultJava() +JavaInstallPtr JavaUtils::GetDefaultJava() { - JavaVersionPtr javaVersion(new JavaVersion()); + JavaInstallPtr javaVersion(new JavaInstall()); javaVersion->id = "java"; javaVersion->arch = "unknown"; @@ -52,9 +52,9 @@ JavaVersionPtr JavaUtils::GetDefaultJava() } #if WINDOWS -QList<JavaVersionPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName) +QList<JavaInstallPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName) { - QList<JavaVersionPtr> javas; + QList<JavaInstallPtr> javas; QString archType = "unknown"; if (keyType == KEY_WOW64_64KEY) @@ -114,7 +114,7 @@ QList<JavaVersionPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString &valueSz); // Now, we construct the version object and add it to the list. - JavaVersionPtr javaVersion(new JavaVersion()); + JavaInstallPtr javaVersion(new JavaInstall()); javaVersion->id = subKeyName; javaVersion->arch = archType; @@ -137,15 +137,15 @@ QList<JavaVersionPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString QList<QString> JavaUtils::FindJavaPaths() { - QList<JavaVersionPtr> java_candidates; + QList<JavaInstallPtr> java_candidates; - QList<JavaVersionPtr> JRE64s = this->FindJavaFromRegistryKey( + QList<JavaInstallPtr> JRE64s = this->FindJavaFromRegistryKey( KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); - QList<JavaVersionPtr> JDK64s = this->FindJavaFromRegistryKey( + QList<JavaInstallPtr> JDK64s = this->FindJavaFromRegistryKey( KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit"); - QList<JavaVersionPtr> JRE32s = this->FindJavaFromRegistryKey( + QList<JavaInstallPtr> JRE32s = this->FindJavaFromRegistryKey( KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); - QList<JavaVersionPtr> JDK32s = this->FindJavaFromRegistryKey( + QList<JavaInstallPtr> JDK32s = this->FindJavaFromRegistryKey( KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit"); java_candidates.append(JRE64s); @@ -159,7 +159,7 @@ QList<QString> JavaUtils::FindJavaPaths() java_candidates.append(MakeJavaPtr(this->GetDefaultJava()->path)); QList<QString> candidates; - for(JavaVersionPtr java_candidate : java_candidates) + for(JavaInstallPtr java_candidate : java_candidates) { if(!candidates.contains(java_candidate->path)) { diff --git a/logic/java/JavaUtils.h b/logic/java/JavaUtils.h index 78693b37..b671d0a5 100644 --- a/logic/java/JavaUtils.h +++ b/logic/java/JavaUtils.h @@ -20,7 +20,7 @@ #include "JavaCheckerJob.h" #include "JavaChecker.h" -#include "JavaVersionList.h" +#include "JavaInstallList.h" #ifdef Q_OS_WIN #include <windows.h> @@ -34,11 +34,11 @@ class MULTIMC_LOGIC_EXPORT JavaUtils : public QObject public: JavaUtils(); - JavaVersionPtr MakeJavaPtr(QString path, QString id = "unknown", QString arch = "unknown"); + JavaInstallPtr MakeJavaPtr(QString path, QString id = "unknown", QString arch = "unknown"); QList<QString> FindJavaPaths(); - JavaVersionPtr GetDefaultJava(); + JavaInstallPtr GetDefaultJava(); #ifdef Q_OS_WIN - QList<JavaVersionPtr> FindJavaFromRegistryKey(DWORD keyType, QString keyName); + QList<JavaInstallPtr> FindJavaFromRegistryKey(DWORD keyType, QString keyName); #endif }; diff --git a/logic/java/JavaVersion.cpp b/logic/java/JavaVersion.cpp new file mode 100644 index 00000000..84fc48a4 --- /dev/null +++ b/logic/java/JavaVersion.cpp @@ -0,0 +1,112 @@ +#include "JavaVersion.h" +#include <MMCStrings.h> + +#include <QRegularExpression> +#include <QString> + +JavaVersion & JavaVersion::operator=(const QString & javaVersionString) +{ + string = javaVersionString; + + auto getCapturedInteger = [](const QRegularExpressionMatch & match, const QString &what) -> int + { + auto str = match.captured(what); + if(str.isEmpty()) + { + return 0; + } + return str.toInt(); + }; + + QRegularExpression pattern; + if(javaVersionString.startsWith("1.")) + { + pattern = QRegularExpression ("1[.](?<major>[0-9]+)([.](?<minor>[0-9]+))?(_(?<security>[0-9]+)?)?(-(?<prerelease>[a-zA-Z0-9]+))?"); + } + else + { + pattern = QRegularExpression("(?<major>[0-9]+)([.](?<minor>[0-9]+))?([.](?<security>[0-9]+))?(-(?<prerelease>[a-zA-Z0-9]+))?"); + } + + auto match = pattern.match(string); + parseable = match.hasMatch(); + major = getCapturedInteger(match, "major"); + minor = getCapturedInteger(match, "minor"); + security = getCapturedInteger(match, "security"); + prerelease = match.captured("prerelease"); + return *this; +} + +JavaVersion::JavaVersion(const QString &rhs) +{ + operator=(rhs); +} + +QString JavaVersion::toString() +{ + return string; +} + +bool JavaVersion::requiresPermGen() +{ + if(parseable) + { + return major < 8; + } + return true; +} + +bool JavaVersion::operator<(const JavaVersion &rhs) +{ + if(parseable && rhs.parseable) + { + if(major < rhs.major) + return true; + if(major > rhs.major) + return false; + if(minor < rhs.minor) + return true; + if(minor > rhs.minor) + return false; + if(security < rhs.security) + return true; + if(security > rhs.security) + return false; + + // everything else being equal, consider prerelease status + bool thisPre = !prerelease.isEmpty(); + bool rhsPre = !rhs.prerelease.isEmpty(); + if(thisPre && !rhsPre) + { + // this is a prerelease and the other one isn't -> lesser + return true; + } + else if(!thisPre && rhsPre) + { + // this isn't a prerelease and the other one is -> greater + return false; + } + else if(thisPre && rhsPre) + { + // both are prereleases - use natural compare... + return Strings::naturalCompare(prerelease, rhs.prerelease, Qt::CaseSensitive) < 0; + } + // neither is prerelease, so they are the same -> this cannot be less than rhs + return false; + } + else return Strings::naturalCompare(string, rhs.string, Qt::CaseSensitive) < 0; +} + +bool JavaVersion::operator==(const JavaVersion &rhs) +{ + if(parseable && rhs.parseable) + { + return major == rhs.major && minor == rhs.minor && security == rhs.security && prerelease == rhs.prerelease; + } + return string == rhs.string; +} + +bool JavaVersion::operator>(const JavaVersion &rhs) +{ + return (!operator<(rhs)) && (!operator==(rhs)); +} diff --git a/logic/java/JavaVersion.h b/logic/java/JavaVersion.h new file mode 100644 index 00000000..f9a733d3 --- /dev/null +++ b/logic/java/JavaVersion.h @@ -0,0 +1,30 @@ +#pragma once + +#include "multimc_logic_export.h" +#include <QString> + +class MULTIMC_LOGIC_EXPORT JavaVersion +{ + friend class JavaVersionTest; +public: + JavaVersion() {}; + JavaVersion(const QString & rhs); + + JavaVersion & operator=(const QString & rhs); + + bool operator<(const JavaVersion & rhs); + bool operator==(const JavaVersion & rhs); + bool operator>(const JavaVersion & rhs); + + bool requiresPermGen(); + + QString toString(); + +private: + QString string; + int major = 0; + int minor = 0; + int security = 0; + bool parseable = false; + QString prerelease; +}; diff --git a/logic/launch/steps/CheckJava.cpp b/logic/launch/steps/CheckJava.cpp index 66f7cc2b..a4eaa307 100644 --- a/logic/launch/steps/CheckJava.cpp +++ b/logic/launch/steps/CheckJava.cpp @@ -83,9 +83,9 @@ void CheckJava::checkJavaFinished(JavaCheckResult result) else { auto instance = m_parent->instance(); - emit logLine(tr("Java version is %1!\n").arg(result.javaVersion), + emit logLine(tr("Java version is %1!\n").arg(result.javaVersion.toString()), MessageLevel::MultiMC); - instance->settings()->set("JavaVersion", result.javaVersion); + instance->settings()->set("JavaVersion", result.javaVersion.toString()); instance->settings()->set("JavaTimestamp", m_javaUnixTime); emitSucceeded(); } diff --git a/logic/minecraft/MinecraftInstance.cpp b/logic/minecraft/MinecraftInstance.cpp index 05dedf1d..405ccd26 100644 --- a/logic/minecraft/MinecraftInstance.cpp +++ b/logic/minecraft/MinecraftInstance.cpp @@ -7,6 +7,7 @@ #include <pathmatcher/RegexpMatcher.h> #include <pathmatcher/MultiMatcher.h> #include <FileSystem.h> +#include <java/JavaVersion.h> #define IBUS "@im=ibus" @@ -104,8 +105,8 @@ QStringList MinecraftInstance::javaArguments() const args << QString("-Xmx%1m").arg(settings()->get("MaxMemAlloc").toInt()); // No PermGen in newer java. - auto javaVersion = settings()->get("JavaVersion"); - if(Strings::naturalCompare(javaVersion.toString(), "1.8.0", Qt::CaseInsensitive) < 0) + JavaVersion javaVersion(settings()->get("JavaVersion").toString()); + if(javaVersion.requiresPermGen()) { auto permgen = settings()->get("PermGen").toInt(); if (permgen != 64) diff --git a/logic/minecraft/VersionFilterData.cpp b/logic/minecraft/VersionFilterData.cpp index 8270a490..0c4a6e3d 100644 --- a/logic/minecraft/VersionFilterData.cpp +++ b/logic/minecraft/VersionFilterData.cpp @@ -72,5 +72,4 @@ VersionFilterData::VersionFilterData() // Version list magic recommendedMinecraftVersion = "1.7.10"; - discouragedJavaVersion = "1.9.0"; } diff --git a/logic/minecraft/VersionFilterData.h b/logic/minecraft/VersionFilterData.h index 98db2484..f7d4ebe7 100644 --- a/logic/minecraft/VersionFilterData.h +++ b/logic/minecraft/VersionFilterData.h @@ -28,7 +28,5 @@ struct VersionFilterData QSet<QString> lwjglWhitelist; // Currently recommended minecraft version QString recommendedMinecraftVersion; - // Currently discouraged java version (anything equal and above will be discouraged) - QString discouragedJavaVersion; }; extern VersionFilterData MULTIMC_LOGIC_EXPORT g_VersionFilterData; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index efbcacbf..89bf63ee 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -30,6 +30,7 @@ add_unit_test(filematchers tst_filematchers.cpp) add_unit_test(ModList tst_ModList.cpp) add_unit_test(Resource tst_Resource.cpp) add_unit_test(GZip tst_GZip.cpp) +add_unit_test(JavaVersion tst_JavaVersion.cpp) # Tests END # diff --git a/tests/tst_JavaVersion.cpp b/tests/tst_JavaVersion.cpp new file mode 100644 index 00000000..708c8d8d --- /dev/null +++ b/tests/tst_JavaVersion.cpp @@ -0,0 +1,120 @@ +#include <QTest> +#include "TestUtil.h" + +#include "java/JavaVersion.h" + +class JavaVersionTest : public QObject +{ + Q_OBJECT +private +slots: + void test_Parse_data() + { + QTest::addColumn<QString>("string"); + QTest::addColumn<int>("major"); + QTest::addColumn<int>("minor"); + QTest::addColumn<int>("security"); + QTest::addColumn<QString>("prerelease"); + + QTest::newRow("old format") << "1.6.0_33" << 6 << 0 << 33 << QString(); + QTest::newRow("old format prerelease") << "1.9.0_1-ea" << 9 << 0 << 1 << "ea"; + + QTest::newRow("new format major") << "9" << 9 << 0 << 0 << QString(); + QTest::newRow("new format minor") << "9.1" << 9 << 1 << 0 << QString(); + QTest::newRow("new format security") << "9.0.1" << 9 << 0 << 1 << QString(); + QTest::newRow("new format prerelease") << "9-ea" << 9 << 0 << 0 << "ea"; + QTest::newRow("new format long prerelease") << "9.0.1-ea" << 9 << 0 << 1 << "ea"; + } + void test_Parse() + { + QFETCH(QString, string); + QFETCH(int, major); + QFETCH(int, minor); + QFETCH(int, security); + QFETCH(QString, prerelease); + + JavaVersion test(string); + QCOMPARE(test.string, string); + QCOMPARE(test.toString(), string); + QCOMPARE(test.major, major); + QCOMPARE(test.minor, minor); + QCOMPARE(test.security, security); + QCOMPARE(test.prerelease, prerelease); + } + + void test_Sort_data() + { + QTest::addColumn<QString>("lhs"); + QTest::addColumn<QString>("rhs"); + QTest::addColumn<bool>("smaller"); + QTest::addColumn<bool>("equal"); + QTest::addColumn<bool>("bigger"); + + // old format and new format equivalence + QTest::newRow("1.6.0_33 == 6.0.33") << "1.6.0_33" << "6.0.33" << false << true << false; + // old format major version + QTest::newRow("1.5.0_33 < 1.6.0_33") << "1.5.0_33" << "1.6.0_33" << true << false << false; + // new format - first release vs first security patch + QTest::newRow("9 < 9.0.1") << "9" << "9.0.1" << true << false << false; + QTest::newRow("9.0.1 > 9") << "9.0.1" << "9" << false << false << true; + // new format - first minor vs first release/security patch + QTest::newRow("9.1 > 9.0.1") << "9.1" << "9.0.1" << false << false << true; + QTest::newRow("9.0.1 < 9.1") << "9.0.1" << "9.1" << true << false << false; + QTest::newRow("9.1 > 9") << "9.1" << "9" << false << false << true; + QTest::newRow("9 > 9.1") << "9" << "9.1" << true << false << false; + // new format - omitted numbers + QTest::newRow("9 == 9.0") << "9" << "9.0" << false << true << false; + QTest::newRow("9 == 9.0.0") << "9" << "9.0.0" << false << true << false; + QTest::newRow("9.0 == 9.0.0") << "9.0" << "9.0.0" << false << true << false; + // early access and prereleases compared to final release + QTest::newRow("9-ea < 9") << "9-ea" << "9" << true << false << false; + QTest::newRow("9 < 9.0.1-ea") << "9" << "9.0.1-ea" << true << false << false; + QTest::newRow("9.0.1-ea > 9") << "9.0.1-ea" << "9" << false << false << true; + // prerelease difference only testing + QTest::newRow("9-1 == 9-1") << "9-1" << "9-1" << false << true << false; + QTest::newRow("9-1 < 9-2") << "9-1" << "9-2" << true << false << false; + QTest::newRow("9-5 < 9-20") << "9-5" << "9-20" << true << false << false; + QTest::newRow("9-rc1 < 9-rc2") << "9-rc1" << "9-rc2" << true << false << false; + QTest::newRow("9-rc5 < 9-rc20") << "9-rc5" << "9-rc20" << true << false << false; + QTest::newRow("9-rc < 9-rc2") << "9-rc" << "9-rc2" << true << false << false; + QTest::newRow("9-ea < 9-rc") << "9-ea" << "9-rc" << true << false << false; + } + void test_Sort() + { + QFETCH(QString, lhs); + QFETCH(QString, rhs); + QFETCH(bool, smaller); + QFETCH(bool, equal); + QFETCH(bool, bigger); + JavaVersion lver(lhs); + JavaVersion rver(rhs); + QCOMPARE(lver < rver, smaller); + QCOMPARE(lver == rver, equal); + QCOMPARE(lver > rver, bigger); + } + void test_PermGen_data() + { + QTest::addColumn<QString>("version"); + QTest::addColumn<bool>("needs_permgen"); + QTest::newRow("1.6.0_33") << "1.6.0_33" << true; + QTest::newRow("1.7.0_60") << "1.7.0_60" << true; + QTest::newRow("1.8.0_22") << "1.8.0_22" << false; + QTest::newRow("9-ea") << "9-ea" << false; + QTest::newRow("9.2.4") << "9.2.4" << false; + } + void test_PermGen() + { + QFETCH(QString, version); + QFETCH(bool, needs_permgen); + JavaVersion v(version); + QCOMPARE(needs_permgen, v.requiresPermGen()); + } +}; + +QTEST_GUILESS_MAIN(JavaVersionTest) + +#include "tst_JavaVersion.moc" + + + // manual testing fakery + |