Better (but unsorted) Java detection

This commit is contained in:
Sky 2013-12-11 03:54:39 +00:00
parent ab69c1b9e6
commit afa5e14e20
13 changed files with 338 additions and 87 deletions

View File

@ -388,6 +388,8 @@ logic/NagUtils.h
logic/NagUtils.cpp
logic/SkinUtils.h
logic/SkinUtils.cpp
logic/JavaCheckerJob.h
logic/JavaCheckerJob.cpp
# Assets
logic/assets/AssetsUtils.h

View File

@ -2,13 +2,23 @@ import java.lang.Integer;
public class JavaCheck
{
private static final String key = "os.arch";
private static final String[] keys = {"os.arch", "java.version"};
public static void main (String [] args)
{
String property = System.getProperty(key);
System.out.println(key + "=" + property);
if (property != null)
System.exit(0);
System.exit(1);
int ret = 0;
for(String key : keys)
{
String property = System.getProperty(key);
if(property != null)
{
System.out.println(key + "=" + property);
}
else
{
ret = 1;
}
}
System.exit(ret);
}
}

View File

@ -220,7 +220,8 @@ void InstanceSettings::on_javaTestBtn_clicked()
checker.reset(new JavaChecker());
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
SLOT(checkFinished(JavaCheckResult)));
checker->performCheck(ui->javaPathTextBox->text());
checker->path = ui->javaPathTextBox->text();
checker->performCheck();
}
void InstanceSettings::checkFinished(JavaCheckResult result)

View File

@ -259,7 +259,8 @@ void SettingsDialog::on_javaTestBtn_clicked()
checker.reset(new JavaChecker());
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
SLOT(checkFinished(JavaCheckResult)));
checker->performCheck(ui->javaPathTextBox->text());
checker->path = ui->javaPathTextBox->text();
checker->performCheck();
}
void SettingsDialog::checkFinished(JavaCheckResult result)
@ -271,7 +272,8 @@ void SettingsDialog::checkFinished(JavaCheckResult result)
if (result.is_64bit)
text += "Using 64bit java.\n";
text += "\n";
text += "Platform reported: " + result.realPlatform;
text += "Platform reported: " + result.realPlatform + "\n";
text += "Java version reported: " + result.javaVersion;
QMessageBox::information(this, tr("Java test success"), text);
}
else

View File

@ -1,6 +1,7 @@
#include "JavaChecker.h"
#include <QFile>
#include <QProcess>
#include <QMap>
#define CHECKER_FILE "JavaChecker.jar"
@ -8,7 +9,7 @@ JavaChecker::JavaChecker(QObject *parent) : QObject(parent)
{
}
void JavaChecker::performCheck(QString path)
void JavaChecker::performCheck()
{
if(QFile::exists(CHECKER_FILE))
{
@ -40,30 +41,53 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
QProcessPtr _process;
_process.swap(process);
if (status == QProcess::CrashExit || exitcode == 1)
{
emit checkFinished({});
return;
}
QString p_stdout = _process->readAllStandardOutput();
auto parts = p_stdout.split('=', QString::SkipEmptyParts);
if (parts.size() != 2 || parts[0] != "os.arch")
{
emit checkFinished({});
return;
}
auto os_arch = parts[1].remove('\n').remove('\r');
bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
JavaCheckResult result;
{
result.valid = true;
result.is_64bit = is_64;
result.mojangPlatform = is_64 ? "64" : "32";
result.realPlatform = os_arch;
result.path = path;
}
if (status == QProcess::CrashExit || exitcode == 1)
{
emit checkFinished(result);
return;
}
bool success = true;
QString p_stdout = _process->readAllStandardOutput();
QMap<QString, QString> results;
QStringList lines = p_stdout.split("\n", QString::SkipEmptyParts);
for(QString line : lines)
{
line = line.trimmed();
auto parts = line.split('=', QString::SkipEmptyParts);
if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty())
{
success = false;
}
else
{
results.insert(parts[0], parts[1]);
}
}
if(!results.contains("os.arch") || !results.contains("java.version") || !success)
{
emit checkFinished(result);
return;
}
auto os_arch = results["os.arch"];
auto java_version = results["java.version"];
bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
result.valid = true;
result.is_64bit = is_64;
result.mojangPlatform = is_64 ? "64" : "32";
result.realPlatform = os_arch;
result.javaVersion = java_version;
emit checkFinished(result);
}
@ -72,7 +96,13 @@ void JavaChecker::error(QProcess::ProcessError err)
if(err == QProcess::FailedToStart)
{
killTimer.stop();
emit checkFinished({});
JavaCheckResult result;
{
result.path = path;
}
emit checkFinished(result);
return;
}
}

View File

@ -3,21 +3,28 @@
#include <QTimer>
#include <memory>
class JavaChecker;
struct JavaCheckResult
{
QString path;
QString mojangPlatform;
QString realPlatform;
QString javaVersion;
bool valid = false;
bool is_64bit = false;
};
typedef std::shared_ptr<QProcess> QProcessPtr;
typedef std::shared_ptr<QProcess> QProcessPtr;
typedef std::shared_ptr<JavaChecker> JavaCheckerPtr;
class JavaChecker : public QObject
{
Q_OBJECT
public:
explicit JavaChecker(QObject *parent = 0);
void performCheck(QString path);
void performCheck();
QString path;
signals:
void checkFinished(JavaCheckResult result);

49
logic/JavaCheckerJob.cpp Normal file
View File

@ -0,0 +1,49 @@
/* Copyright 2013 MultiMC Contributors
*
* 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.
*/
#include "JavaCheckerJob.h"
#include "pathutils.h"
#include "MultiMC.h"
#include "logger/QsLog.h"
void JavaCheckerJob::partFinished(JavaCheckResult result)
{
num_finished++;
QLOG_INFO() << m_job_name.toLocal8Bit() << "progress:" << num_finished << "/"
<< javacheckers.size();
emit progress(num_finished, javacheckers.size());
javaresults.append(result);
int result_size = javacheckers.size();
emit progress(num_finished, result_size);
if (num_finished == javacheckers.size())
{
emit finished(javaresults);
}
}
void JavaCheckerJob::start()
{
QLOG_INFO() << m_job_name.toLocal8Bit() << " started.";
m_running = true;
for (auto iter : javacheckers)
{
connect(iter.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult)));
iter->performCheck();
}
}

100
logic/JavaCheckerJob.h Normal file
View File

@ -0,0 +1,100 @@
/* Copyright 2013 MultiMC Contributors
*
* 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.
*/
#pragma once
#include <QtNetwork>
#include <QLabel>
#include "JavaChecker.h"
#include "logic/tasks/ProgressProvider.h"
class JavaCheckerJob;
typedef std::shared_ptr<JavaCheckerJob> JavaCheckerJobPtr;
class JavaCheckerJob : public ProgressProvider
{
Q_OBJECT
public:
explicit JavaCheckerJob(QString job_name) : ProgressProvider(), m_job_name(job_name) {};
bool addJavaCheckerAction(JavaCheckerPtr base)
{
javacheckers.append(base);
total_progress++;
// if this is already running, the action needs to be started right away!
if (isRunning())
{
emit progress(current_progress, total_progress);
connect(base.get(), SIGNAL(checkFinished(JavaCheckResult)), SLOT(partFinished(JavaCheckResult)));
base->performCheck();
}
return true;
}
JavaCheckerPtr operator[](int index)
{
return javacheckers[index];
}
;
JavaCheckerPtr first()
{
if (javacheckers.size())
return javacheckers[0];
return JavaCheckerPtr();
}
int size() const
{
return javacheckers.size();
}
virtual void getProgress(qint64 &current, qint64 &total)
{
current = current_progress;
total = total_progress;
}
;
virtual QString getStatus() const
{
return m_job_name;
}
;
virtual bool isRunning() const
{
return m_running;
}
;
signals:
void started();
void progress(int current, int total);
void finished(QList<JavaCheckResult>);
public
slots:
virtual void start();
// FIXME: implement
virtual void abort() {};
private
slots:
void partFinished(JavaCheckResult result);
private:
QString m_job_name;
QList<JavaCheckerPtr> javacheckers;
QList<JavaCheckResult> javaresults;
qint64 current_progress = 0;
qint64 total_progress = 0;
int num_finished = 0;
bool m_running = false;
};

View File

@ -26,11 +26,24 @@
#include "JavaUtils.h"
#include "logger/QsLog.h"
#include "gui/dialogs/VersionSelectDialog.h"
#include "JavaCheckerJob.h"
#include "lists/JavaVersionList.h"
JavaUtils::JavaUtils()
{
}
JavaVersionPtr JavaUtils::MakeJavaPtr(QString path, QString id, QString arch)
{
JavaVersionPtr javaVersion(new JavaVersion());
javaVersion->id = id;
javaVersion->arch = arch;
javaVersion->path = path;
return javaVersion;
}
JavaVersionPtr JavaUtils::GetDefaultJava()
{
JavaVersionPtr javaVersion(new JavaVersion());
@ -38,7 +51,6 @@ JavaVersionPtr JavaUtils::GetDefaultJava()
javaVersion->id = "java";
javaVersion->arch = "unknown";
javaVersion->path = "java";
javaVersion->recommended = false;
return javaVersion;
}
@ -112,7 +124,6 @@ QList<JavaVersionPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString
javaVersion->arch = archType;
javaVersion->path =
QDir(PathCombine(value, "bin")).absoluteFilePath("java.exe");
javaVersion->recommended = (recommended == subKeyName);
javas.append(javaVersion);
}
@ -130,7 +141,7 @@ QList<JavaVersionPtr> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString
QList<JavaVersionPtr> JavaUtils::FindJavaPaths()
{
QList<JavaVersionPtr> javas;
QList<JavaVersionPtr> candidates;
QList<JavaVersionPtr> JRE64s = this->FindJavaFromRegistryKey(
KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
@ -141,30 +152,21 @@ QList<JavaVersionPtr> JavaUtils::FindJavaPaths()
QList<JavaVersionPtr> JDK32s = this->FindJavaFromRegistryKey(
KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit");
javas.append(JRE64s);
javas.append(JDK64s);
javas.append(JRE32s);
javas.append(JDK32s);
candidates.append(JRE64s);
candidates.append(JDK64s);
candidates.append(JRE32s);
candidates.append(JDK32s);
if (javas.size() <= 0)
{
QLOG_WARN() << "Failed to find Java in the Windows registry - defaulting to \"java\"";
javas.append(this->GetDefaultJava());
return javas;
}
candidates.append(MakeJavaPtr("C:/Program Files/Java/jre7/bin/java.exe"));
candidates.append(MakeJavaPtr("C:/Program Files/Java/jre6/bin/java.exe"));
candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre7/bin/java.exe"));
candidates.append(MakeJavaPtr("C:/Program Files (x86)/Java/jre6/bin/java.exe"));
QLOG_INFO() << "Found the following Java installations (64 -> 32, JRE -> JDK): ";
candidates.append(this->GetDefaultJava());
for (auto &java : javas)
{
QString sRec;
if (java->recommended)
sRec = "(Recommended)";
QLOG_INFO() << java->id << java->arch << " at " << java->path << sRec;
}
return javas;
return candidates;
}
#elif OSX
QList<JavaVersionPtr> JavaUtils::FindJavaPaths()
{

View File

@ -19,21 +19,23 @@
#include <QWidget>
#include <osutils.h>
#include "logic/lists/JavaVersionList.h"
#include "JavaCheckerJob.h"
#include "JavaChecker.h"
#include "lists/JavaVersionList.h"
#if WINDOWS
#include <windows.h>
#endif
class JavaUtils
class JavaUtils : public QObject
{
Q_OBJECT
public:
JavaUtils();
JavaVersionPtr MakeJavaPtr(QString path, QString id = "unknown", QString arch = "unknown");
QList<JavaVersionPtr> FindJavaPaths();
JavaVersionPtr GetDefaultJava();
private:
#if WINDOWS
QList<JavaVersionPtr> FindJavaFromRegistryKey(DWORD keyType, QString keyName);

View File

@ -64,7 +64,8 @@ void OneSixUpdate::executeTask()
checker.reset(new JavaChecker());
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
SLOT(checkFinishedOffline(JavaCheckResult)));
checker->performCheck(java_path);
checker->path = java_path;
checker->performCheck();
return;
}
@ -95,7 +96,8 @@ void OneSixUpdate::checkJavaOnline()
checker.reset(new JavaChecker());
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
SLOT(checkFinishedOnline(JavaCheckResult)));
checker->performCheck(java_path);
checker->path = java_path;
checker->performCheck();
}
void OneSixUpdate::checkFinishedOnline(JavaCheckResult result)

View File

@ -21,7 +21,8 @@
#include <QRegExp>
#include "logger/QsLog.h"
#include <logic/JavaUtils.h>
#include "logic/JavaCheckerJob.h"
#include "logic/JavaUtils.h"
JavaVersionList::JavaVersionList(QObject *parent) : BaseVersionList(parent)
{
@ -49,7 +50,7 @@ int JavaVersionList::count() const
int JavaVersionList::columnCount(const QModelIndex &parent) const
{
return 4;
return 3;
}
QVariant JavaVersionList::data(const QModelIndex &index, int role) const
@ -75,9 +76,6 @@ QVariant JavaVersionList::data(const QModelIndex &index, int role) const
case 2:
return version->path;
case 3:
return version->recommended ? tr("Yes") : tr("No");
default:
return QVariant();
}
@ -109,9 +107,6 @@ QVariant JavaVersionList::headerData(int section, Qt::Orientation orientation, i
case 2:
return "Path";
case 3:
return "Recommended";
default:
return QVariant();
}
@ -128,9 +123,6 @@ QVariant JavaVersionList::headerData(int section, Qt::Orientation orientation, i
case 2:
return "Path to this Java version.";
case 3:
return "Whether the version is recommended or not.";
default:
return QVariant();
}
@ -142,15 +134,15 @@ QVariant JavaVersionList::headerData(int section, Qt::Orientation orientation, i
BaseVersionPtr JavaVersionList::getTopRecommended() const
{
for (int i = 0; i < m_vlist.length(); i++)
auto first = m_vlist.first();
if(first != nullptr)
{
auto ver = std::dynamic_pointer_cast<JavaVersion>(m_vlist.at(i));
if (ver->recommended)
{
return m_vlist.at(i);
}
return first;
}
else
{
return BaseVersionPtr();
}
return BaseVersionPtr();
}
void JavaVersionList::updateListData(QList<BaseVersionPtr> versions)
@ -182,17 +174,66 @@ void JavaListLoadTask::executeTask()
{
setStatus("Detecting Java installations...");
QSet<QString> candidate_paths;
JavaUtils ju;
QList<JavaVersionPtr> javas = ju.FindJavaPaths();
QList<JavaVersionPtr> candidates = ju.FindJavaPaths();
for(JavaVersionPtr &candidate : candidates)
{
candidate_paths.insert(candidate->path);
}
auto job = new JavaCheckerJob("Java detection");
connect(job, SIGNAL(finished(QList<JavaCheckResult>)), this, SLOT(javaCheckerFinished(QList<JavaCheckResult>)));
connect(job, SIGNAL(progress(int, int)), this, SLOT(checkerProgress(int, int)));
for(const QString candidate : candidate_paths)
{
auto candidate_checker = new JavaChecker();
candidate_checker->path = candidate;
job->addJavaCheckerAction(JavaCheckerPtr(candidate_checker));
}
QLOG_DEBUG() << "Starting java checker job with" << job->size() << "candidates";
job->start();
}
void JavaListLoadTask::checkerProgress(int current, int total)
{
float progress = (current * 100.0) / (current + total);
this->setProgress((int) progress);
}
void JavaListLoadTask::javaCheckerFinished(QList<JavaCheckResult> results)
{
QList<JavaVersionPtr> candidates;
QLOG_DEBUG() << "Got Java checker results:";
for(JavaCheckResult result : results)
{
if(result.valid)
{
JavaVersionPtr javaVersion(new JavaVersion());
javaVersion->id = result.javaVersion;
javaVersion->arch = result.mojangPlatform;
javaVersion->path = result.path;
candidates.append(javaVersion);
QLOG_DEBUG() << javaVersion->id << javaVersion->arch << javaVersion->path;
}
}
QList<BaseVersionPtr> javas_bvp;
for (int i = 0; i < javas.length(); i++)
for (auto &java : candidates)
{
BaseVersionPtr java = std::dynamic_pointer_cast<BaseVersion>(javas.at(i));
//QLOG_INFO() << java->id << java->arch << " at " << java->path;
BaseVersionPtr bp_java = std::dynamic_pointer_cast<BaseVersion>(java);
if (java)
if (bp_java)
{
javas_bvp.append(java);
javas_bvp.append(bp_java);
}
}

View File

@ -20,6 +20,7 @@
#include "BaseVersionList.h"
#include "logic/tasks/Task.h"
#include "logic/JavaCheckerJob.h"
class JavaListLoadTask;
@ -43,7 +44,6 @@ struct JavaVersion : public BaseVersion
QString id;
QString arch;
QString path;
bool recommended;
};
typedef std::shared_ptr<JavaVersion> JavaVersionPtr;
@ -85,6 +85,9 @@ public:
~JavaListLoadTask();
virtual void executeTask();
public slots:
void javaCheckerFinished(QList<JavaCheckResult> results);
void checkerProgress(int current, int total);
protected:
JavaVersionList *m_list;