Not sure what I changed here... but it's faster now

This commit is contained in:
Josh Larson
2017-06-06 20:57:05 -04:00
parent 54964334ef
commit e000100067
72 changed files with 780 additions and 386 deletions

View File

@@ -2,32 +2,11 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="lib" path="lib/sqlite-jdbc-3.8.11.2.jar"/>
<classpathentry kind="lib" path="lib/fast-json-1.4.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="lib" path="lib/org.eclipse.jgit-4.6.0.201612231935-r.jar">
<attributes>
<attribute name="javadoc_location" value="jar:platform:/resource/Lightspeed/lib/org.eclipse.jgit-4.6.0.201612231935-r-javadoc.jar!/"/>
</attributes>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/">
<accessrules>
<accessrule kind="accessible" pattern="javafx/**"/>
</accessrules>
</classpathentry>
<classpathentry kind="lib" path="lib/slf4j-nop-1.7.24.jar"/>
<classpathentry kind="lib" path="lib/slf4j-api-1.7.24.jar"/>
<classpathentry kind="lib" path="lib/jsch-0.1.54.jar"/>
<classpathentry kind="lib" path="lib/ClientHolocore.jar">
<attributes>
<attribute name="javadoc_location" value="jar:platform:/resource/Lightspeed/lib/ClientHolocore-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/HolocoreAdminPackets.jar"/>
<classpathentry kind="lib" path="lib/lz4-1.3.0.jar"/>
<classpathentry kind="lib" path="lib/ant/ant-launcher.jar"/>
<classpathentry kind="lib" path="lib/ant/ant.jar"/>
<classpathentry kind="lib" path="lib/PSWGCommon.jar"/>
<classpathentry kind="lib" path="lib/ant/ant-junit4.jar"/>
<classpathentry kind="lib" path="lib/ant/ant-testutil.jar"/>
<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
<classpathentry kind="lib" path="lib/junit-4.12.jar"/>
<classpathentry kind="lib" path="lib/nanohttpd-2.3.2-SNAPSHOT.jar"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -6,18 +6,18 @@
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@@ -1,91 +0,0 @@
<project name="Lightspeed" default="jar" basedir=".">
<description>
Standard Lightspeed Build File
</description>
<!-- set global properties for this build -->
<property name="src" location="${opdir}/src"/>
<property name="test" location="${opdir}/test"/>
<property name="bin" location="${opdir}/bin"/>
<property name="lib" location="${opdir}/lib"/>
<property name="dist" location="${bin}/dist"/>
<property name="name" value="ProjectSWG"/>
<property name="main.class" value="main.ProjectSWG"/>
<property name="jar" location="${dist}/${name}.jar"/>
<property name="ext-jar" location="${dist}/${name}-dependencies.jar"/>
<path id="ant.path">
<fileset dir="lib/ant/">
<include name="*.jar" />
</fileset>
<pathelement location="junit-4.12.jar"/>
</path>
<taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask" classpathref="ant.path" />
<target name="init">
<!-- Create the bin directory structure used by compile -->
<mkdir dir="${bin}"/>
</target>
<target name="compile" depends="init" description="Compile the sources">
<path id="classpath">
<pathelement path="${classpath}"/>
<fileset dir="${lib}" includes="**/*.jar" />
</path>
<!-- Compile sources -->
<javac srcdir="${src}" destdir="${bin}" includeantruntime="true" fork="true" debug="true">
<classpath refid="classpath" />
</javac>
<!-- Compile tests -->
<javac srcdir="${test}" destdir="${bin}" includeantruntime="true" fork="true" debug="true">
<classpath refid="classpath" />
</javac>
</target>
<target name="test" depends="compile" description="Test">
<junit printsummary="yes" haltonfailure="no" includeantruntime="true" fork="true" dir="${opdir}">
<classpath>
<pathelement location="${bin}" />
<pathelement location="hamcrest-core-1.3.jar" />
<pathelement location="junit-4.12.jar" />
<fileset dir="${lib}" includes="**/*.jar" />
</classpath>
<test name="main.TestAll" haltonfailure="no">
</test>
</junit>
</target>
<target name="jar" depends="compile" description="Create the JAR">
<!-- Create the distribution directory -->
<delete dir="${dist}" />
<mkdir dir="${dist}"/>
<!-- Create the classpath -->
<path id="classpath">
<fileset dir="${lib}" includes="**/*.jar" />
</path>
<pathconvert property="manifest.classpath" pathsep=" " refid="classpath">
<!-- Map it to a manifest-compatible string -->
<map from="${opdir}/" to=""/>
</pathconvert>
<jar jarfile="${ext-jar}">
<zipgroupfileset dir="${lib}">
<include name="**/*.jar"/>
</zipgroupfileset>
</jar>
<!-- Create the JAR -->
<jar destfile="${jar}" basedir="${bin}">
<fileset dir="${bin}" includes="**/*.class" />
<zipfileset src="${ext-jar}" excludes="META-INF/**/*" />
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
</manifest>
</jar>
<delete file="${ext-jar}" />
</target>
<target name="clean" description="Clean up">
<!-- Delete the ${bin} directory -->
<delete dir="${dist}"/>
<delete dir="${bin}"/>
</target>
</project>

64
build_frontend.gradle Normal file
View File

@@ -0,0 +1,64 @@
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'java'
mainClassName = 'com.projectswg.lightspeed_frontend.LightspeedFrontendGUI'
manifest {
attributes 'Main-Class': 'com.projectswg.lightspeed_frontend.LightspeedFrontendGUI'
}
sourceSets {
main {
java {
srcDirs = ['src']
includes ['**/*.java']
}
resources {
srcDirs = ['src']
includes = ['**/*.fxml', '**/*.css', '**/*.properties']
}
}
test {
java {
srcDirs = ['test']
}
}
}
test {
testLogging {
events "skipped", "failed"
}
afterSuite { TestDescriptor td, TestResult tr ->
println 'Tests run: ('+tr.getTestCount()+'), Failures: ('+tr.getFailedTestCount()+'), Errors: (0)'
}
include 'com/projectswg/lightspeed/TestLightspeed.class'
}
shadowJar{
archiveName = "LightspeedFrontend.${extension}"
}
dependencies {
compileOnly fileTree(dir: 'lib', include: ['*.jar'])
runtime fileTree(dir: 'lib_frontend', include: ['*.jar'])
}
repositories {
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
jcenter()
}
dependencies {
compile "org.gradle:gradle-tooling-api:3.3"
}
buildscript {
repositories {
maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.0'
}
}

56
build_server.gradle Normal file
View File

@@ -0,0 +1,56 @@
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'java'
mainClassName = 'com.projectswg.Lightspeed'
manifest {
attributes 'Main-Class': 'com.projectswg.Lightspeed'
}
sourceSets {
main {
java {
srcDirs = ['src']
}
}
test {
java {
srcDirs = ['test']
}
}
}
test {
testLogging {
events "skipped", "failed"
}
afterSuite { TestDescriptor td, TestResult tr ->
println 'Tests run: ('+tr.getTestCount()+'), Failures: ('+tr.getFailedTestCount()+'), Errors: (0)'
}
include 'com/projectswg/lightspeed/TestLightspeed.class'
}
shadowJar{
archiveName = "Lightspeed.${extension}"
}
dependencies {
compile fileTree(dir: 'lib', include: ['*.jar'])
}
repositories {
maven { url 'https://repo.gradle.org/gradle/libs-releases' }
jcenter()
}
dependencies {
compile "org.gradle:gradle-tooling-api:3.3"
}
buildscript {
repositories {
maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies { classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.0' }
}

Binary file not shown.

View File

@@ -30,6 +30,7 @@ package com.projectswg;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import com.projectswg.common.data.info.RelationalServerFactory;
import com.projectswg.common.debug.Log;
import com.projectswg.common.debug.Log.LogLevel;
import com.projectswg.common.debug.log_wrapper.ConsoleLogWrapper;
@@ -45,6 +46,7 @@ public class Lightspeed {
if (MAIN_THREAD.get() != null)
throw new IllegalStateException("Cannot run main() twice!");
Log.addWrapper(new ConsoleLogWrapper(LogLevel.VERBOSE));
RelationalServerFactory.setBasePath("data/");
MAIN_THREAD.set(Thread.currentThread());
LightspeedMainManager.setDataManager(new HeavyweightDataManager());
LightspeedMainManager.getDataManager().initialize();

View File

@@ -29,8 +29,8 @@ package com.projectswg;
import java.util.concurrent.atomic.AtomicBoolean;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.debug.Log;
import com.projectswg.common.info.Config;
import com.projectswg.common.info.ConfigFile;
import com.projectswg.common.info.LightweightDataManager;
import com.projectswg.lightspeed.LightspeedMainManager;

View File

@@ -28,7 +28,7 @@
package com.projectswg.common.control;
import com.projectswg.common.data.BackendData;
import com.projectswg.common.info.Config;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.info.ConfigFile;
import com.projectswg.common.info.DataManager;

View File

@@ -28,7 +28,7 @@
package com.projectswg.common.control;
import com.projectswg.common.data.BackendData;
import com.projectswg.common.info.Config;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.info.ConfigFile;
import com.projectswg.common.info.DataManager;

View File

@@ -34,9 +34,9 @@ import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.SQLBuildData.BuildInformationBuilder;
import com.projectswg.common.data.info.RelationalDatabase;
import com.projectswg.common.data.info.RelationalServerFactory;
import com.projectswg.common.debug.Log;
import com.projectswg.common.info.RelationalDatabase;
import com.projectswg.common.info.RelationalServerFactory;
import com.projectswg.lightspeed_frontend.data.SharedBuildData.BuildState;
class BuildHistoryTable implements AutoCloseable {
@@ -66,6 +66,7 @@ class BuildHistoryTable implements AutoCloseable {
this.getBuildByIdStatement = db.prepareStatement(GET_BUILD_BY_ID_SQL);
}
@Override
public void close() {
if (database != null)
database.close();

View File

@@ -34,9 +34,9 @@ import java.util.ArrayList;
import java.util.List;
import com.projectswg.common.data.SQLDeploymentData.DeploymentInformationBuilder;
import com.projectswg.common.data.info.RelationalDatabase;
import com.projectswg.common.data.info.RelationalServerFactory;
import com.projectswg.common.debug.Log;
import com.projectswg.common.info.RelationalDatabase;
import com.projectswg.common.info.RelationalServerFactory;
class DeploymentTable implements AutoCloseable {
@@ -54,6 +54,7 @@ class DeploymentTable implements AutoCloseable {
private final PreparedStatement getDeploymentsByServerStatement;
private final PreparedStatement getLastDeploymentStatement;
public DeploymentTable() {
this.database = RelationalServerFactory.getServerDatabase("lightspeed.db");
this.insertDeploymentStatement = database.prepareStatement(INSERT_DEPLOYMENT_SQL);
@@ -72,6 +73,7 @@ class DeploymentTable implements AutoCloseable {
this.getLastDeploymentStatement = db.prepareStatement(GET_LAST_DEPLOYMENT_SQL);
}
@Override
public void close() {
if (database != null)
database.close();

View File

@@ -32,8 +32,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.projectswg.common.info.RelationalDatabase;
import com.projectswg.common.info.RelationalServerFactory;
import com.projectswg.common.data.info.RelationalDatabase;
import com.projectswg.common.data.info.RelationalServerFactory;
import com.projectswg.lightspeed.build.ServerBuildData;
import com.projectswg.lightspeed.deployment.ServerDeploymentData;
import com.projectswg.lightspeed.server.ServerServerData;
@@ -48,18 +48,21 @@ public class HeavyweightBackendData implements BackendData {
loadServers();
}
@Override
public void insertBuild(ServerBuildData build) {
try (BuildHistoryTable buildTable = new BuildHistoryTable()) {
buildTable.insertBuildHistory(new SQLBuildData(build));
}
}
@Override
public void insertDeployment(ServerDeploymentData deployment) {
try (DeploymentTable deploymentTable = new DeploymentTable()) {
deploymentTable.insertDeployment(new SQLDeploymentData(deployment));
}
}
@Override
public List<ServerServerData> getServerList() {
List<ServerServerData> servers;
synchronized (serverMap) {
@@ -68,6 +71,7 @@ public class HeavyweightBackendData implements BackendData {
return servers;
}
@Override
public ServerServerData getServer(String serverId) {
synchronized (serverMap) {
ServerServerData server = serverMap.get(serverId);

View File

@@ -28,6 +28,7 @@
package com.projectswg.common.info;
import com.projectswg.common.data.BackendData;
import com.projectswg.common.data.info.Config;
public interface DataManager {

View File

@@ -35,6 +35,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import com.projectswg.common.data.BackendData;
import com.projectswg.common.data.HeavyweightBackendData;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.debug.Log;
import com.projectswg.common.debug.log_wrapper.FileLogWrapper;
@@ -49,6 +50,7 @@ public class HeavyweightDataManager implements DataManager {
initialized = new AtomicBoolean(false);
}
@Override
public synchronized void initialize() {
if (initialized.getAndSet(true))
return;
@@ -62,6 +64,7 @@ public class HeavyweightDataManager implements DataManager {
}
}
@Override
public synchronized void terminate() {
if (!initialized.getAndSet(false))
return;

View File

@@ -30,6 +30,8 @@ package com.projectswg.common.info;
import java.io.File;
import java.util.Map;
import com.projectswg.common.data.info.Config;
public class LightweightConfig extends Config {
public LightweightConfig(String filename) {
@@ -44,10 +46,12 @@ public class LightweightConfig extends Config {
super(file);
}
@Override
public Map<String, String> load() {
return null;
}
@Override
public boolean save() {
return true;
}

View File

@@ -32,6 +32,7 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import com.projectswg.common.data.LightweightBackendData;
import com.projectswg.common.data.info.Config;
public class LightweightDataManager implements DataManager {
@@ -45,12 +46,14 @@ public class LightweightDataManager implements DataManager {
configs = new HashMap<>();
}
@Override
public synchronized void initialize() {
if (initialized.getAndSet(true))
return;
setupConfigs();
}
@Override
public synchronized void terminate() {
if (!initialized.getAndSet(false))
return;

View File

@@ -29,9 +29,23 @@ package com.projectswg.common.network.packets;
import com.projectswg.common.debug.Log;
import com.projectswg.common.network.packets.connection.ConnectionProbePacket;
import com.projectswg.common.network.packets.post.*;
import com.projectswg.common.network.packets.request.*;
import com.projectswg.common.network.packets.response.*;
import com.projectswg.common.network.packets.post.PostBuildPacket;
import com.projectswg.common.network.packets.post.PostDeployPacket;
import com.projectswg.common.network.packets.post.PostResult;
import com.projectswg.common.network.packets.post.PostStopBuildPacket;
import com.projectswg.common.network.packets.post.PostStopDeployPacket;
import com.projectswg.common.network.packets.request.RequestBuildDetailedPacket;
import com.projectswg.common.network.packets.request.RequestBuildListPacket;
import com.projectswg.common.network.packets.request.RequestDeploymentDetailedPacket;
import com.projectswg.common.network.packets.request.RequestDeploymentListPacket;
import com.projectswg.common.network.packets.request.RequestServerDetailedPacket;
import com.projectswg.common.network.packets.request.RequestServerListPacket;
import com.projectswg.common.network.packets.response.ResponseBuildDetailedPacket;
import com.projectswg.common.network.packets.response.ResponseBuildListPacket;
import com.projectswg.common.network.packets.response.ResponseDeploymentDetailedPacket;
import com.projectswg.common.network.packets.response.ResponseDeploymentListPacket;
import com.projectswg.common.network.packets.response.ResponseServerDetailedPacket;
import com.projectswg.common.network.packets.response.ResponseServerListPacket;
import me.joshlarson.json.JSONObject;

View File

@@ -27,11 +27,11 @@
***********************************************************************************/
package com.projectswg.common.network.packets.connection;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public abstract class ConnectionPacket extends Packet {
public ConnectionPacket(JSONObject json, PacketType type) {

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.connection;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class ConnectionProbePacket extends ConnectionPacket {
public ConnectionProbePacket(JSONObject json) {

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.post;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class PostBuildPacket extends PostPacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.post;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class PostDeployPacket extends PostPacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,11 +27,11 @@
***********************************************************************************/
package com.projectswg.common.network.packets.post;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public abstract class PostPacket extends Packet {
public PostPacket(JSONObject json, PacketType type) {

View File

@@ -27,11 +27,11 @@
***********************************************************************************/
package com.projectswg.common.network.packets.post;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class PostResult extends Packet {
private static final String SUCCESS = "success";

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.post;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class PostStopBuildPacket extends PostPacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.post;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class PostStopDeployPacket extends PostPacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.request;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class RequestBuildDetailedPacket extends RequestPacket {
private static final String BUILD_ID = "build_id";

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.request;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class RequestBuildListPacket extends RequestPacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.request;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class RequestDeploymentDetailedPacket extends RequestPacket {
private static final String DEPLOYMENT_ID = "deployment_id";

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.request;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class RequestDeploymentListPacket extends RequestPacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,11 +27,11 @@
***********************************************************************************/
package com.projectswg.common.network.packets.request;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public abstract class RequestPacket extends Packet {
public RequestPacket(JSONObject json, PacketType type) {

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.request;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class RequestServerDetailedPacket extends RequestPacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,10 +27,10 @@
***********************************************************************************/
package com.projectswg.common.network.packets.request;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public class RequestServerListPacket extends RequestPacket {
public RequestServerListPacket(JSONObject json) {

View File

@@ -27,14 +27,14 @@
***********************************************************************************/
package com.projectswg.common.network.packets.response;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.data.TestDetails;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
import com.projectswg.lightspeed_frontend.data.SharedBuildData.BuildState;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import me.joshlarson.json.JSONObject;
public class ResponseBuildDetailedPacket extends ResponsePacket {
private static final String SERVER_ID = "server_id";

View File

@@ -30,13 +30,13 @@ package com.projectswg.common.network.packets.response;
import java.util.ArrayList;
import java.util.List;
import me.joshlarson.json.JSONArray;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import me.joshlarson.json.JSONArray;
import me.joshlarson.json.JSONObject;
public class ResponseBuildListPacket extends ResponsePacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,13 +27,13 @@
***********************************************************************************/
package com.projectswg.common.network.packets.response;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData.DeploymentState;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import me.joshlarson.json.JSONObject;
public class ResponseDeploymentDetailedPacket extends ResponsePacket {

View File

@@ -30,14 +30,14 @@ package com.projectswg.common.network.packets.response;
import java.util.ArrayList;
import java.util.List;
import me.joshlarson.json.JSONArray;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import me.joshlarson.json.JSONArray;
import me.joshlarson.json.JSONObject;
public class ResponseDeploymentListPacket extends ResponsePacket {
private static final String SERVER_ID = "server_id";

View File

@@ -27,11 +27,11 @@
***********************************************************************************/
package com.projectswg.common.network.packets.response;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.common.network.packets.PacketType;
import me.joshlarson.json.JSONObject;
public abstract class ResponsePacket extends Packet {
public ResponsePacket(JSONObject json, PacketType type) {

View File

@@ -27,11 +27,11 @@
***********************************************************************************/
package com.projectswg.common.network.packets.response;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import me.joshlarson.json.JSONObject;
public class ResponseServerDetailedPacket extends ResponsePacket {
private static final String SERVER_ID = "server_id";

View File

@@ -30,12 +30,12 @@ package com.projectswg.common.network.packets.response;
import java.util.ArrayList;
import java.util.List;
import me.joshlarson.json.JSONArray;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import me.joshlarson.json.JSONArray;
import me.joshlarson.json.JSONObject;
public class ResponseServerListPacket extends ResponsePacket {
private static final String SERVER_LIST = "server_list";

View File

@@ -56,22 +56,22 @@ import org.nanohttpd.protocols.http.response.Response;
import org.nanohttpd.protocols.http.response.Status;
import org.nanohttpd.protocols.http.threading.IAsyncRunner;
import resources.common.BCrypt;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
import com.projectswg.common.concurrency.PswgThreadPool;
import com.projectswg.common.control.LightspeedService;
import com.projectswg.common.data.CsvTable;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.debug.Assert;
import com.projectswg.common.debug.Log;
import com.projectswg.common.info.Config;
import com.projectswg.common.info.ConfigFile;
import com.projectswg.common.intents.RegisterHttpListenerIntent;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.common.network.packets.connection.ConnectionProbePacket;
import com.projectswg.lightspeed.communication.HttpResponder;
import me.joshlarson.json.JSONObject;
import resources.common.BCrypt;
public class CommunicationService extends LightspeedService {
private final NanoHTTPD httpServer;
@@ -84,6 +84,7 @@ public class CommunicationService extends LightspeedService {
public CommunicationService() {
this.httpServer = new NanoHTTPD(44444) {
@Override
public Response serve(IHTTPSession session) {
return CommunicationService.this.serve(session);
}

View File

@@ -30,6 +30,7 @@ package com.projectswg.lightspeed;
import java.io.File;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -38,13 +39,10 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import me.joshlarson.json.JSONObject;
import network.packets.swg.admin.AdminShutdownServer;
import com.projectswg.common.control.LightspeedService;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.debug.Assert;
import com.projectswg.common.debug.Log;
import com.projectswg.common.info.Config;
import com.projectswg.common.info.ConfigFile;
import com.projectswg.common.intents.LaunchStarshipIntent;
import com.projectswg.common.intents.RegisterHttpListenerIntent;
@@ -63,10 +61,13 @@ import com.projectswg.lightspeed.build.ServerBuildData;
import com.projectswg.lightspeed.deployment.ServerDeploymentData;
import com.projectswg.lightspeed.sequenced.SequencedStarter;
import com.projectswg.lightspeed.server.ServerServerData;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
import com.projectswg.lightspeed_frontend.data.SharedBuildData.BuildState;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData.DeploymentState;
import me.joshlarson.json.JSONObject;
import network.packets.swg.admin.AdminShutdownServer;
public class DeploymentService extends LightspeedService {
private final AtomicLong deploymentId;
@@ -305,14 +306,46 @@ public class DeploymentService extends LightspeedService {
File jar = new File("data"+File.separatorChar+"releases"+File.separatorChar+deployment.getServer().getName()+".jar");
File dir = new File(deployment.getServer().getDirectory());
String [] jvmArguments = deployment.getServer().getJvmArguments().split(" ");
String [] command = new String[3 + jvmArguments.length];
command[0] = java.getAbsolutePath();
System.arraycopy(jvmArguments, 0, command, 1, jvmArguments.length);
command[jvmArguments.length+1] = "-jar";
command[jvmArguments.length+2] = jar.getAbsolutePath();
String [] command = createStringArray(java.getAbsolutePath(), jvmArguments, "-jar", jar);
Log.d("Command: %s", Arrays.toString(command));
return StarshipProcess.create(dir, command);
}
private String [] createStringArray(Object ... objects) {
int size = 0;
for (Object o : objects) {
if (o instanceof String) {
if (!((String) o).isEmpty())
size++;
} else if (o instanceof String[]) {
for (String str : (String[]) o) {
if (!str.isEmpty())
size++;
}
} else if (o instanceof File) {
size++;
} else {
throw new IllegalArgumentException("Invalid argument: " + o);
}
}
String [] ret = new String[size];
int index = 0;
for (Object o : objects) {
if (o instanceof String) {
if (!((String) o).isEmpty())
ret[index++] = (String) o;
} else if (o instanceof File) {
ret[index++] = ((File) o).getAbsolutePath();
} else if (o instanceof String[]) {
for (String str : (String[]) o) {
if (!str.isEmpty())
ret[index++] = str;
}
}
}
return ret;
}
private void onDeploymentStarted(ServerDeploymentData deployment) {
deployment.setStartTime(TimeUtilities.getTime());
deployment.setDeploymentState(DeploymentState.RUNNING);

View File

@@ -30,7 +30,9 @@ package com.projectswg.lightspeed;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import com.projectswg.common.debug.Assert;
@@ -116,6 +118,17 @@ public class StarshipProcess {
}
public void gobbleOutput(ServerDeploymentData deployment) {
try (InputStream is = process.getInputStream()) {
byte [] buffer = new byte[256];
int bytes;
SharedDeploymentData sharedDeployment = deployment.getShared();
while ((bytes = is.read(buffer)) >= 0) {
sharedDeployment.appendOutput(new String(buffer, 0, bytes, StandardCharsets.UTF_8)); // gobble.
}
} catch (IOException e) {
if (Assert.debug() && (e.getMessage() == null || !e.getMessage().toLowerCase().contains("closed")))
Log.e(e);
}
try (BufferedReader gobbler = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
SharedDeploymentData sharedDeployment = deployment.getShared();

View File

@@ -39,11 +39,9 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.control.LightspeedService;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.debug.Log;
import com.projectswg.common.info.Config;
import com.projectswg.common.info.ConfigFile;
import com.projectswg.common.intents.LaunchStarshipIntent;
import com.projectswg.common.intents.PrepareStarshipIntent;
@@ -62,6 +60,8 @@ import com.projectswg.lightspeed.server.ServerServerData;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
import com.projectswg.lightspeed_frontend.data.SharedBuildData.BuildState;
import me.joshlarson.json.JSONObject;
public class BuildService extends LightspeedService {
private final AtomicLong buildId;
@@ -206,6 +206,7 @@ public class BuildService extends LightspeedService {
}
}
@Override
public void onCancelled(ServerBuildData build) {
removeInProgress();
Log.i("Build cancelled: %s", serverId);

View File

@@ -27,31 +27,34 @@
***********************************************************************************/
package com.projectswg.lightspeed.build;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.ProjectConnection;
import com.projectswg.common.data.TestDetails;
import com.projectswg.common.debug.Log;
import com.projectswg.common.utilities.TimeUtilities;
import com.projectswg.lightspeed.build.ServerBuildData.InstallationCallback;
import com.projectswg.lightspeed.build.java_builder.RepoInstaller;
import com.projectswg.lightspeed.server.ServerServerData;
import com.projectswg.lightspeed_frontend.data.SharedBuildData.BuildState;
public class JavaBuildMethod {
private static final Pattern JUNIT_PATTERN = Pattern.compile("Tests run: (\\d+), Failures: (\\d+), Errors: (\\d+).*$");
private static final String SEP = File.separator;
private static final Pattern JUNIT_PATTERN = Pattern.compile(".*Tests run: \\((\\d+)\\), Failures: \\((\\d+)\\).*", Pattern.DOTALL);
private final RepoInstaller installer;
private final ServerBuildData buildData;
private final InstallationCallback callback;
private final ProjectConnection connection;
public JavaBuildMethod(File jdk, ServerServerData serverData, ServerBuildData buildData, InstallationCallback callback) {
this.installer = new RepoInstaller(processRepositoryArgument(serverData.getDirectory()), jdk);
this.buildData = buildData;
this.callback = callback;
this.connection = GradleConnector.newConnector().forProjectDirectory(new File(serverData.getDirectory())).connect();
}
public void start() {
@@ -60,12 +63,6 @@ public class JavaBuildMethod {
}, "java-build-"+buildData.getId()).start();
}
private File processRepositoryArgument(String repo) {
if (repo.endsWith(SEP))
return new File(repo.substring(0, repo.length()-1));
return new File(repo);
}
private void createJar() {
try {
buildData.setTime(TimeUtilities.getTime());
@@ -85,8 +82,13 @@ public class JavaBuildMethod {
private boolean build() {
updateState(BuildState.COMPILING);
long start = System.nanoTime();
StringBuilder output = new StringBuilder("");
boolean success = installer.executeAnt("compile", output);
ByteArrayOutputStream output = new ByteArrayOutputStream();
boolean success = true;
try {
connection.newBuild().forTasks("compileJava").setStandardOutput(output).setStandardError(output).run();
} catch (Exception e) {
success = false;
}
buildData.setBuildString(output.toString());
buildData.setCompileTime((System.nanoTime() - start) / 1E6);
if (!success)
@@ -96,17 +98,21 @@ public class JavaBuildMethod {
private boolean test() {
updateState(BuildState.TESTING);
StringBuilder output = new StringBuilder("");
boolean success = installer.executeAnt("test", output);
Matcher m = JUNIT_PATTERN.matcher(output.substring(output.indexOf("Tests run"), output.indexOf("\n", output.indexOf("Tests run"))));
if (!m.matches()) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
boolean success = true;
try {
connection.newBuild().setJvmArguments("-Duser.dir="+buildData.getServer().getDirectory()).forTasks("cleanTest", "test").setStandardOutput(output).setStandardError(output).run();
} catch (Exception e) {
success = false;
System.err.println("Failed to match FAIL pattern: " + output);
buildData.setTestDetails(new TestDetails(0, 0));
} else {
buildData.setTestDetails(new TestDetails(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)) + Integer.parseInt(m.group(3))));
}
buildData.setTestString(output.toString());
String outputString = getOutputStreamString(output);
Matcher m = JUNIT_PATTERN.matcher(outputString);
if (m.matches())
buildData.setTestDetails(new TestDetails(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2))));
else
buildData.setTestDetails(new TestDetails(0, 0));
Log.d("Tests Completed. Total: %d Failed: %d", buildData.getTestDetails().getTotal(), buildData.getTestDetails().getFailures());
buildData.setTestString(outputString);
if (!success)
updateState(BuildState.TEST_FAILED);
return success && !detectCancelled(buildData, callback);
@@ -114,9 +120,26 @@ public class JavaBuildMethod {
private boolean install() {
updateState(BuildState.INSTALLING);
installer.executeAnt("jar", new StringBuilder(""));
buildData.setJar(installer.getJar());
return !detectCancelled(buildData, callback);
ByteArrayOutputStream output = new ByteArrayOutputStream();
boolean success = true;
try {
connection.newBuild().setJvmArguments("-Duser.dir="+buildData.getServer().getDirectory()).forTasks("shadowJar").setStandardOutput(output).setStandardError(output).run();
} catch (Exception e) {
success = false;
}
if (!success)
updateState(BuildState.INSTALL_FAILED);
buildData.setJar(new File(buildData.getServer().getDirectory(), "build/libs/Holocore.jar"));
return success && !detectCancelled(buildData, callback);
}
private String getOutputStreamString(ByteArrayOutputStream output) {
try {
return output.toString("ASCII");
} catch (UnsupportedEncodingException e) {
Log.e(e);
return "";
}
}
private boolean detectCancelled(ServerBuildData buildData, InstallationCallback callback) {

View File

@@ -31,13 +31,6 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import com.projectswg.common.debug.Log;
public class RepoInstaller {
@@ -166,36 +159,4 @@ public class RepoInstaller {
return files;
}
public boolean executeAnt(String target, StringBuilder output) {
File buildFile = new File("build.xml");
Project p = new Project();
ProjectHelper helper = ProjectHelper.getProjectHelper();
p.setProperty("java.home", getJdk().getAbsolutePath());
p.setUserProperty("ant.file", buildFile.getAbsolutePath());
p.setUserProperty("opdir", getRepo().getAbsolutePath());
p.init();
p.addReference("ant.projectHelper", helper);
helper.parse(p, buildFile);
p.addBuildListener(new BuildListener() {
public void taskStarted(BuildEvent arg0) { }
public void taskFinished(BuildEvent arg0) { }
public void targetStarted(BuildEvent arg0) { }
public void targetFinished(BuildEvent arg0) { }
public void buildStarted(BuildEvent arg0) { }
public void buildFinished(BuildEvent arg0) { }
@Override
public void messageLogged(BuildEvent arg0) {
if (arg0.getPriority() <= 2)
output.append(arg0.getMessage() + '\n');
}
});
try {
p.executeTarget(target);
return true;
} catch (Throwable t) {
Log.e(t);
return false;
}
}
}

View File

@@ -27,14 +27,14 @@
***********************************************************************************/
package com.projectswg.lightspeed.gui;
import javafx.application.Application;
import com.projectswg.Lightspeed;
import com.projectswg.common.concurrency.PswgBasicThread;
import com.projectswg.common.control.LightspeedService;
import com.projectswg.common.data.BackendData;
import com.projectswg.common.info.ConfigFile;
import javafx.application.Application;
public class GUIService extends LightspeedService {
private final PswgBasicThread guiThread;

View File

@@ -33,8 +33,8 @@ import java.util.Map;
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
import com.projectswg.common.utilities.TimeUtilities;
import com.projectswg.lightspeed.deployment.ServerDeploymentData;
import com.projectswg.lightspeed.build.ServerBuildData;
import com.projectswg.lightspeed.deployment.ServerDeploymentData;
import com.projectswg.lightspeed.gui.GUIService.GUIData;
import com.projectswg.lightspeed.server.ServerServerData;

View File

@@ -33,8 +33,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
import com.projectswg.common.control.LightspeedService;
import com.projectswg.common.debug.Log;
@@ -48,6 +46,8 @@ import com.projectswg.common.network.packets.response.ResponseServerListPacket;
import com.projectswg.lightspeed.git.GitInterface;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import me.joshlarson.json.JSONObject;
public class ServerService extends LightspeedService {
private final Set<ServerServerData> servers;

View File

@@ -31,14 +31,16 @@ import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.prefs.Preferences;
import com.projectswg.common.concurrency.PswgScheduledThreadPool;
import com.projectswg.common.concurrency.PswgThreadPool;
import com.projectswg.common.data.TestDetails;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.debug.Assert;
import com.projectswg.common.debug.Log;
import com.projectswg.common.info.Config;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.common.network.packets.request.RequestBuildDetailedPacket;
import com.projectswg.common.network.packets.request.RequestBuildListPacket;
@@ -60,10 +62,15 @@ import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import com.projectswg.lightspeed_frontend.intents.InboundPacketIntent;
import javafx.stage.Stage;
public class Frontend {
private final PswgThreadPool threadPool;
private final PswgScheduledThreadPool scheduledUpdater;
private final AtomicReference<Stage> primaryStage;
private final AtomicBoolean canSendRequestLatestBuild;
private final AtomicBoolean canSendRequestLatestDeployment;
private final FrontendCommunication communication;
private final FrontendData data;
private final Preferences preferences;
@@ -71,7 +78,11 @@ public class Frontend {
public Frontend() {
this.threadPool = new PswgThreadPool(5, "frontend-thread-pool");
this.threadPool.setInterruptOnStop(true);
this.scheduledUpdater = new PswgScheduledThreadPool(1, "frontend-updater");
this.primaryStage = new AtomicReference<>(null);
this.canSendRequestLatestBuild = new AtomicBoolean(true);
this.canSendRequestLatestDeployment = new AtomicBoolean(true);
this.data = new FrontendData();
File data = new File("cfg");
data.mkdirs();
@@ -85,7 +96,7 @@ public class Frontend {
public void setAddress(InetSocketAddress address) {
Log.i("Changing remote address to %s", address);
if (!address.equals(communication.getAddress())) {
if ((address != communication.getAddress() && (address == null || communication.getAddress() == null)) || !address.equals(communication.getAddress())) {
communication.setAddress(address);
Log.i("Clearing all frontend data - requesting complete reload");
data.clearAll();
@@ -93,12 +104,20 @@ public class Frontend {
}
}
public void setPrimaryStage(Stage stage) {
primaryStage.set(stage);
}
public Stage getPrimaryStage() {
return primaryStage.get();
}
public void start() {
Assert.test(communication.start());
threadPool.start();
scheduledUpdater.start();
scheduledUpdater.executeWithFixedDelay(0, 10000, () -> requestCompleteLoad());
scheduledUpdater.executeWithFixedDelay(3000, 3000, () -> requestLatestUpdates());
scheduledUpdater.executeWithFixedDelay(10000, 1000, () -> requestLatestUpdates());
}
public void stop() {
@@ -166,7 +185,7 @@ public class Frontend {
send(new RequestDeploymentListPacket(serverId), callback);
}
private void requestCompleteLoad() {
public void requestCompleteLoad() {
probeConnectivity(connected -> {
if (!connected) {
data.clearAll();
@@ -185,18 +204,21 @@ public class Frontend {
SharedServerData server = data.getSelectedServer();
if (server == null)
return;
SharedBuildData lastBuild = server.getLastBuild();
if (lastBuild != null && lastBuild.getBuildState().isInProgress()) {
loadBuildDetailed(lastBuild.getId(), null);
if (canSendRequestLatestBuild.getAndSet(false)) {
SharedBuildData lastBuild = server.getLastBuild();
if (lastBuild != null && lastBuild.getBuildState().isInProgress()) {
loadBuildDetailed(lastBuild.getId(), null);
}
}
SharedDeploymentData lastDeployment = server.getLastDeployment();
if (lastDeployment != null) {
loadDeploymentDetailed(lastDeployment.getId(), null);
if (canSendRequestLatestDeployment.getAndSet(false)) {
SharedDeploymentData lastDeployment = server.getLastDeployment();
if (lastDeployment != null) {
loadDeploymentDetailed(lastDeployment.getId(), null);
}
}
}
private void process(Packet packet) {
new InboundPacketIntent(packet).broadcast();
if (packet instanceof ResponseServerListPacket)
processServerList((ResponseServerListPacket) packet);
else if (packet instanceof ResponseServerDetailedPacket)
@@ -209,6 +231,7 @@ public class Frontend {
processDeploymentList((ResponseDeploymentListPacket) packet);
else if (packet instanceof ResponseDeploymentDetailedPacket)
processDeploymentDetailed((ResponseDeploymentDetailedPacket) packet);
new InboundPacketIntent(packet).broadcast();
}
private void processServerList(ResponseServerListPacket list) {
@@ -237,6 +260,7 @@ public class Frontend {
SharedBuildData last = server.getLastBuild();
for (SharedBuildData build : list.getBuildList()) {
if (server.getBuildData(build.getId()) == null) {
canSendRequestLatestBuild.set(true);
server.addBuild(build);
}
}
@@ -246,6 +270,7 @@ public class Frontend {
}
private void processBuildDetailed(ResponseBuildDetailedPacket detailed) {
canSendRequestLatestBuild.set(true);
SharedServerData server = data.getServer(detailed.getServerId());
SharedBuildData build = server.getBuildData(detailed.getBuildId());
if (build != null) {
@@ -265,6 +290,7 @@ public class Frontend {
SharedDeploymentData last = server.getLastDeployment();
for (SharedDeploymentData deployment : list.getDeploymentList()) {
if (server.getDeploymentData(deployment.getId()) == null) {
canSendRequestLatestDeployment.set(true);
server.addDeployment(deployment);
}
}
@@ -274,6 +300,7 @@ public class Frontend {
}
private void processDeploymentDetailed(ResponseDeploymentDetailedPacket detailed) {
canSendRequestLatestDeployment.set(true);
SharedServerData server = data.getServer(detailed.getServerId());
SharedDeploymentData deployment = server.getDeploymentData(detailed.getDeploymentId());
if (deployment != null) {

View File

@@ -27,14 +27,15 @@
***********************************************************************************/
package com.projectswg.lightspeed_frontend;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import com.projectswg.common.javafx.PSWGObjectProperty;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class FrontendData {
private final ObservableList<SharedServerData> servers;
@@ -54,6 +55,10 @@ public class FrontendData {
}
public void clearAll() {
if (!Platform.isFxApplicationThread()) {
Platform.runLater(() -> clearAll());
return;
}
servers.clear();
selectedServer.set(null);
selectedBuild.set(null);

View File

@@ -1,30 +1,6 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com * * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * Our goal is to create an emulator which will provide a server for players to * continue playing a game similar to the one they used to play. We are basing * it on the final publish of the game prior to end-game events. * * This file is part of Holocore. * * -------------------------------------------------------------------------------- * * Holocore is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * Holocore is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Holocore. If not, see <http://www.gnu.org/licenses/>. * *
***********************************************************************************/
package com.projectswg.lightspeed_frontend;
import java.io.File;
@@ -61,7 +37,7 @@ public class LightspeedFrontendGUI extends Application {
frontend.start();
}
public static void main(String [] args) {
public static void main(String[] args) {
ResourceUtilities.setPrimarySource(LightspeedFrontendGUI.class);
Log.addWrapper(new ConsoleLogWrapper(LogLevel.VERBOSE));
try {
@@ -75,7 +51,8 @@ public class LightspeedFrontendGUI extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
IntentManager.getInstance().initialize();
primaryView = (LightspeedPrimaryView) FXMLUtilities.loadFxml("PrimaryView.fxml", Locale.ENGLISH);
frontend.setPrimaryStage(primaryStage);
primaryView = (LightspeedPrimaryView) FXMLUtilities.loadFxmlAsClassResource("PrimaryView.fxml", Locale.ENGLISH);
Parent root = primaryView.getRoot();
primaryStage.setTitle("Lightspeed Frontend");
primaryStage.setScene(new Scene(root));
@@ -85,6 +62,7 @@ public class LightspeedFrontendGUI extends Application {
primaryStage.setOnCloseRequest((we) -> {
close(we);
primaryStage.close();
System.exit(0);
});
}

View File

@@ -38,9 +38,22 @@ import com.projectswg.common.debug.Log;
import com.projectswg.common.debug.Log.LogLevel;
import com.projectswg.common.debug.log_wrapper.ConsoleLogWrapper;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.common.network.packets.post.*;
import com.projectswg.common.network.packets.request.*;
import com.projectswg.common.network.packets.response.*;
import com.projectswg.common.network.packets.post.PostBuildPacket;
import com.projectswg.common.network.packets.post.PostDeployPacket;
import com.projectswg.common.network.packets.post.PostStopBuildPacket;
import com.projectswg.common.network.packets.post.PostStopDeployPacket;
import com.projectswg.common.network.packets.request.RequestBuildDetailedPacket;
import com.projectswg.common.network.packets.request.RequestBuildListPacket;
import com.projectswg.common.network.packets.request.RequestDeploymentDetailedPacket;
import com.projectswg.common.network.packets.request.RequestDeploymentListPacket;
import com.projectswg.common.network.packets.request.RequestPacket;
import com.projectswg.common.network.packets.request.RequestServerDetailedPacket;
import com.projectswg.common.network.packets.request.RequestServerListPacket;
import com.projectswg.common.network.packets.response.ResponseBuildDetailedPacket;
import com.projectswg.common.network.packets.response.ResponseBuildListPacket;
import com.projectswg.common.network.packets.response.ResponseDeploymentDetailedPacket;
import com.projectswg.common.network.packets.response.ResponseDeploymentListPacket;
import com.projectswg.common.network.packets.response.ResponseServerListPacket;
import com.projectswg.common.utilities.TimeUtilities;
import com.projectswg.lightspeed_frontend.communication.FrontendCommunication;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;

View File

@@ -27,14 +27,12 @@
***********************************************************************************/
package com.projectswg.lightspeed_frontend.communication;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.prefs.Preferences;
import com.projectswg.common.debug.Assert;
import com.projectswg.common.debug.Log;
import com.projectswg.common.info.Config;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.lightspeed_frontend.Frontend;
@@ -49,14 +47,6 @@ public class FrontendCommunication {
this.frontend = frontend;
this.running = new AtomicBoolean(false);
this.callback = null;
Config config = frontend.getConfig();
if (config.getBoolean("SECURITY", false)) {
String keystore = config.getString("KEYSTORE", "");
if (!keystore.isEmpty()) {
HttpClient.setupSSL(new File(keystore), config.getString("KEYSTORE-PASS", ""));
HttpClient.setupUserPass(config.getString("USERNAME", ""), config.getString("PASSWORD", ""));
}
}
Preferences comm = frontend.getPreferences().node("communication");
this.address = new InetSocketAddress(comm.get("inet-addr", "localhost"), comm.getInt("inet-port", 44444));
}
@@ -71,8 +61,13 @@ public class FrontendCommunication {
public void setAddress(InetSocketAddress address) {
Preferences comm = frontend.getPreferences().node("communication");
comm.put("inet-addr", address.getHostString());
comm.putInt("inet-port", address.getPort());
if (address == null) {
comm.remove("inet-addr");
comm.remove("inet-port");
} else {
comm.put("inet-addr", address.getHostString());
comm.putInt("inet-port", address.getPort());
}
this.address = address;
}

View File

@@ -37,6 +37,7 @@ import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@@ -49,11 +50,9 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManagerFactory;
import me.joshlarson.json.JSON;
import me.joshlarson.json.JSONObject;
import com.projectswg.common.debug.Log;
import com.projectswg.common.network.packets.Packet;
import com.projectswg.common.network.packets.PacketType;
@@ -62,6 +61,9 @@ import com.projectswg.common.network.packets.connection.ConnectionProbePacket;
import com.projectswg.common.network.packets.post.PostPacket;
import com.projectswg.common.network.packets.request.RequestPacket;
import me.joshlarson.json.JSON;
import me.joshlarson.json.JSONObject;
public class HttpClient {
private static final AtomicBoolean SSL = new AtomicBoolean(false);
@@ -69,6 +71,10 @@ public class HttpClient {
private static final AtomicReference<String> PASSWORD = new AtomicReference<>("");
public static void setupSSL(File keystoreFile, String password) {
if (keystoreFile == null || password == null) {
SSL.set(false);
return;
}
try {
InputStream keystoreStream = new FileInputStream(keystoreFile);
char[] trustPassword = password.toCharArray();
@@ -95,6 +101,10 @@ public class HttpClient {
PASSWORD.set(pass);
}
public static boolean isSSLEnabled() {
return SSL.get();
}
public static boolean probeConnection(InetSocketAddress address) {
return requestPacket(address, new ConnectionProbePacket()) != null;
}
@@ -111,9 +121,18 @@ public class HttpClient {
}
PacketType type = PacketType.valueOf(obj.getString("type"));
return Packet.inflate(obj, type);
} catch (SSLHandshakeException e) {
Log.w("SSL failed to %s", address);
return null;
} catch (ConnectException e) {
Log.w("Failed to connect to %s", address);
return null;
} catch (SocketException e) {
if (e.getMessage() != null && e.getMessage().contains("end of file"))
Log.w("HTTP failed to %s", address);
else
Log.e(e);
return null;
} catch (IOException e) {
Log.e(e);
}
@@ -123,25 +142,32 @@ public class HttpClient {
public static String requestString(InetSocketAddress address, Packet packet) throws IOException {
URL url = new URL(generateURL(address, packet));
HttpURLConnection con = (HttpURLConnection) url.openConnection();
if (SSL.get()) {
String encoded = Base64.getEncoder().encodeToString((USERNAME.get()+":"+PASSWORD.get()).getBytes(StandardCharsets.UTF_8));
con.setRequestProperty("Authorization", "Basic "+encoded);
}
con.setRequestMethod((packet instanceof PostPacket) ? "POST" : "GET");
con.setRequestProperty("User-Agent", "LightspeedFrontend");
int responseCode = con.getResponseCode();
if (responseCode != 200)
return "RESPONSE CODE " + responseCode;
return readResponse(con);
}
private static String readResponse(HttpURLConnection connection) throws IOException {
StringBuilder response = new StringBuilder("");
try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
InputStream inputStream = connection.getInputStream();
try (BufferedReader in = new BufferedReader(new InputStreamReader(inputStream))) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
}
int responseCode = connection.getResponseCode();
inputStream.close();
if (responseCode != 200)
return "RESPONSE CODE " + responseCode;
return response.toString();
}

View File

@@ -33,7 +33,7 @@ public class SharedDeploymentData {
private SharedBuildData build;
private long startTime;
private long endTime;
private String output;
private StringBuilder output;
private DeploymentState state;
public SharedDeploymentData(long id, SharedBuildData build) {
@@ -41,7 +41,7 @@ public class SharedDeploymentData {
this.build = build;
this.startTime = 0;
this.endTime = 0;
this.output = "";
this.output = new StringBuilder("");
this.state = DeploymentState.CREATED;
}
@@ -68,7 +68,7 @@ public class SharedDeploymentData {
}
public String getOutput() {
return output;
return output.toString();
}
public DeploymentState getDeploymentState() {
@@ -88,21 +88,24 @@ public class SharedDeploymentData {
}
public void setOutput(String output) {
this.output = output;
this.output.setLength(0);
this.output.append(output);
}
public void appendOutput(String line) {
this.output += line + '\n';
this.output.append(line);
}
public void setDeploymentState(DeploymentState state) {
this.state = state;
}
@Override
public int hashCode() {
return Long.hashCode(id);
}
@Override
public boolean equals(Object o) {
if (o == null)
return false;
@@ -111,6 +114,7 @@ public class SharedDeploymentData {
return ((SharedDeploymentData) o).getId() == id;
}
@Override
public String toString() {
return String.format("SharedDeploymentData[id=%d, build=%d, server=%s, start_time=%d, end_time=%d]", id, getBuild().getId(), getServer().getName(), startTime, endTime);
}

View File

@@ -40,6 +40,11 @@
<fx:include source="primary_tabs/Deployment.fxml" />
</content>
</Tab>
<Tab text="Settings">
<content>
<fx:include source="primary_tabs/Settings.fxml" />
</content>
</Tab>
</tabs>
</TabPane>
</VBox>

View File

@@ -45,6 +45,7 @@
<Label fx:id="statusText" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label fx:id="startTimeText" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Label fx:id="uptimeText" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<Button fx:id="logDownloadButton" GridPane.columnIndex="1" GridPane.rowIndex="7" text="Download" />
</GridPane>
<TextArea fx:id="logTextArea" styleClass="log" editable="false" maxHeight="Infinity" VBox.vgrow="ALWAYS" />
</VBox>

View File

@@ -0,0 +1,22 @@
.white-label {
-fx-text-fill: #FFFFFF;
}
.red-label {
-fx-text-fill: #ff1e1e;
}
.green-label {
-fx-text-fill: #04ff00;
}
.log {
-fx-text-fill: #FFFFFF;
}
.log .content {
-fx-background: #3F4042;
-fx-background-color: #3F4042;
-fx-border-color: white;
-fx-border-width: 1 0 1 0;
}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import javafx.scene.web.*?>
<?import javafx.scene.effect.*?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.*?>
<?import java.net.URL?>
<GridPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:id="rootSettings" stylesheets="@Settings.css" fx:controller="com.projectswg.lightspeed_frontend.gui.primary_tabs.SettingsTab">
<padding>
<Insets top="5.0" left="5.0" right="5.0" bottom="5.0" />
</padding>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="200.0" minWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="NEVER" prefHeight="40" />
<RowConstraints vgrow="NEVER" prefHeight="40" />
<RowConstraints vgrow="NEVER" prefHeight="40" />
<RowConstraints vgrow="NEVER" prefHeight="40" />
<RowConstraints vgrow="NEVER" prefHeight="40" />
</rowConstraints>
<Label text="Security:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="0" />
<Label text="Keystore:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="1" />
<Label text="Keystore Pass:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="2" />
<Label text="Username:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="3" />
<Label text="Password:" styleClass="white-label" GridPane.columnIndex="0" GridPane.rowIndex="4" />
<CheckBox fx:id="securityCheckBox" GridPane.columnIndex="1" GridPane.rowIndex="0" />
<Button fx:id="keystoreButton" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<PasswordField fx:id="keystorePasswordTextField" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<TextField fx:id="usernameTextField" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<PasswordField fx:id="passwordTextField" GridPane.columnIndex="1" GridPane.rowIndex="4" />
</GridPane>

View File

@@ -29,6 +29,10 @@ package com.projectswg.lightspeed_frontend.gui;
import java.awt.Color;
import javax.swing.UIManager;
import com.projectswg.common.debug.Log;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
@@ -44,10 +48,6 @@ import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javax.swing.UIManager;
import com.projectswg.common.debug.Log;
public class InternalWindow extends Region {

View File

@@ -97,9 +97,9 @@ public class LightspeedPrimaryView implements FXMLController {
@Override
public void initialize(URL location, ResourceBundle resources) {
FXMLUtilities.onFxmlLoaded(this);
FXMLUtilities.loadFxml("primary_tabs/General.fxml", Locale.ENGLISH);
FXMLUtilities.loadFxml("primary_tabs/Build.fxml", Locale.ENGLISH);
FXMLUtilities.loadFxml("primary_tabs/Deployment.fxml", Locale.ENGLISH);
FXMLUtilities.loadFxmlAsClassResource("primary_tabs/General.fxml", Locale.ENGLISH);
FXMLUtilities.loadFxmlAsClassResource("primary_tabs/Build.fxml", Locale.ENGLISH);
FXMLUtilities.loadFxmlAsClassResource("primary_tabs/Deployment.fxml", Locale.ENGLISH);
ipAddressText.setText(frontend.getCommunication().getAddress().getHostString());
portText.setText(Integer.toString(frontend.getCommunication().getAddress().getPort()));
validIpRegion.setBackground(validIpBackground);

View File

@@ -42,8 +42,8 @@ import com.projectswg.common.utilities.TimeUtilities;
import com.projectswg.lightspeed_frontend.Frontend;
import com.projectswg.lightspeed_frontend.LightspeedFrontendGUI;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import com.projectswg.lightspeed_frontend.data.SharedBuildData.BuildState;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import com.projectswg.lightspeed_frontend.intents.InboundPacketIntent;
import javafx.application.Platform;

View File

@@ -27,11 +27,17 @@
***********************************************************************************/
package com.projectswg.lightspeed_frontend.gui.primary_tabs;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import com.projectswg.common.concurrency.PswgScheduledThreadPool;
import com.projectswg.common.control.IntentManager;
import com.projectswg.common.debug.Log;
@@ -50,6 +56,7 @@ import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
@@ -76,6 +83,8 @@ public class DeploymentTab implements FXMLController {
@FXML
private Label uptimeText;
@FXML
private Button logDownloadButton;
@FXML
private TextArea logTextArea;
private final PswgScheduledThreadPool scheduledUpdater;
@@ -116,6 +125,7 @@ public class DeploymentTab implements FXMLController {
frontend.loadDeploymentDetailed(val.getId(), response -> Platform.runLater(() -> updateDeploymentDetails()));
}
});
logDownloadButton.setOnAction(eh -> downloadLog());
IntentManager.getInstance().registerForIntent(InboundPacketIntent.class, ipi -> Platform.runLater(() -> updateDeploymentList(false)));
this.frontend.getData().getSelectedServerProperty().addListener((val, prev, next) -> Platform.runLater(() -> updateDeploymentList(true)));
updateDeploymentList(true);
@@ -249,7 +259,7 @@ public class DeploymentTab implements FXMLController {
double pos = logTextArea.getScrollTop();
int anchor = logTextArea.getAnchor();
int caret = logTextArea.getCaretPosition();
logTextArea.setText(selectedDeployment.getOutput());
logTextArea.setText(tail(selectedDeployment.getOutput(), 100));
if (anchor != caret) {
logTextArea.setScrollTop(pos);
logTextArea.selectRange(anchor, caret);
@@ -259,18 +269,49 @@ public class DeploymentTab implements FXMLController {
}
}
private void downloadLog() {
SharedDeploymentData selectedDeployment = frontend.getData().getSelectedDeployment();
if (selectedDeployment == null || selectedDeployment.getStartTime() == 0) {
// TODO: Simple little popup saying cannot download
} else {
try (FileOutputStream fos = new FileOutputStream(createDownloadLogFile(selectedDeployment))) {
fos.write(selectedDeployment.getOutput().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
Log.e(e);
}
}
}
private File createDownloadLogFile(SharedDeploymentData selectedDeployment) {
String folder = ".";
String time = new SimpleDateFormat("MMdd-HH:mm:ss").format(System.currentTimeMillis());
return new File(folder, String.format("deployment-log-ID%d-TIME%s.log", selectedDeployment.getId(), time));
}
private String tail(String str, int n) {
int index = str.length();
for (int i = 0; i < n && index > 0; i++) {
index = str.lastIndexOf('\n', index-1);
}
if (index <= 0)
return str;
return str.substring(index);
}
public interface SelectedDeploymentChangedCallback {
void onDeploymentChanged(SharedDeploymentData deployment);
}
private class DeploymentStringConverter extends StringConverter<SharedDeploymentData> {
@Override
public String toString(SharedDeploymentData deployment) {
if (deployment == NULL_DEPLOY)
return "latest";
return "D " + deployment.getId() + " - B " + deployment.getBuild().getId();
}
@Override
public SharedDeploymentData fromString(String string) {
if (string.isEmpty() || string.equals("latest"))
return NULL_DEPLOY;

View File

@@ -0,0 +1,203 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.lightspeed_frontend.gui.primary_tabs;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import com.projectswg.common.debug.Log;
import com.projectswg.common.javafx.FXMLController;
import com.projectswg.common.javafx.FXMLUtilities;
import com.projectswg.lightspeed_frontend.Frontend;
import com.projectswg.lightspeed_frontend.LightspeedFrontendGUI;
import com.projectswg.lightspeed_frontend.communication.HttpClient;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.FileChooser;
public class SettingsTab implements FXMLController {
private static final String DEFAULT_KEYSTORE_PATH = "No Keystore Defined";
@FXML
private Parent rootSettings;
@FXML
private CheckBox securityCheckBox;
@FXML
private Button keystoreButton;
@FXML
private PasswordField keystorePasswordTextField;
@FXML
private TextField usernameTextField;
@FXML
private PasswordField passwordTextField;
private final Frontend frontend;
public SettingsTab() {
this.frontend = LightspeedFrontendGUI.FRONTEND;
}
@Override
public Parent getRoot() {
return rootSettings;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
FXMLUtilities.onFxmlLoaded(this);
loadSettings();
updateAccountInformation();
updateKeystore();
keystoreButton.setOnAction(e -> setKeystorePathPopup());
securityCheckBox.selectedProperty().addListener(l -> updateKeystore());
keystoreButton.textProperty().addListener(l -> updateKeystore());
keystorePasswordTextField.textProperty().addListener(l -> updateKeystore());
usernameTextField.textProperty().addListener(l -> updateAccountInformation());
passwordTextField.textProperty().addListener(l -> updateAccountInformation());
}
@Override
public void terminate() {
saveSettings();
}
private void updateKeystore() {
saveSettings();
if (!isSecure()) {
HttpClient.setupSSL(null, null);
frontend.requestCompleteLoad();
return;
}
String path = getKeystorePath();
String pass = getKeystorePassword();
File keystore = new File(path);
if (path.isEmpty() || !keystore.isFile()) {
HttpClient.setupSSL(null, null);
frontend.requestCompleteLoad();
Log.w("Invalid keystore file: '%s'", path);
return;
}
HttpClient.setupSSL(keystore, pass);
frontend.requestCompleteLoad();
}
private void updateAccountInformation() {
saveSettings();
HttpClient.setupUserPass(getUsername(), getPassword());
if (HttpClient.isSSLEnabled())
frontend.requestCompleteLoad();
}
private boolean isSecure() {
return securityCheckBox.isSelected();
}
private String getKeystorePath() {
String path = keystoreButton.getText();
if (path.equals(DEFAULT_KEYSTORE_PATH))
return "";
return path;
}
private String getKeystorePassword() {
return keystorePasswordTextField.getText();
}
private String getUsername() {
return usernameTextField.getText();
}
private String getPassword() {
return passwordTextField.getText();
}
private void setSecure(boolean secure) {
securityCheckBox.setSelected(secure);
}
private void setKeystorePath(String path) {
if (path.isEmpty())
keystoreButton.setText(DEFAULT_KEYSTORE_PATH);
else
keystoreButton.setText(path);
}
private void setKeystorePassword(String pass) {
keystorePasswordTextField.setText(pass);
}
private void setUsername(String username) {
usernameTextField.setText(username);
}
private void setPassword(String password) {
passwordTextField.setText(password);
}
private void loadSettings() {
Preferences settings = frontend.getPreferences().node("settings");
setSecure(settings.getBoolean("SECURE", false));
setKeystorePath(settings.get("KEYSTORE-PATH", ""));
setKeystorePassword(settings.get("KEYSTORE-PASS", ""));
setUsername(settings.get("USERNAME", ""));
setPassword(settings.get("PASSWORD", ""));
}
private void saveSettings() {
Preferences settings = frontend.getPreferences().node("settings");
settings.putBoolean("SECURE", isSecure());
settings.put("KEYSTORE-PATH", getKeystorePath());
settings.put("KEYSTORE-PASS", getKeystorePassword());
settings.put("USERNAME", getUsername());
settings.put("PASSWORD", getPassword());
try {
settings.flush();
} catch (BackingStoreException e) {
Log.e(e);
}
}
private void setKeystorePathPopup() {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Set the keystore path");
File file = fileChooser.showOpenDialog(frontend.getPrimaryStage());
if (file == null || !file.isFile())
return;
setKeystorePath(file.getAbsolutePath());
}
}

View File

@@ -1,40 +0,0 @@
/***********************************************************************************
* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
* Our goal is to create an emulator which will provide a server for players to *
* continue playing a game similar to the one they used to play. We are basing *
* it on the final publish of the game prior to end-game events. *
* *
* This file is part of Holocore. *
* *
* -------------------------------------------------------------------------------- *
* *
* Holocore is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* Holocore is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
* *
***********************************************************************************/
package com.projectswg.lightspeed;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
})
public class TestLightspeed {
}