summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2016-01-02 00:35:54 +0100
committerPetr Mrázek <peterix@gmail.com>2016-01-02 00:35:54 +0100
commita008efd24e81441a23ff3e81320ac3522251327e (patch)
treef73886925814cc4cfb397be9f8342f7963d8f8d7
parent5f57df81109d268c79b34aac799fc7694ec5882a (diff)
downloadMultiMC-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
-rw-r--r--application/JavaCommon.cpp4
-rw-r--r--application/MainWindow.cpp6
-rw-r--r--application/MultiMC.cpp4
-rw-r--r--application/MultiMC.h6
-rw-r--r--application/pages/InstanceSettingsPage.cpp6
-rw-r--r--application/pages/global/JavaPage.cpp6
-rw-r--r--depends/launcher/org/multimc/Utils.java8
-rw-r--r--logic/CMakeLists.txt12
-rw-r--r--logic/java/JavaChecker.h7
-rw-r--r--logic/java/JavaInstall.cpp28
-rw-r--r--logic/java/JavaInstall.h38
-rw-r--r--logic/java/JavaInstallList.cpp (renamed from logic/java/JavaVersionList.cpp)72
-rw-r--r--logic/java/JavaInstallList.h (renamed from logic/java/JavaVersionList.h)44
-rw-r--r--logic/java/JavaUtils.cpp28
-rw-r--r--logic/java/JavaUtils.h8
-rw-r--r--logic/java/JavaVersion.cpp112
-rw-r--r--logic/java/JavaVersion.h30
-rw-r--r--logic/launch/steps/CheckJava.cpp4
-rw-r--r--logic/minecraft/MinecraftInstance.cpp5
-rw-r--r--logic/minecraft/VersionFilterData.cpp1
-rw-r--r--logic/minecraft/VersionFilterData.h2
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/tst_JavaVersion.cpp120
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
+